Skip to content

Assistant sqli fix suggestion#1

Open
stuartcmehrens wants to merge 1 commit intomasterfrom
update-product-search
Open

Assistant sqli fix suggestion#1
stuartcmehrens wants to merge 1 commit intomasterfrom
update-product-search

Conversation

@stuartcmehrens
Copy link

No description provided.

return (req: Request, res: Response, next: NextFunction) => {
let criteria: any = req.query.q === 'undefined' ? '' : req.query.q ?? ''
criteria = (criteria.length <= 200) ? criteria : criteria.substring(0, 200)
models.sequelize.query("SELECT * FROM Products WHERE ((name LIKE '%"+criteria+"%' OR description LIKE '%"+criteria+"%') AND deletedAt IS NULL) ORDER BY name")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Detected a sequelize statement that is tainted by user-input. This could lead to SQL injection if the variable is user-controlled and is not properly sanitized. In order to prevent SQL injection, it is recommended to use parameterized queries or prepared statements.

View Dataflow Graph
flowchart LR
    classDef invis fill:white, stroke: none
    classDef default fill:#e7f5ff, color:#1c7fd6, stroke: none

    subgraph File0["<b>src/assistant-fix-sqli-sequelize.ts</b>"]
        direction LR
        %% Source

        subgraph Source
            direction LR

            v0["<a href=https://github.com/Semgrep-Demo/sharpcompress/blob/040ef9505cbd34b360de29a840059d1d20b8877c/src/assistant-fix-sqli-sequelize.ts#L3 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 3] req.query</a>"]
        end
        %% Intermediate

        subgraph Traces0[Traces]
            direction TB

            v2["<a href=https://github.com/Semgrep-Demo/sharpcompress/blob/040ef9505cbd34b360de29a840059d1d20b8877c/src/assistant-fix-sqli-sequelize.ts#L3 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 3] criteria</a>"]
        end
        %% Sink

        subgraph Sink
            direction LR

            v1["<a href=https://github.com/Semgrep-Demo/sharpcompress/blob/040ef9505cbd34b360de29a840059d1d20b8877c/src/assistant-fix-sqli-sequelize.ts#L5 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 5] &quot;SELECT * FROM Products WHERE ((name LIKE &apos;%&quot;+criteria+&quot;%&apos; OR description LIKE &apos;%&quot;+criteria+&quot;%&apos;) AND deletedAt IS NULL) ORDER BY name&quot;</a>"]
        end
    end
    %% Class Assignment
    Source:::invis
    Sink:::invis

    Traces0:::invis
    File0:::invis

    %% Connections

    Source --> Traces0
    Traces0 --> Sink

Loading
Ignore this finding from express-sequelize-injection.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep Assistant suggests the following fix: Use parameterized queries with Sequelize to prevent SQL injection.

View step-by-step instructions
  1. Change the SQL query string to use parameterized query syntax. Replace the dynamic values with placeholders.

    const query = "SELECT * FROM Products WHERE ((name LIKE :criteria OR description LIKE :criteria) AND deletedAt IS NULL) ORDER BY name";
  2. Pass the dynamic values as a second parameter to the sequelize.query method in an object.

    models.sequelize.query(query, {
      replacements: { criteria: `%${criteria}%` }
    })
  3. Replace the original query execution with the updated parameterized query.

    models.sequelize.query(query, {
      replacements: { criteria: `%${criteria}%` }
    })
    .then(([products]: any) => {
      const dataString = JSON.stringify(products)
      for (let i = 0; i < products.length; i++) {
        products[i].name = req.__(products[i].name)
        products[i].description = req.__(products[i].description)
      }
      res.json(utils.queryResultToJson(products))
    }).catch((error: ErrorWithParent) => {
      next(error.parent)
    })

Using parameterized queries helps prevent SQL injection by ensuring that user input is treated as data rather than executable code.

This code change should be a good starting point:

Suggested change
models.sequelize.query("SELECT * FROM Products WHERE ((name LIKE '%"+criteria+"%' OR description LIKE '%"+criteria+"%') AND deletedAt IS NULL) ORDER BY name")
models.sequelize.query(
"SELECT * FROM Products WHERE ((name LIKE :criteria OR description LIKE :criteria) AND deletedAt IS NULL) ORDER BY name",
{
replacements: { criteria: `%${criteria}%` },
type: models.sequelize.QueryTypes.SELECT
}
)

AI-generated comment. Please review the response carefully and leave feedback in the form of a 👍 or 👎 reaction

return (req: Request, res: Response, next: NextFunction) => {
let criteria: any = req.query.q === 'undefined' ? '' : req.query.q ?? ''
criteria = (criteria.length <= 200) ? criteria : criteria.substring(0, 200)
models.sequelize.query("SELECT * FROM Products WHERE ((name LIKE '%"+criteria+"%' OR description LIKE '%"+criteria+"%') AND deletedAt IS NULL) ORDER BY name")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Detected user input used to manually construct a SQL string. This is usually bad practice because manual construction could accidentally result in a SQL injection. An attacker could use a SQL injection to steal or modify contents of the database. Instead, use a parameterized query which is available by default in most database engines. Alternatively, consider using an object-relational mapper (ORM) such as Sequelize which will protect your queries.

View Dataflow Graph
flowchart LR
    classDef invis fill:white, stroke: none
    classDef default fill:#e7f5ff, color:#1c7fd6, stroke: none

    subgraph File0["<b>src/assistant-fix-sqli-sequelize.ts</b>"]
        direction LR
        %% Source

        subgraph Source
            direction LR

            v0["<a href=https://github.com/Semgrep-Demo/sharpcompress/blob/040ef9505cbd34b360de29a840059d1d20b8877c/src/assistant-fix-sqli-sequelize.ts#L3 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 3] req.query</a>"]
        end
        %% Intermediate

        subgraph Traces0[Traces]
            direction TB

            v2["<a href=https://github.com/Semgrep-Demo/sharpcompress/blob/040ef9505cbd34b360de29a840059d1d20b8877c/src/assistant-fix-sqli-sequelize.ts#L3 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 3] criteria</a>"]
        end
        %% Sink

        subgraph Sink
            direction LR

            v1["<a href=https://github.com/Semgrep-Demo/sharpcompress/blob/040ef9505cbd34b360de29a840059d1d20b8877c/src/assistant-fix-sqli-sequelize.ts#L5 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 5] criteria</a>"]
        end
    end
    %% Class Assignment
    Source:::invis
    Sink:::invis

    Traces0:::invis
    File0:::invis

    %% Connections

    Source --> Traces0
    Traces0 --> Sink

Loading
Ignore this finding from tainted-sql-string.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep Assistant suggests the following fix: Use parameterized queries with Sequelize to prevent SQL injection.

View step-by-step instructions
  1. Change the SQL query string to use parameterized queries. Replace the dynamic parts with placeholders.

    const query = "SELECT * FROM Products WHERE ((name LIKE :criteria OR description LIKE :criteria) AND deletedAt IS NULL) ORDER BY name";
  2. Pass the dynamic value as a parameter to the sequelize.query method.

    models.sequelize.query(query, {
      replacements: { criteria: `%${criteria}%` }
    })
  3. Replace the original query call with the updated parameterized query.

    models.sequelize.query(query, {
      replacements: { criteria: `%${criteria}%` }
    })
    .then(([products]: any) => {
      const dataString = JSON.stringify(products)
      for (let i = 0; i < products.length; i++) {
        products[i].name = req.__(products[i].name)
        products[i].description = req.__(products[i].description)
      }
      res.json(utils.queryResultToJson(products))
    }).catch((error: ErrorWithParent) => {
      next(error.parent)
    })

Using parameterized queries helps prevent SQL injection by ensuring that user input is treated as data rather than executable code.

This code change should be a good starting point:

Suggested change
models.sequelize.query("SELECT * FROM Products WHERE ((name LIKE '%"+criteria+"%' OR description LIKE '%"+criteria+"%') AND deletedAt IS NULL) ORDER BY name")
models.sequelize.query(
"SELECT * FROM Products WHERE ((name LIKE :criteria OR description LIKE :criteria) AND deletedAt IS NULL) ORDER BY name",
{
replacements: { criteria: `%${criteria}%` },
type: models.sequelize.QueryTypes.SELECT
}
)

AI-generated comment. Please review the response carefully and leave feedback in the form of a 👍 or 👎 reaction

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant