diff --git a/javascript/ql/lib/change-notes/2025-07-28-dynamodb.md b/javascript/ql/lib/change-notes/2025-07-28-dynamodb.md new file mode 100644 index 000000000000..bbf5d57163ae --- /dev/null +++ b/javascript/ql/lib/change-notes/2025-07-28-dynamodb.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added support for the `aws-sdk` and `@aws-sdk/client-dynamodb`, `@aws-sdk/client-athena`, `@aws-sdk/client-s3`, and `@aws-sdk/client-rds-data` packages. diff --git a/javascript/ql/lib/ext/aws-sdk.model.yml b/javascript/ql/lib/ext/aws-sdk.model.yml index eefa87fbe613..d850fec7371c 100644 --- a/javascript/ql/lib/ext/aws-sdk.model.yml +++ b/javascript/ql/lib/ext/aws-sdk.model.yml @@ -3,6 +3,49 @@ extensions: pack: codeql/javascript-all extensible: sinkModel data: - - ["aws-sdk", "AnyMember.Argument[0].Member[secretAccessKey,accessKeyId]", "credentials-key"] - - ["aws-sdk", "AnyMember.Member[secretAccessKey,accessKeyId]", "credentials-key"] - - ["aws-sdk", "Member[Credentials].Argument[0,1]", "credentials-key"] + - ["aws-sdk", "AnyMember.Argument[0].Member[secretAccessKey,accessKeyId]", "credentials-key"] + - ["aws-sdk", "AnyMember.Member[secretAccessKey,accessKeyId]", "credentials-key"] + - ["aws-sdk", "Member[Credentials].Argument[0,1]", "credentials-key"] + - ["AWS-V3-Common", "ReturnValue.Member[send].Argument[0]", "sql-injection"] + - ["AthenaClientV2", "ReturnValue.Member[startQueryExecution,createNamedQuery,updateNamedQuery].Argument[0].Member[QueryString]", "sql-injection"] + - ["S3ClientV2", "ReturnValue.Member[selectObjectContent].Argument[0].Member[Expression]", "sql-injection"] + - ["RDSDataClientV2", "ReturnValue.Member[executeStatement,batchExecuteStatement].Argument[0].Member[sql]", "sql-injection"] + - ["RDSDataClientV2", "ReturnValue.Member[batchExecuteStatement].Argument[0].Member[parameterSets].ArrayElement.Member[sql]", "sql-injection"] + - ["DynamoDBClientV2", "ReturnValue.Member[executeStatement].Argument[0].Member[Statement]", "sql-injection"] + - ["DynamoDBClientV2", "ReturnValue.Member[batchExecuteStatement].Argument[0].Member[Statements].ArrayElement.Member[Statement]", "sql-injection"] + - addsTo: + pack: codeql/javascript-all + extensible: summaryModel + data: + - ["@aws-sdk/client-athena", "Member[StartQueryExecutionCommand,CreateNamedQueryCommand,UpdateNamedQueryCommand]", "Argument[0].Member[QueryString]", "ReturnValue", "taint"] + - ["@aws-sdk/client-s3", "Member[SelectObjectContentCommand]", "Argument[0].Member[Expression]", "ReturnValue", "taint"] + - ["@aws-sdk/client-rds-data", "Member[ExecuteStatementCommand,BatchExecuteStatementCommand]", "Argument[0].Member[sql]", "ReturnValue", "taint"] + - ["@aws-sdk/client-rds-data", "Member[BatchExecuteStatementCommand]", "Argument[0].Member[parameterSets].ArrayElement.Member[sql]", "ReturnValue", "taint"] + - ["@aws-sdk/client-rds-data", "Member[ExecuteSqlCommand]", "Argument[0].Member[sqlStatements]", "ReturnValue", "taint"] + - ["@aws-sdk/client-dynamodb", "Member[ExecuteStatementCommand]", "Argument[0].Member[Statement]", "ReturnValue", "taint"] + - ["@aws-sdk/client-dynamodb", "Member[BatchExecuteStatementCommand]", "Argument[0].Member[Statements].ArrayElement.Member[Statement]", "ReturnValue", "taint"] + - addsTo: + pack: codeql/javascript-all + extensible: typeModel + data: + - ["AthenaClientV2", "aws-sdk", "Member[Athena]"] + - ["S3ClientV2", "aws-sdk", "Member[S3]"] + - ["RDSDataClientV2", "aws-sdk", "Member[RDSDataService]"] + - ["DynamoDBClientV2", "aws-sdk", "Member[DynamoDB]"] + - ["AWS-V3-Common", "@aws-sdk/client-athena", "Member[AthenaClient]"] + - ["AWS-V3-Common", "@aws-sdk/client-s3", "Member[S3Client]"] + - ["AWS-V3-Common", "@aws-sdk/client-dynamodb", "Member[DynamoDBClient,DynamoDB]"] + - ["AWS-V3-Common", "@aws-sdk/client-rds-data", "Member[RDSDataClient]"] + - addsTo: + pack: codeql/javascript-all + extensible: sourceModel + data: + - ["AWS-V3-Common", "ReturnValue.Member[send].ReturnValue.Awaited", "database-access-result"] + - ["AthenaClientV2", "ReturnValue.Member[getQueryResults].ReturnValue.Member[promise].ReturnValue.Awaited", "database-access-result"] + - ["AthenaClientV2", "ReturnValue.Member[getQueryResults].Argument[1].Parameter[1]", "database-access-result"] + - ["S3ClientV2", "ReturnValue.Member[getObject].ReturnValue.Member[promise].ReturnValue.Awaited", "database-access-result"] + - ["S3ClientV2", "ReturnValue.Member[getObject].Argument[1].Parameter[1]", "database-access-result"] + - ["RDSDataClientV2", "ReturnValue.Member[executeStatement,batchExecuteStatement].ReturnValue.Member[promise].ReturnValue.Awaited", "database-access-result"] + - ["RDSDataClientV2", "ReturnValue.Member[executeStatement,batchExecuteStatement].Argument[1].Parameter[1]", "database-access-result"] + - ["DynamoDBClientV2", "ReturnValue.Member[executeStatement,batchExecuteStatement,query,scan,getItem,batchGetItem].ReturnValue.Member[promise].ReturnValue.Awaited", "database-access-result"] + - ["DynamoDBClientV2", "ReturnValue.Member[executeStatement,batchExecuteStatement,query,scan,getItem,batchGetItem].Argument[1].Parameter[1]", "database-access-result"] diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected index c031b7c1810c..295a830754ce 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected @@ -32,6 +32,34 @@ nodes | angular-tempate-url.js:13:30:13:31 | ev | semmle.label | ev | | angular-tempate-url.js:14:26:14:27 | ev | semmle.label | ev | | angular-tempate-url.js:14:26:14:32 | ev.data | semmle.label | ev.data | +| aws-db.js:15:31:15:37 | results | semmle.label | results | +| aws-db.js:15:31:15:76 | results ... arValue | semmle.label | results ... arValue | +| aws-db.js:20:31:20:38 | response | semmle.label | response | +| aws-db.js:20:31:20:54 | respons ... tring() | semmle.label | respons ... tring() | +| aws-db.js:24:31:24:39 | response2 | semmle.label | response2 | +| aws-db.js:24:31:24:47 | response2.records | semmle.label | response2.records | +| aws-db.js:28:31:28:39 | response3 | semmle.label | response3 | +| aws-db.js:28:31:28:44 | response3.Item | semmle.label | response3.Item | +| aws-db.js:43:31:43:37 | results | semmle.label | results | +| aws-db.js:43:31:43:76 | results ... arValue | semmle.label | results ... arValue | +| aws-db.js:46:35:46:38 | data | semmle.label | data | +| aws-db.js:46:35:46:77 | data.Re ... arValue | semmle.label | data.Re ... arValue | +| aws-db.js:51:31:51:38 | response | semmle.label | response | +| aws-db.js:51:31:51:54 | respons ... tring() | semmle.label | respons ... tring() | +| aws-db.js:54:35:54:38 | data | semmle.label | data | +| aws-db.js:54:35:54:54 | data.Body.toString() | semmle.label | data.Body.toString() | +| aws-db.js:59:31:59:39 | response1 | semmle.label | response1 | +| aws-db.js:59:31:59:47 | response1.records | semmle.label | response1.records | +| aws-db.js:62:35:62:38 | data | semmle.label | data | +| aws-db.js:62:35:62:46 | data.records | semmle.label | data.records | +| aws-db.js:66:31:66:39 | response2 | semmle.label | response2 | +| aws-db.js:66:31:66:53 | respons ... Results | semmle.label | respons ... Results | +| aws-db.js:69:35:69:38 | data | semmle.label | data | +| aws-db.js:69:35:69:52 | data.updateResults | semmle.label | data.updateResults | +| aws-db.js:74:35:74:38 | data | semmle.label | data | +| aws-db.js:74:35:74:43 | data.Item | semmle.label | data.Item | +| aws-db.js:77:35:77:38 | data | semmle.label | data | +| aws-db.js:77:35:77:43 | data.Item | semmle.label | data.Item | | classnames.js:7:31:7:84 | `` | semmle.label | `` | | classnames.js:7:47:7:69 | classNa ... w.name) | semmle.label | classNa ... w.name) | | classnames.js:7:58:7:68 | window.name | semmle.label | window.name | @@ -724,6 +752,20 @@ edges | angular-tempate-url.js:13:30:13:31 | ev | angular-tempate-url.js:14:26:14:27 | ev | provenance | | | angular-tempate-url.js:14:26:14:27 | ev | angular-tempate-url.js:14:26:14:32 | ev.data | provenance | | | angular-tempate-url.js:14:26:14:32 | ev.data | angular-tempate-url.js:9:26:9:45 | Cookie.get("unsafe") | provenance | | +| aws-db.js:15:31:15:37 | results | aws-db.js:15:31:15:76 | results ... arValue | provenance | | +| aws-db.js:20:31:20:38 | response | aws-db.js:20:31:20:54 | respons ... tring() | provenance | | +| aws-db.js:24:31:24:39 | response2 | aws-db.js:24:31:24:47 | response2.records | provenance | | +| aws-db.js:28:31:28:39 | response3 | aws-db.js:28:31:28:44 | response3.Item | provenance | | +| aws-db.js:43:31:43:37 | results | aws-db.js:43:31:43:76 | results ... arValue | provenance | | +| aws-db.js:46:35:46:38 | data | aws-db.js:46:35:46:77 | data.Re ... arValue | provenance | | +| aws-db.js:51:31:51:38 | response | aws-db.js:51:31:51:54 | respons ... tring() | provenance | | +| aws-db.js:54:35:54:38 | data | aws-db.js:54:35:54:54 | data.Body.toString() | provenance | | +| aws-db.js:59:31:59:39 | response1 | aws-db.js:59:31:59:47 | response1.records | provenance | | +| aws-db.js:62:35:62:38 | data | aws-db.js:62:35:62:46 | data.records | provenance | | +| aws-db.js:66:31:66:39 | response2 | aws-db.js:66:31:66:53 | respons ... Results | provenance | | +| aws-db.js:69:35:69:38 | data | aws-db.js:69:35:69:52 | data.updateResults | provenance | | +| aws-db.js:74:35:74:38 | data | aws-db.js:74:35:74:43 | data.Item | provenance | | +| aws-db.js:77:35:77:38 | data | aws-db.js:77:35:77:43 | data.Item | provenance | | | classnames.js:7:47:7:69 | classNa ... w.name) | classnames.js:7:31:7:84 | `` | provenance | | | classnames.js:7:58:7:68 | window.name | classnames.js:7:47:7:69 | classNa ... w.name) | provenance | | | classnames.js:8:47:8:70 | classNa ... w.name) | classnames.js:8:31:8:85 | `` | provenance | | @@ -1319,6 +1361,20 @@ subpaths | various-concat-obfuscations.js:21:17:21:46 | documen ... h.attrs | various-concat-obfuscations.js:17:24:17:28 | attrs | various-concat-obfuscations.js:18:10:18:105 | '
') | various-concat-obfuscations.js:21:4:21:47 | indirec ... .attrs) | | various-concat-obfuscations.js:21:17:21:46 | documen ... h.attrs | various-concat-obfuscations.js:17:24:17:28 | attrs | various-concat-obfuscations.js:18:10:18:105 | '
') [ArrayElement] | various-concat-obfuscations.js:21:4:21:47 | indirec ... .attrs) | #select +| aws-db.js:15:31:15:76 | results ... arValue | aws-db.js:15:31:15:37 | results | aws-db.js:15:31:15:76 | results ... arValue | Cross-site scripting vulnerability due to $@. | aws-db.js:15:31:15:37 | results | user-provided value | +| aws-db.js:20:31:20:54 | respons ... tring() | aws-db.js:20:31:20:38 | response | aws-db.js:20:31:20:54 | respons ... tring() | Cross-site scripting vulnerability due to $@. | aws-db.js:20:31:20:38 | response | user-provided value | +| aws-db.js:24:31:24:47 | response2.records | aws-db.js:24:31:24:39 | response2 | aws-db.js:24:31:24:47 | response2.records | Cross-site scripting vulnerability due to $@. | aws-db.js:24:31:24:39 | response2 | user-provided value | +| aws-db.js:28:31:28:44 | response3.Item | aws-db.js:28:31:28:39 | response3 | aws-db.js:28:31:28:44 | response3.Item | Cross-site scripting vulnerability due to $@. | aws-db.js:28:31:28:39 | response3 | user-provided value | +| aws-db.js:43:31:43:76 | results ... arValue | aws-db.js:43:31:43:37 | results | aws-db.js:43:31:43:76 | results ... arValue | Cross-site scripting vulnerability due to $@. | aws-db.js:43:31:43:37 | results | user-provided value | +| aws-db.js:46:35:46:77 | data.Re ... arValue | aws-db.js:46:35:46:38 | data | aws-db.js:46:35:46:77 | data.Re ... arValue | Cross-site scripting vulnerability due to $@. | aws-db.js:46:35:46:38 | data | user-provided value | +| aws-db.js:51:31:51:54 | respons ... tring() | aws-db.js:51:31:51:38 | response | aws-db.js:51:31:51:54 | respons ... tring() | Cross-site scripting vulnerability due to $@. | aws-db.js:51:31:51:38 | response | user-provided value | +| aws-db.js:54:35:54:54 | data.Body.toString() | aws-db.js:54:35:54:38 | data | aws-db.js:54:35:54:54 | data.Body.toString() | Cross-site scripting vulnerability due to $@. | aws-db.js:54:35:54:38 | data | user-provided value | +| aws-db.js:59:31:59:47 | response1.records | aws-db.js:59:31:59:39 | response1 | aws-db.js:59:31:59:47 | response1.records | Cross-site scripting vulnerability due to $@. | aws-db.js:59:31:59:39 | response1 | user-provided value | +| aws-db.js:62:35:62:46 | data.records | aws-db.js:62:35:62:38 | data | aws-db.js:62:35:62:46 | data.records | Cross-site scripting vulnerability due to $@. | aws-db.js:62:35:62:38 | data | user-provided value | +| aws-db.js:66:31:66:53 | respons ... Results | aws-db.js:66:31:66:39 | response2 | aws-db.js:66:31:66:53 | respons ... Results | Cross-site scripting vulnerability due to $@. | aws-db.js:66:31:66:39 | response2 | user-provided value | +| aws-db.js:69:35:69:52 | data.updateResults | aws-db.js:69:35:69:38 | data | aws-db.js:69:35:69:52 | data.updateResults | Cross-site scripting vulnerability due to $@. | aws-db.js:69:35:69:38 | data | user-provided value | +| aws-db.js:74:35:74:43 | data.Item | aws-db.js:74:35:74:38 | data | aws-db.js:74:35:74:43 | data.Item | Cross-site scripting vulnerability due to $@. | aws-db.js:74:35:74:38 | data | user-provided value | +| aws-db.js:77:35:77:43 | data.Item | aws-db.js:77:35:77:38 | data | aws-db.js:77:35:77:43 | data.Item | Cross-site scripting vulnerability due to $@. | aws-db.js:77:35:77:38 | data | user-provided value | | hana.js:11:37:11:51 | rows[0].comment | hana.js:11:37:11:40 | rows | hana.js:11:37:11:51 | rows[0].comment | Cross-site scripting vulnerability due to $@. | hana.js:11:37:11:40 | rows | user-provided value | | hana.js:16:37:16:51 | rows[0].comment | hana.js:16:37:16:40 | rows | hana.js:16:37:16:51 | rows[0].comment | Cross-site scripting vulnerability due to $@. | hana.js:16:37:16:40 | rows | user-provided value | | hana.js:19:37:19:51 | rows[0].comment | hana.js:19:37:19:40 | rows | hana.js:19:37:19:51 | rows[0].comment | Cross-site scripting vulnerability due to $@. | hana.js:19:37:19:40 | rows | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/aws-db.js b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/aws-db.js new file mode 100644 index 000000000000..0f345f7172e0 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/aws-db.js @@ -0,0 +1,79 @@ +const { AthenaClient, GetQueryResultsCommand } = require('@aws-sdk/client-athena'); +const { S3Client, GetObjectCommand } = require("@aws-sdk/client-s3"); +const { RDSDataClient, ExecuteStatementCommand } = require("@aws-sdk/client-rds-data"); +const { DynamoDBClient, GetItemCommand } = require("@aws-sdk/client-dynamodb"); + + +const express = require('express'); +const bodyParser = require('body-parser'); +const app = express(); +app.use(bodyParser.json()); + +app.post('/v3/all', async (req, res) => { + const client = new AthenaClient({ region: "us-east-1" }); + const results = await client.send(new GetQueryResultsCommand({ QueryExecutionId })); + document.body.innerHTML = results.ResultSet.Rows[0].Data[0].VarCharValue; // $ Alert[js/xss-additional-sources-dom-test] + + const s3 = new S3Client({ region: "us-east-1" }); + const command = new GetObjectCommand({ Bucket: bucket, Key: key }); + const response = await s3.send(command); + document.body.innerHTML = response.Body.toString(); // $ Alert[js/xss-additional-sources-dom-test] + + const clientRDS = new RDSDataClient({ region: "us-east-1" }); + const response2 = await clientRDS.send(new ExecuteStatementCommand(command)); + document.body.innerHTML = response2.records; // $ Alert[js/xss-additional-sources-dom-test] + + const clientDyamo = new DynamoDBClient({ region: "us-east-1" }); + const response3 = await clientDyamo.send(new GetItemCommand(command)); + document.body.innerHTML = response3.Item; // $ Alert[js/xss-additional-sources-dom-test] + +}); + + +app.post('/v2/all', async (req, res) => { + const AWS = require('aws-sdk'); + const athena = new AWS.Athena(); + const params = { + QueryString: 'SELECT * FROM my_table', + ResultConfiguration: { OutputLocation: 's3://bucket/prefix/' } + }; + const { QueryExecutionId } = await athena.startQueryExecution(params).promise(); + + const results = await athena.getQueryResults({ QueryExecutionId }).promise(); + document.body.innerHTML = results.ResultSet.Rows[0].Data[0].VarCharValue; // $ Alert[js/xss-additional-sources-dom-test] + + athena.getQueryResults({ QueryExecutionId }, (err, data) => { + document.body.innerHTML = data.ResultSet.Rows[0].Data[0].VarCharValue; // $ Alert[js/xss-additional-sources-dom-test] + }); + + const s3 = new AWS.S3({ region: "us-east-1" }); + const response = await s3.getObject({ Bucket: "bucket", Key: "key" }).promise(); + document.body.innerHTML = response.Body.toString(); // $ Alert[js/xss-additional-sources-dom-test] + + s3.getObject({ Bucket: "bucket", Key: "key" }, (err, data) => { + document.body.innerHTML = data.Body.toString(); // $ Alert[js/xss-additional-sources-dom-test] + }); + + const rdsData = new AWS.RDSDataService({ region: "us-east-1" }); + const response1 = await rdsData.executeStatement(params).promise(); + document.body.innerHTML = response1.records; // $ Alert[js/xss-additional-sources-dom-test] + + rdsData.executeStatement(params, function(err, data) { + document.body.innerHTML = data.records; // $ Alert[js/xss-additional-sources-dom-test] + }); + + const response2 = await rdsData.batchExecuteStatement(params).promise(); + document.body.innerHTML = response2.updateResults; // $ Alert[js/xss-additional-sources-dom-test] + + rdsData.batchExecuteStatement(params, function(err, data) { + document.body.innerHTML = data.updateResults; // $ Alert[js/xss-additional-sources-dom-test] + }); + + const dynamodb = new AWS.DynamoDB({ region: "us-east-1" }); + dynamodb.executeStatement(params, (err, data) => { + document.body.innerHTML = data.Item; // $ Alert[js/xss-additional-sources-dom-test] + }); + dynamodb.executeStatement(params).promise().then(data => { + document.body.innerHTML = data.Item; // $ Alert[js/xss-additional-sources-dom-test] + }); +}); diff --git a/javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected b/javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected index 843d41eb9229..888cbee4641e 100644 --- a/javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected @@ -1,4 +1,19 @@ #select +| athena.js:19:23:19:23 | p | athena.js:9:23:9:30 | req.body | athena.js:19:23:19:23 | p | This query string depends on a $@. | athena.js:9:23:9:30 | req.body | user-provided value | +| athena.js:27:23:27:58 | new Cre ... arams2) | athena.js:9:23:9:30 | req.body | athena.js:27:23:27:58 | new Cre ... arams2) | This query string depends on a $@. | athena.js:9:23:9:30 | req.body | user-provided value | +| athena.js:36:23:36:58 | new Upd ... arams3) | athena.js:9:23:9:30 | req.body | athena.js:36:23:36:58 | new Upd ... arams3) | This query string depends on a $@. | athena.js:9:23:9:30 | req.body | user-provided value | +| athena.js:48:22:48:30 | userQuery | athena.js:43:23:43:30 | req.body | athena.js:48:22:48:30 | userQuery | This query string depends on a $@. | athena.js:43:23:43:30 | req.body | user-provided value | +| athena.js:57:22:57:30 | userQuery | athena.js:43:23:43:30 | req.body | athena.js:57:22:57:30 | userQuery | This query string depends on a $@. | athena.js:43:23:43:30 | req.body | user-provided value | +| athena.js:66:22:66:30 | userQuery | athena.js:43:23:43:30 | req.body | athena.js:66:22:66:30 | userQuery | This query string depends on a $@. | athena.js:43:23:43:30 | req.body | user-provided value | +| clients3.js:18:23:18:60 | new Sel ... params) | clients3.js:10:26:10:33 | req.body | clients3.js:18:23:18:60 | new Sel ... params) | This query string depends on a $@. | clients3.js:10:26:10:33 | req.body | user-provided value | +| clients3.js:29:21:29:68 | "SELECT ... usInput | clients3.js:23:26:23:33 | req.body | clients3.js:29:21:29:68 | "SELECT ... usInput | This query string depends on a $@. | clients3.js:23:26:23:33 | req.body | user-provided value | +| clients3.js:38:21:38:68 | "SELECT ... usInput | clients3.js:23:26:23:33 | req.body | clients3.js:38:21:38:68 | "SELECT ... usInput | This query string depends on a $@. | clients3.js:23:26:23:33 | req.body | user-provided value | +| dynamodb.js:15:23:15:29 | command | dynamodb.js:9:26:9:33 | req.body | dynamodb.js:15:23:15:29 | command | This query string depends on a $@. | dynamodb.js:9:26:9:33 | req.body | user-provided value | +| dynamodb.js:21:23:21:35 | updateCommand | dynamodb.js:9:26:9:33 | req.body | dynamodb.js:21:23:21:35 | updateCommand | This query string depends on a $@. | dynamodb.js:9:26:9:33 | req.body | user-provided value | +| dynamodb.js:47:24:47:30 | command | dynamodb.js:9:26:9:33 | req.body | dynamodb.js:47:24:47:30 | command | This query string depends on a $@. | dynamodb.js:9:26:9:33 | req.body | user-provided value | +| dynamodb.js:58:20:58:77 | `SELECT ... nput}'` | dynamodb.js:56:26:56:33 | req.body | dynamodb.js:58:20:58:77 | `SELECT ... nput}'` | This query string depends on a $@. | dynamodb.js:56:26:56:33 | req.body | user-provided value | +| dynamodb.js:64:28:64:85 | `SELECT ... nput}'` | dynamodb.js:56:26:56:33 | req.body | dynamodb.js:64:28:64:85 | `SELECT ... nput}'` | This query string depends on a $@. | dynamodb.js:56:26:56:33 | req.body | user-provided value | +| dynamodb.js:67:28:67:85 | `SELECT ... nput}'` | dynamodb.js:56:26:56:33 | req.body | dynamodb.js:67:28:67:85 | `SELECT ... nput}'` | This query string depends on a $@. | dynamodb.js:56:26:56:33 | req.body | user-provided value | | graphql.js:9:34:19:5 | `\\n ... }\\n ` | graphql.js:8:16:8:28 | req.params.id | graphql.js:9:34:19:5 | `\\n ... }\\n ` | This query string depends on a $@. | graphql.js:8:16:8:28 | req.params.id | user-provided value | | graphql.js:26:30:26:40 | `foo ${id}` | graphql.js:25:16:25:28 | req.params.id | graphql.js:26:30:26:40 | `foo ${id}` | This query string depends on a $@. | graphql.js:25:16:25:28 | req.params.id | user-provided value | | graphql.js:29:32:29:42 | `foo ${id}` | graphql.js:25:16:25:28 | req.params.id | graphql.js:29:32:29:42 | `foo ${id}` | This query string depends on a $@. | graphql.js:25:16:25:28 | req.params.id | user-provided value | @@ -122,6 +137,10 @@ | pg-promise.js:60:20:60:24 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:60:20:60:24 | query | This query string depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value | | pg-promise.js:63:23:63:27 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:63:23:63:27 | query | This query string depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value | | pg-promise.js:64:16:64:20 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:64:16:64:20 | query | This query string depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value | +| rds-client.js:19:23:19:58 | new Exe ... arams1) | rds-client.js:8:23:8:30 | req.body | rds-client.js:19:23:19:58 | new Exe ... arams1) | This query string depends on a $@. | rds-client.js:8:23:8:30 | req.body | user-provided value | +| rds-client.js:36:23:36:51 | new Exe ... params) | rds-client.js:8:23:8:30 | req.body | rds-client.js:36:23:36:51 | new Exe ... params) | This query string depends on a $@. | rds-client.js:8:23:8:30 | req.body | user-provided value | +| rds-client.js:53:14:53:22 | userQuery | rds-client.js:44:23:44:30 | req.body | rds-client.js:53:14:53:22 | userQuery | This query string depends on a $@. | rds-client.js:44:23:44:30 | req.body | user-provided value | +| rds-client.js:61:50:61:52 | sql | rds-client.js:45:25:45:32 | req.body | rds-client.js:61:50:61:52 | sql | This query string depends on a $@. | rds-client.js:45:25:45:32 | req.body | user-provided value | | redis.js:10:16:10:27 | req.body.key | redis.js:10:16:10:23 | req.body | redis.js:10:16:10:27 | req.body.key | This query object depends on a $@. | redis.js:10:16:10:23 | req.body | user-provided value | | redis.js:18:16:18:18 | key | redis.js:12:15:12:22 | req.body | redis.js:18:16:18:18 | key | This query object depends on a $@. | redis.js:12:15:12:22 | req.body | user-provided value | | redis.js:19:43:19:45 | key | redis.js:12:15:12:22 | req.body | redis.js:19:43:19:45 | key | This query object depends on a $@. | redis.js:12:15:12:22 | req.body | user-provided value | @@ -137,6 +156,64 @@ | tst4.js:8:10:8:66 | 'SELECT ... d + '"' | tst4.js:8:46:8:60 | $routeParams.id | tst4.js:8:10:8:66 | 'SELECT ... d + '"' | This query string depends on a $@. | tst4.js:8:46:8:60 | $routeParams.id | user-provided value | | tst.js:10:10:10:64 | 'SELECT ... d + '"' | tst.js:10:46:10:58 | req.params.id | tst.js:10:10:10:64 | 'SELECT ... d + '"' | This query string depends on a $@. | tst.js:10:46:10:58 | req.params.id | user-provided value | edges +| athena.js:9:11:9:36 | userQuery | athena.js:14:30:14:38 | userQuery | provenance | | +| athena.js:9:11:9:36 | userQuery | athena.js:24:22:24:30 | userQuery | provenance | | +| athena.js:9:11:9:36 | userQuery | athena.js:33:22:33:30 | userQuery | provenance | | +| athena.js:9:23:9:30 | req.body | athena.js:9:11:9:36 | userQuery | provenance | | +| athena.js:13:11:17:5 | params1 [QueryString] | athena.js:18:46:18:52 | params1 [QueryString] | provenance | | +| athena.js:13:21:17:5 | {\\n ... }\\n } [QueryString] | athena.js:13:11:17:5 | params1 [QueryString] | provenance | | +| athena.js:14:22:14:38 | "SQL" + userQuery | athena.js:13:21:17:5 | {\\n ... }\\n } [QueryString] | provenance | | +| athena.js:14:30:14:38 | userQuery | athena.js:14:22:14:38 | "SQL" + userQuery | provenance | | +| athena.js:18:11:18:53 | p | athena.js:19:23:19:23 | p | provenance | | +| athena.js:18:15:18:53 | new Sta ... arams1) | athena.js:18:11:18:53 | p | provenance | | +| athena.js:18:46:18:52 | params1 [QueryString] | athena.js:18:15:18:53 | new Sta ... arams1) | provenance | | +| athena.js:21:11:26:5 | params2 [QueryString] | athena.js:27:51:27:57 | params2 [QueryString] | provenance | | +| athena.js:21:21:26:5 | {\\n ... "\\n } [QueryString] | athena.js:21:11:26:5 | params2 [QueryString] | provenance | | +| athena.js:24:22:24:30 | userQuery | athena.js:21:21:26:5 | {\\n ... "\\n } [QueryString] | provenance | | +| athena.js:27:51:27:57 | params2 [QueryString] | athena.js:27:23:27:58 | new Cre ... arams2) | provenance | | +| athena.js:29:11:35:5 | params3 [QueryString] | athena.js:36:51:36:57 | params3 [QueryString] | provenance | | +| athena.js:29:21:35:5 | {\\n ... "\\n } [QueryString] | athena.js:29:11:35:5 | params3 [QueryString] | provenance | | +| athena.js:33:22:33:30 | userQuery | athena.js:29:21:35:5 | {\\n ... "\\n } [QueryString] | provenance | | +| athena.js:36:51:36:57 | params3 [QueryString] | athena.js:36:23:36:58 | new Upd ... arams3) | provenance | | +| athena.js:43:11:43:36 | userQuery | athena.js:48:22:48:30 | userQuery | provenance | | +| athena.js:43:11:43:36 | userQuery | athena.js:57:22:57:30 | userQuery | provenance | | +| athena.js:43:11:43:36 | userQuery | athena.js:66:22:66:30 | userQuery | provenance | | +| athena.js:43:23:43:30 | req.body | athena.js:43:11:43:36 | userQuery | provenance | | +| clients3.js:10:9:10:40 | maliciousInput | clients3.js:16:55:16:68 | maliciousInput | provenance | | +| clients3.js:10:26:10:33 | req.body | clients3.js:10:9:10:40 | maliciousInput | provenance | | +| clients3.js:12:11:17:5 | params [Expression] | clients3.js:18:54:18:59 | params [Expression] | provenance | | +| clients3.js:12:20:17:5 | {\\n ... ,\\n } [Expression] | clients3.js:12:11:17:5 | params [Expression] | provenance | | +| clients3.js:16:21:16:68 | "SELECT ... usInput | clients3.js:12:20:17:5 | {\\n ... ,\\n } [Expression] | provenance | | +| clients3.js:16:55:16:68 | maliciousInput | clients3.js:16:21:16:68 | "SELECT ... usInput | provenance | | +| clients3.js:18:54:18:59 | params [Expression] | clients3.js:18:23:18:60 | new Sel ... params) | provenance | | +| clients3.js:23:9:23:40 | maliciousInput | clients3.js:29:55:29:68 | maliciousInput | provenance | | +| clients3.js:23:9:23:40 | maliciousInput | clients3.js:38:55:38:68 | maliciousInput | provenance | | +| clients3.js:23:26:23:33 | req.body | clients3.js:23:9:23:40 | maliciousInput | provenance | | +| clients3.js:29:55:29:68 | maliciousInput | clients3.js:29:21:29:68 | "SELECT ... usInput | provenance | | +| clients3.js:38:55:38:68 | maliciousInput | clients3.js:38:21:38:68 | "SELECT ... usInput | provenance | | +| dynamodb.js:9:9:9:38 | maliciousInput | dynamodb.js:11:64:11:77 | maliciousInput | provenance | | +| dynamodb.js:9:9:9:38 | maliciousInput | dynamodb.js:17:80:17:93 | maliciousInput | provenance | | +| dynamodb.js:9:26:9:33 | req.body | dynamodb.js:9:9:9:38 | maliciousInput | provenance | | +| dynamodb.js:11:11:11:80 | statement | dynamodb.js:13:20:13:28 | statement | provenance | | +| dynamodb.js:11:64:11:77 | maliciousInput | dynamodb.js:11:11:11:80 | statement | provenance | | +| dynamodb.js:12:11:14:6 | command | dynamodb.js:15:23:15:29 | command | provenance | | +| dynamodb.js:12:11:14:6 | command | dynamodb.js:47:24:47:30 | command | provenance | | +| dynamodb.js:12:21:14:6 | new Exe ... \\n }) | dynamodb.js:12:11:14:6 | command | provenance | | +| dynamodb.js:12:49:14:5 | {\\n ... t\\n } [Statement] | dynamodb.js:12:21:14:6 | new Exe ... \\n }) | provenance | | +| dynamodb.js:13:20:13:28 | statement | dynamodb.js:12:49:14:5 | {\\n ... t\\n } [Statement] | provenance | | +| dynamodb.js:17:11:17:93 | updateStatement | dynamodb.js:19:20:19:34 | updateStatement | provenance | | +| dynamodb.js:17:80:17:93 | maliciousInput | dynamodb.js:17:11:17:93 | updateStatement | provenance | | +| dynamodb.js:18:11:20:6 | updateCommand | dynamodb.js:21:23:21:35 | updateCommand | provenance | | +| dynamodb.js:18:27:20:6 | new Exe ... \\n }) | dynamodb.js:18:11:20:6 | updateCommand | provenance | | +| dynamodb.js:18:55:20:5 | {\\n ... t\\n } [Statement] | dynamodb.js:18:27:20:6 | new Exe ... \\n }) | provenance | | +| dynamodb.js:19:20:19:34 | updateStatement | dynamodb.js:18:55:20:5 | {\\n ... t\\n } [Statement] | provenance | | +| dynamodb.js:56:9:56:38 | maliciousInput | dynamodb.js:58:61:58:74 | maliciousInput | provenance | | +| dynamodb.js:56:9:56:38 | maliciousInput | dynamodb.js:64:69:64:82 | maliciousInput | provenance | | +| dynamodb.js:56:9:56:38 | maliciousInput | dynamodb.js:67:69:67:82 | maliciousInput | provenance | | +| dynamodb.js:56:26:56:33 | req.body | dynamodb.js:56:9:56:38 | maliciousInput | provenance | | +| dynamodb.js:58:61:58:74 | maliciousInput | dynamodb.js:58:20:58:77 | `SELECT ... nput}'` | provenance | | +| dynamodb.js:64:69:64:82 | maliciousInput | dynamodb.js:64:28:64:85 | `SELECT ... nput}'` | provenance | | +| dynamodb.js:67:69:67:82 | maliciousInput | dynamodb.js:67:28:67:85 | `SELECT ... nput}'` | provenance | | | graphql.js:8:11:8:28 | id | graphql.js:11:46:11:47 | id | provenance | | | graphql.js:8:16:8:28 | req.params.id | graphql.js:8:11:8:28 | id | provenance | | | graphql.js:11:46:11:47 | id | graphql.js:9:34:19:5 | `\\n ... }\\n ` | provenance | | @@ -490,6 +567,23 @@ edges | pg-promise.js:22:11:22:15 | query | pg-promise.js:60:20:60:24 | query | provenance | | | pg-promise.js:22:11:22:15 | query | pg-promise.js:63:23:63:27 | query | provenance | | | pg-promise.js:22:11:22:15 | query | pg-promise.js:64:16:64:20 | query | provenance | | +| rds-client.js:8:11:8:36 | userQuery | rds-client.js:17:14:17:22 | userQuery | provenance | | +| rds-client.js:8:11:8:36 | userQuery | rds-client.js:33:24:33:32 | userQuery | provenance | | +| rds-client.js:8:23:8:30 | req.body | rds-client.js:8:11:8:36 | userQuery | provenance | | +| rds-client.js:13:11:18:5 | params1 [sql] | rds-client.js:19:51:19:57 | params1 [sql] | provenance | | +| rds-client.js:13:21:18:5 | {\\n ... y\\n } [sql] | rds-client.js:13:11:18:5 | params1 [sql] | provenance | | +| rds-client.js:17:14:17:22 | userQuery | rds-client.js:13:21:18:5 | {\\n ... y\\n } [sql] | provenance | | +| rds-client.js:19:51:19:57 | params1 [sql] | rds-client.js:19:23:19:58 | new Exe ... arams1) | provenance | | +| rds-client.js:29:11:34:5 | params [sqlStatements] | rds-client.js:36:45:36:50 | params [sqlStatements] | provenance | | +| rds-client.js:29:20:34:5 | {\\n ... y\\n } [sqlStatements] | rds-client.js:29:11:34:5 | params [sqlStatements] | provenance | | +| rds-client.js:33:24:33:32 | userQuery | rds-client.js:29:20:34:5 | {\\n ... y\\n } [sqlStatements] | provenance | | +| rds-client.js:36:45:36:50 | params [sqlStatements] | rds-client.js:36:23:36:51 | new Exe ... params) | provenance | | +| rds-client.js:44:11:44:36 | userQuery | rds-client.js:53:14:53:22 | userQuery | provenance | | +| rds-client.js:44:23:44:30 | req.body | rds-client.js:44:11:44:36 | userQuery | provenance | | +| rds-client.js:45:11:45:40 | userQueries | rds-client.js:61:24:61:34 | userQueries | provenance | | +| rds-client.js:45:25:45:32 | req.body | rds-client.js:45:11:45:40 | userQueries | provenance | | +| rds-client.js:61:24:61:34 | userQueries | rds-client.js:61:40:61:42 | sql | provenance | | +| rds-client.js:61:40:61:42 | sql | rds-client.js:61:50:61:52 | sql | provenance | | | redis.js:10:16:10:23 | req.body | redis.js:10:16:10:27 | req.body.key | provenance | Config | | redis.js:12:9:12:26 | key | redis.js:13:16:13:18 | key | provenance | | | redis.js:12:9:12:26 | key | redis.js:18:16:18:18 | key | provenance | | @@ -518,6 +612,70 @@ edges | tst4.js:8:46:8:60 | $routeParams.id | tst4.js:8:10:8:66 | 'SELECT ... d + '"' | provenance | | | tst.js:10:46:10:58 | req.params.id | tst.js:10:10:10:64 | 'SELECT ... d + '"' | provenance | | nodes +| athena.js:9:11:9:36 | userQuery | semmle.label | userQuery | +| athena.js:9:23:9:30 | req.body | semmle.label | req.body | +| athena.js:13:11:17:5 | params1 [QueryString] | semmle.label | params1 [QueryString] | +| athena.js:13:21:17:5 | {\\n ... }\\n } [QueryString] | semmle.label | {\\n ... }\\n } [QueryString] | +| athena.js:14:22:14:38 | "SQL" + userQuery | semmle.label | "SQL" + userQuery | +| athena.js:14:30:14:38 | userQuery | semmle.label | userQuery | +| athena.js:18:11:18:53 | p | semmle.label | p | +| athena.js:18:15:18:53 | new Sta ... arams1) | semmle.label | new Sta ... arams1) | +| athena.js:18:46:18:52 | params1 [QueryString] | semmle.label | params1 [QueryString] | +| athena.js:19:23:19:23 | p | semmle.label | p | +| athena.js:21:11:26:5 | params2 [QueryString] | semmle.label | params2 [QueryString] | +| athena.js:21:21:26:5 | {\\n ... "\\n } [QueryString] | semmle.label | {\\n ... "\\n } [QueryString] | +| athena.js:24:22:24:30 | userQuery | semmle.label | userQuery | +| athena.js:27:23:27:58 | new Cre ... arams2) | semmle.label | new Cre ... arams2) | +| athena.js:27:51:27:57 | params2 [QueryString] | semmle.label | params2 [QueryString] | +| athena.js:29:11:35:5 | params3 [QueryString] | semmle.label | params3 [QueryString] | +| athena.js:29:21:35:5 | {\\n ... "\\n } [QueryString] | semmle.label | {\\n ... "\\n } [QueryString] | +| athena.js:33:22:33:30 | userQuery | semmle.label | userQuery | +| athena.js:36:23:36:58 | new Upd ... arams3) | semmle.label | new Upd ... arams3) | +| athena.js:36:51:36:57 | params3 [QueryString] | semmle.label | params3 [QueryString] | +| athena.js:43:11:43:36 | userQuery | semmle.label | userQuery | +| athena.js:43:23:43:30 | req.body | semmle.label | req.body | +| athena.js:48:22:48:30 | userQuery | semmle.label | userQuery | +| athena.js:57:22:57:30 | userQuery | semmle.label | userQuery | +| athena.js:66:22:66:30 | userQuery | semmle.label | userQuery | +| clients3.js:10:9:10:40 | maliciousInput | semmle.label | maliciousInput | +| clients3.js:10:26:10:33 | req.body | semmle.label | req.body | +| clients3.js:12:11:17:5 | params [Expression] | semmle.label | params [Expression] | +| clients3.js:12:20:17:5 | {\\n ... ,\\n } [Expression] | semmle.label | {\\n ... ,\\n } [Expression] | +| clients3.js:16:21:16:68 | "SELECT ... usInput | semmle.label | "SELECT ... usInput | +| clients3.js:16:55:16:68 | maliciousInput | semmle.label | maliciousInput | +| clients3.js:18:23:18:60 | new Sel ... params) | semmle.label | new Sel ... params) | +| clients3.js:18:54:18:59 | params [Expression] | semmle.label | params [Expression] | +| clients3.js:23:9:23:40 | maliciousInput | semmle.label | maliciousInput | +| clients3.js:23:26:23:33 | req.body | semmle.label | req.body | +| clients3.js:29:21:29:68 | "SELECT ... usInput | semmle.label | "SELECT ... usInput | +| clients3.js:29:55:29:68 | maliciousInput | semmle.label | maliciousInput | +| clients3.js:38:21:38:68 | "SELECT ... usInput | semmle.label | "SELECT ... usInput | +| clients3.js:38:55:38:68 | maliciousInput | semmle.label | maliciousInput | +| dynamodb.js:9:9:9:38 | maliciousInput | semmle.label | maliciousInput | +| dynamodb.js:9:26:9:33 | req.body | semmle.label | req.body | +| dynamodb.js:11:11:11:80 | statement | semmle.label | statement | +| dynamodb.js:11:64:11:77 | maliciousInput | semmle.label | maliciousInput | +| dynamodb.js:12:11:14:6 | command | semmle.label | command | +| dynamodb.js:12:21:14:6 | new Exe ... \\n }) | semmle.label | new Exe ... \\n }) | +| dynamodb.js:12:49:14:5 | {\\n ... t\\n } [Statement] | semmle.label | {\\n ... t\\n } [Statement] | +| dynamodb.js:13:20:13:28 | statement | semmle.label | statement | +| dynamodb.js:15:23:15:29 | command | semmle.label | command | +| dynamodb.js:17:11:17:93 | updateStatement | semmle.label | updateStatement | +| dynamodb.js:17:80:17:93 | maliciousInput | semmle.label | maliciousInput | +| dynamodb.js:18:11:20:6 | updateCommand | semmle.label | updateCommand | +| dynamodb.js:18:27:20:6 | new Exe ... \\n }) | semmle.label | new Exe ... \\n }) | +| dynamodb.js:18:55:20:5 | {\\n ... t\\n } [Statement] | semmle.label | {\\n ... t\\n } [Statement] | +| dynamodb.js:19:20:19:34 | updateStatement | semmle.label | updateStatement | +| dynamodb.js:21:23:21:35 | updateCommand | semmle.label | updateCommand | +| dynamodb.js:47:24:47:30 | command | semmle.label | command | +| dynamodb.js:56:9:56:38 | maliciousInput | semmle.label | maliciousInput | +| dynamodb.js:56:26:56:33 | req.body | semmle.label | req.body | +| dynamodb.js:58:20:58:77 | `SELECT ... nput}'` | semmle.label | `SELECT ... nput}'` | +| dynamodb.js:58:61:58:74 | maliciousInput | semmle.label | maliciousInput | +| dynamodb.js:64:28:64:85 | `SELECT ... nput}'` | semmle.label | `SELECT ... nput}'` | +| dynamodb.js:64:69:64:82 | maliciousInput | semmle.label | maliciousInput | +| dynamodb.js:67:28:67:85 | `SELECT ... nput}'` | semmle.label | `SELECT ... nput}'` | +| dynamodb.js:67:69:67:82 | maliciousInput | semmle.label | maliciousInput | | graphql.js:8:11:8:28 | id | semmle.label | id | | graphql.js:8:16:8:28 | req.params.id | semmle.label | req.params.id | | graphql.js:9:34:19:5 | `\\n ... }\\n ` | semmle.label | `\\n ... }\\n ` | @@ -803,6 +961,26 @@ nodes | pg-promise.js:60:20:60:24 | query | semmle.label | query | | pg-promise.js:63:23:63:27 | query | semmle.label | query | | pg-promise.js:64:16:64:20 | query | semmle.label | query | +| rds-client.js:8:11:8:36 | userQuery | semmle.label | userQuery | +| rds-client.js:8:23:8:30 | req.body | semmle.label | req.body | +| rds-client.js:13:11:18:5 | params1 [sql] | semmle.label | params1 [sql] | +| rds-client.js:13:21:18:5 | {\\n ... y\\n } [sql] | semmle.label | {\\n ... y\\n } [sql] | +| rds-client.js:17:14:17:22 | userQuery | semmle.label | userQuery | +| rds-client.js:19:23:19:58 | new Exe ... arams1) | semmle.label | new Exe ... arams1) | +| rds-client.js:19:51:19:57 | params1 [sql] | semmle.label | params1 [sql] | +| rds-client.js:29:11:34:5 | params [sqlStatements] | semmle.label | params [sqlStatements] | +| rds-client.js:29:20:34:5 | {\\n ... y\\n } [sqlStatements] | semmle.label | {\\n ... y\\n } [sqlStatements] | +| rds-client.js:33:24:33:32 | userQuery | semmle.label | userQuery | +| rds-client.js:36:23:36:51 | new Exe ... params) | semmle.label | new Exe ... params) | +| rds-client.js:36:45:36:50 | params [sqlStatements] | semmle.label | params [sqlStatements] | +| rds-client.js:44:11:44:36 | userQuery | semmle.label | userQuery | +| rds-client.js:44:23:44:30 | req.body | semmle.label | req.body | +| rds-client.js:45:11:45:40 | userQueries | semmle.label | userQueries | +| rds-client.js:45:25:45:32 | req.body | semmle.label | req.body | +| rds-client.js:53:14:53:22 | userQuery | semmle.label | userQuery | +| rds-client.js:61:24:61:34 | userQueries | semmle.label | userQueries | +| rds-client.js:61:40:61:42 | sql | semmle.label | sql | +| rds-client.js:61:50:61:52 | sql | semmle.label | sql | | redis.js:10:16:10:23 | req.body | semmle.label | req.body | | redis.js:10:16:10:27 | req.body.key | semmle.label | req.body.key | | redis.js:12:9:12:26 | key | semmle.label | key | diff --git a/javascript/ql/test/query-tests/Security/CWE-089/untyped/athena.js b/javascript/ql/test/query-tests/Security/CWE-089/untyped/athena.js new file mode 100644 index 000000000000..2b661d5d4aea --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-089/untyped/athena.js @@ -0,0 +1,72 @@ +const { AthenaClient, StartQueryExecutionCommand, CreateNamedQueryCommand, UpdateNamedQueryCommand } = require("@aws-sdk/client-athena"); +const AWS = require('aws-sdk'); +const express = require('express'); +const bodyParser = require('body-parser'); +const app = express(); +app.use(bodyParser.json()); + +app.post('/v3/athena/all', async (req, res) => { + const userQuery = req.body.query; // $ Source + + const client = new AthenaClient({ region: "us-east-1" }); + + const params1 = { + QueryString: "SQL" + userQuery, + QueryExecutionContext: { Database: "default" }, + ResultConfiguration: { OutputLocation: "s3://my-results/" } + }; + const p = new StartQueryExecutionCommand(params1); + await client.send(p); // $ Alert + + const params2 = { + Name: "user_query", + Database: "default", + QueryString: userQuery, + Description: "User-provided query" + }; + await client.send(new CreateNamedQueryCommand(params2)); // $ Alert -- This only stores query to database, not executed + + const params3 = { + NamedQueryId: "namedQueryId", + Name: "user_query_updated", + Database: "default", + QueryString: userQuery, + Description: "Updated user-provided query" + }; + await client.send(new UpdateNamedQueryCommand(params3)); // $ Alert -- This only stores query to database, not executed + + res.end(); +}); + + +app.post('/v2/athena/all', async (req, res) => { + const userQuery = req.body.query; // $ Source + + const athena = new AWS.Athena({ region: "us-east-1" }); + + const params1 = { + QueryString: userQuery, // $ Alert + QueryExecutionContext: { Database: "default" }, + ResultConfiguration: { OutputLocation: "s3://my-results/" } + }; + await athena.startQueryExecution(params1).promise(); + + const params2 = { + Name: "user_query", + Database: "default", + QueryString: userQuery, // $ Alert -- This only stores query to database, not executed + Description: "User-provided query" + }; + await athena.createNamedQuery(params2).promise(); + + const params3 = { + NamedQueryId: "namedQueryId", + Name: "user_query_updated", + Database: "default", + QueryString: userQuery, // $ Alert -- This only stores query to database, not executed + Description: "Updated user-provided query" + }; + await athena.updateNamedQuery(params3).promise(); + + res.end(); +}); diff --git a/javascript/ql/test/query-tests/Security/CWE-089/untyped/clients3.js b/javascript/ql/test/query-tests/Security/CWE-089/untyped/clients3.js new file mode 100644 index 000000000000..9c6bce426575 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-089/untyped/clients3.js @@ -0,0 +1,44 @@ +const { S3Client, SelectObjectContentCommand } = require("@aws-sdk/client-s3"); +const AWS = require('aws-sdk'); +const express = require('express'); +const bodyParser = require('body-parser'); + +const app = express(); +app.use(bodyParser.json()); + +app.post('/client/v3/execute', async (req, res) => { + let maliciousInput = req.body.filter; // $ Source + const client = new S3Client({ region: "us-east-1" }); + const params = { + Bucket: "my-bucket", + Key: "data.csv", + ExpressionType: "SQL", + Expression: "SELECT * FROM S3Object WHERE " + maliciousInput, + }; + await client.send(new SelectObjectContentCommand(params)); // $ Alert + res.end(); +}); + +app.post('/client/v2/execute', async (req, res) => { + let maliciousInput = req.body.filter; // $ Source + const s3 = new AWS.S3({ region: "us-east-1" }); + const params = { + Bucket: "my-bucket", + Key: "data.csv", + ExpressionType: "SQL", + Expression: "SELECT * FROM S3Object WHERE " + maliciousInput, // $ Alert + }; + await s3.selectObjectContent(params).promise(); + res.end(); + + const params1 = { + Bucket: "my-bucket", + Key: "data.csv", + ExpressionType: "SQL", + Expression: "SELECT * FROM S3Object WHERE " + maliciousInput, // $ Alert + }; + + s3.selectObjectContent(params1, (err, data) => { + res.end(); + }); +}); diff --git a/javascript/ql/test/query-tests/Security/CWE-089/untyped/dynamodb.js b/javascript/ql/test/query-tests/Security/CWE-089/untyped/dynamodb.js new file mode 100644 index 000000000000..ef9e3c3005ce --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-089/untyped/dynamodb.js @@ -0,0 +1,73 @@ +import {DynamoDBClient, ExecuteStatementCommand, BatchExecuteStatementCommand, DynamoDB} from "@aws-sdk/client-dynamodb"; +const express = require('express'); + +const app = express(); +const region = 'us-east-1'; + +app.post('/partiql/v3/execute', async (req, res) => { + const client = new DynamoDBClient({}); + let maliciousInput = req.body.data; // $ Source + + const statement = `SELECT * FROM Users WHERE username = '${maliciousInput}'`; + const command = new ExecuteStatementCommand({ + Statement: statement + }); + await client.send(command); // $ Alert + + const updateStatement = "UPDATE Users SET status = 'active' WHERE id = " + maliciousInput; + const updateCommand = new ExecuteStatementCommand({ + Statement: updateStatement + }); + await client.send(updateCommand); // $ Alert + + + const batchInput = { + Statements: [{ + Statement: `SELECT * FROM Users WHERE username = '${maliciousInput}'` + }, + { + Statement: "UPDATE Users SET role = 'user' WHERE username = bob" + } + ] + }; + + const batchCommand = new BatchExecuteStatementCommand(batchInput); + await client.send(batchCommand); // $ MISSING: Alert + + const batchInput2 = { + Statements: maliciousInput.map(input => ({ + Statement: `SELECT * FROM SensitiveData WHERE username = '${input}'` + })) + }; + + const batchCommand2 = new BatchExecuteStatementCommand(batchInput2); + await client.send(batchCommand2); // $ MISSING: Alert + + const client2 = new DynamoDB({}); + await client2.send(command); // $ Alert + await client2.send(batchCommand); // $ MISSING: Alert +}); + +app.post('/partiql/v2/execute', async (req, res) => { + const AWS = require('aws-sdk'); + const dynamodb = new AWS.DynamoDB({ + region: 'us-east-1' + }); + let maliciousInput = req.body.data; // $ Source + const params = { + Statement: `SELECT * FROM Users WHERE username = '${maliciousInput}'` // $ Alert + }; + + dynamodb.executeStatement(params, function(err, data) {}); + const params2 = { + Statements: [{ + Statement: `SELECT * FROM Users WHERE username = '${maliciousInput}'` // $ Alert + }, + { + Statement: `SELECT * FROM Users WHERE username = '${maliciousInput}'` // $ Alert + } + ] + }; + + dynamodb.batchExecuteStatement(params2, function(err, data) {}); +}); diff --git a/javascript/ql/test/query-tests/Security/CWE-089/untyped/rds-client.js b/javascript/ql/test/query-tests/Security/CWE-089/untyped/rds-client.js new file mode 100644 index 000000000000..35d41e145f98 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-089/untyped/rds-client.js @@ -0,0 +1,68 @@ +const { RDSDataClient, BatchExecuteStatementCommand, ExecuteStatementCommand, ExecuteSqlCommand } = require("@aws-sdk/client-rds-data"); +const express = require('express'); +const bodyParser = require('body-parser'); +const app = express(); +app.use(bodyParser.json()); + +app.post('/v3/rds/all', async (req, res) => { + const userQuery = req.body.query; // $ Source + const userQueries = req.body.queries; // $ MISSING: Source + + const client = new RDSDataClient({ region: "us-east-1" }); + + const params1 = { + resourceArn: "arn:aws:rds:us-east-1:123456789012:cluster:my-aurora-cluster", + secretArn: "arn:aws:secretsmanager:us-east-1:123456789012:secret:my-secret", + database: "userDatabase", + sql: userQuery + }; + await client.send(new ExecuteStatementCommand(params1)); // $ Alert + + const params2 = { + resourceArn: "arn:aws:rds:us-east-1:123456789012:cluster:my-aurora-cluster", + secretArn: "arn:aws:secretsmanager:us-east-1:123456789012:secret:my-secret", + database: "userDatabase", + parameterSets: userQueries.map(sql => ({ sql })) + }; + await client.send(new BatchExecuteStatementCommand(params2)); // $ MISSING: Alert + + const params = { + resourceArn: "...", + secretArn: "...", + database: "userDatabase", + sqlStatements: userQuery + }; + + await client.send(new ExecuteSqlCommand(params)); // $ Alert + + res.end(); +}); + +const AWS = require('aws-sdk'); + +app.post('/v2/rds/all', async (req, res) => { + const userQuery = req.body.query; // $ Source + const userQueries = req.body.queries; // $ Source + + const rdsData = new AWS.RDSDataService({ region: "us-east-1" }); + + const params1 = { + resourceArn: "arn:aws:rds:us-east-1:123456789012:cluster:my-aurora-cluster", + secretArn: "arn:aws:secretsmanager:us-east-1:123456789012:secret:my-secret", + database: "userDatabase", + sql: userQuery // $ Alert + }; + await rdsData.executeStatement(params1).promise(); + + const params2 = { + resourceArn: "arn:aws:rds:us-east-1:123456789012:cluster:my-aurora-cluster", + secretArn: "arn:aws:secretsmanager:us-east-1:123456789012:secret:my-secret", + database: "userDatabase", + parameterSets: userQueries.map(sql => ({ sql })) // $ Alert + }; + await rdsData.batchExecuteStatement(params2).promise(); + + res.end(); +}); + +app.listen(3000); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy