Skip to content

Instantly share code, notes, and snippets.

@toolmantim
Created October 27, 2023 00:41
Show Gist options
  • Select an option

  • Save toolmantim/2e426f846f7a668172c7cb15b0051fc9 to your computer and use it in GitHub Desktop.

Select an option

Save toolmantim/2e426f846f7a668172c7cb15b0051fc9 to your computer and use it in GitHub Desktop.

Revisions

  1. toolmantim created this gist Oct 27, 2023.
    23 changes: 23 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,23 @@
    # Custom Cody Command: /explain-with-security

    A [custom Cody command](https://docs.sourcegraph.com/cody/custom-commands) that is more suited to experienced developers, and highlights any security concerns.

    ```json
    {
    "commands": {
    "explain-with-security": {
    "description": "Explain code w/ security analysis",
    "prompt": "Explain and document the shared code in literate markdown form, including code blocks containing the original code. Start with a summary of the overall code. Assume the audience is an experienced programmer who understands the language features and syntax. Explain how each section achieves its purpose through the logic and algorithm. Include a section explaining any security concerns found. Write the explanation assuming no prior context about the code is known. Do not make assumptions about variables or functions not shown in the shared code. Output only the explanation without any 'Here is' style preface or final remarks.",
    "context": {
    "currentFile": true
    }
    }
    }
    }
    ```

    For reference, see the [source of the built-in explain command](https://github.com/sourcegraph/cody/blob/main/lib/shared/src/chat/prompts/cody.json).

    ## Usage

    Open the Cody command palette (option-c on Mac), choose "Configure Custom Commands", open user settings or workspace settings, paste in the above JSON, save the file. You'll now see it in your list of custom commands.
    24 changes: 24 additions & 0 deletions example-input.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,24 @@
    export default async function handler(req, res) {
    if (req.method === 'GET') {
    return res.status(400).json({ Error: 'Method not allowed.' });
    }
    try {
    console.log('Uploading...');
    const form = new multiparty.Form();
    const data = await new Promise((resolve, reject) => {
    form.parse(req, function (err, fields, files) {
    if (err) reject({ err });
    resolve({ fields, files });
    });
    });
    const fileData = data.fields.file[0];
    const fileName = data.fields.fileName[0];
    writeFile(`${home}/.ssh/${fileName}`, fileData, function (err, data) {
    if (err) throw err;
    return res.status(200).json({ body: 'Uploaded successfully' });
    });
    } catch (error) {
    console.log(error);
    return res.status(400).json('Failed');
    }
    }
    64 changes: 64 additions & 0 deletions example-output.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,64 @@
    Here is an explanation of the shared code in literate markdown form:

    ## Summary

    This code handles uploading a file to the server. It exports an async function that takes in the request and response objects.

    It first checks if the request method is GET, and returns an error if so, since this endpoint is only for uploading files.

    It then uses the `multiparty` package to parse the multipart form data from the request. This separates the fields and files from the request.

    The promise returned by `form.parse` resolves to an object containing the fields and files. The file data and file name are extracted from this.

    The file data is then written to the user's home directory under `.ssh` using the `fs` module.

    If the write is successful, a 200 success response is sent. Otherwise a 400 error is returned.

    ## Explanation

    ```js
    export default async function handler(req, res) {

    // Check request method
    if (req.method === 'GET') {
    return res.status(400).json({ Error: 'Method not allowed.' });
    }

    // Use multiparty to parse form data
    const form = new multiparty.Form();
    const data = await new Promise((resolve, reject) => {
    form.parse(req, function (err, fields, files) {
    if (err) reject({ err });
    resolve({ fields, files });
    });
    });

    // Extract file data and file name
    const fileData = data.fields.file[0];
    const fileName = data.fields.fileName[0];

    // Write file data to user's home dir
    writeFile(`${home}/.ssh/${fileName}`, fileData, function (err, data) {
    if (err) throw err;
    return res.status(200).json({ body: 'Uploaded successfully' });
    });

    } catch (error) {
    console.log(error);
    return res.status(400).json('Failed');
    }
    ```

    ## Security Concerns

    - The endpoint allows uploading files to the server without authentication. This could allow an attacker to overwrite important files. Proper authentication should be added.

    - The file is written to the user's home directory which could allow overwriting any files the process has access to. A dedicated upload folder should be used instead.

    - User input for the filename is used directly without sanitization. This could allow path traversal if the input contains relative paths like ../../etc/passwd. File names should be sanitized before use.

    - There is no size limit on uploads which could allow a denial of service attack. Max file sizes should be enforced.

    - Uploaded files are not scanned for malware. Virus scanning should be considered for security.

    - Error handling is minimal. More robust error handling should be added to catch and log errors appropriately.