From 2915d6b9d87dc32122a467aef54aa4c9995cc241 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Wed, 23 Jul 2025 14:37:21 -0400 Subject: [PATCH 1/5] Add sensitive exposure split query --- .../SensitiveExposureLikely.md | 30 ++++++++++++++++++ .../SensitiveExposureLikely.ql | 31 +++++++++++++++++++ .../sensitive-exposure-likely.expected | 17 ++++++++++ .../sensitive-exposure-likely.js | 8 +++++ .../sensitive-exposure-likely.qlref | 1 + 5 files changed, 87 insertions(+) create mode 100644 javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureLikely.md create mode 100644 javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureLikely.ql create mode 100644 javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.expected create mode 100644 javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.js create mode 100644 javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.qlref diff --git a/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureLikely.md b/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureLikely.md new file mode 100644 index 000000000..0418e5305 --- /dev/null +++ b/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureLikely.md @@ -0,0 +1,30 @@ +# CAP Insertion of Sensitive Information into Log File + +If sensitive information is written to a log entry using the CAP Node.js logging API, a malicious user may be able to gain access to user data. + +Data that may expose system information such as full path names, system information, usernames and passwords should not be logged. + +## Recommendation + +CAP applications should not log sensitive information. + +## Examples + +This CAP service directly logs the sensitive information. + +``` javascript +import cds from '@sap/cds' +const LOG = cds.log("logger"); + +class SampleVulnService extends cds.ApplicationService { + init() { + LOG.info(`[INFO] Environment: ${JSON.stringify(process.env)}`); // CAP log exposure alert + } +} +``` + +## References + +- OWASP 2021: [Security Logging and Monitoring Failures](https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures/). +- OWASP: [Logging Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html). +- OWASP: [User Privacy Protection Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/User_Privacy_Protection_Cheat_Sheet.html). \ No newline at end of file diff --git a/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureLikely.ql b/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureLikely.ql new file mode 100644 index 000000000..0d70dc2fb --- /dev/null +++ b/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureLikely.ql @@ -0,0 +1,31 @@ +/** + * @name Insertion of sensitive information into log files + * @description Writing heuristically sensitive information to log files can allow that + * information to be leaked to an attacker more easily. + * @kind path-problem + * @problem.severity warning + * @security-severity 7.5 + * @precision low + * @id js/cap-sensitive-log-likely + * @tags security + * external/cwe/cwe-532 + */ + +import javascript +import advanced_security.javascript.frameworks.cap.CDS +import advanced_security.javascript.frameworks.cap.CAPLogInjectionQuery +private import semmle.javascript.security.dataflow.CleartextLoggingCustomizations::CleartextLogging as CleartextLogging +import DataFlow::PathGraph + +class SensitiveLogExposureConfig extends TaintTracking::Configuration { + SensitiveLogExposureConfig() { this = "SensitiveLogExposure" } + + override predicate isSource(DataFlow::Node source) { source instanceof CleartextLogging::Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof CdsLogSink } +} + +from SensitiveLogExposureConfig config, DataFlow::PathNode source, DataFlow::PathNode sink +where config.hasFlowPath(source, sink) +select sink, source, sink, "This logs sensitive data returned by $@ as clear text.", + source.getNode(), source.getNode().(CleartextLogging::Source).describe() diff --git a/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.expected b/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.expected new file mode 100644 index 000000000..1f4853756 --- /dev/null +++ b/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.expected @@ -0,0 +1,17 @@ +WARNING: module 'PathGraph' has been deprecated and may be removed in future (SensitiveExposureLikely.ql:18,8-27) +WARNING: type 'Configuration' has been deprecated and may be removed in future (SensitiveExposureLikely.ql:20,42-70) +WARNING: type 'PathNode' has been deprecated and may be removed in future (SensitiveExposureLikely.ql:28,41-59) +WARNING: type 'PathNode' has been deprecated and may be removed in future (SensitiveExposureLikely.ql:28,68-86) +nodes +| sensitive-exposure-likely.js:6:18:6:69 | `[INFO] ... .env)}` | +| sensitive-exposure-likely.js:6:18:6:69 | `[INFO] ... .env)}` | +| sensitive-exposure-likely.js:6:41:6:67 | JSON.st ... ss.env) | +| sensitive-exposure-likely.js:6:56:6:66 | process.env | +| sensitive-exposure-likely.js:6:56:6:66 | process.env | +edges +| sensitive-exposure-likely.js:6:41:6:67 | JSON.st ... ss.env) | sensitive-exposure-likely.js:6:18:6:69 | `[INFO] ... .env)}` | +| sensitive-exposure-likely.js:6:41:6:67 | JSON.st ... ss.env) | sensitive-exposure-likely.js:6:18:6:69 | `[INFO] ... .env)}` | +| sensitive-exposure-likely.js:6:56:6:66 | process.env | sensitive-exposure-likely.js:6:41:6:67 | JSON.st ... ss.env) | +| sensitive-exposure-likely.js:6:56:6:66 | process.env | sensitive-exposure-likely.js:6:41:6:67 | JSON.st ... ss.env) | +#select +| sensitive-exposure-likely.js:6:18:6:69 | `[INFO] ... .env)}` | sensitive-exposure-likely.js:6:56:6:66 | process.env | sensitive-exposure-likely.js:6:18:6:69 | `[INFO] ... .env)}` | This logs sensitive data returned by $@ as clear text. | sensitive-exposure-likely.js:6:56:6:66 | process.env | process environment | diff --git a/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.js b/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.js new file mode 100644 index 000000000..f4de93a09 --- /dev/null +++ b/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.js @@ -0,0 +1,8 @@ +import cds from '@sap/cds' +const LOG = cds.log("logger"); + +class SampleVulnService extends cds.ApplicationService { + init() { + LOG.info(`[INFO] Environment: ${JSON.stringify(process.env)}`); // CAP log exposure alert + } +} \ No newline at end of file diff --git a/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.qlref b/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.qlref new file mode 100644 index 000000000..396454622 --- /dev/null +++ b/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.qlref @@ -0,0 +1 @@ +sensitive-exposure/SensitiveExposureLikely.ql \ No newline at end of file From d7995ce232350ec0b78fb6cf6066ec337c2f9e1a Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Fri, 1 Aug 2025 16:52:50 -0400 Subject: [PATCH 2/5] Rename sensitive-exposure-likely to heuristic --- ...y.md => SensitiveExposureHeuristicSource.md} | 0 ...y.ql => SensitiveExposureHeuristicSource.ql} | 0 ...sensitive-exposure-heuristic-source.expected | 17 +++++++++++++++++ ...s => sensitive-exposure-heuristic-source.js} | 0 .../sensitive-exposure-heuristic-source.qlref | 1 + .../sensitive-exposure-likely.expected | 17 ----------------- .../sensitive-exposure-likely.qlref | 1 - 7 files changed, 18 insertions(+), 18 deletions(-) rename javascript/frameworks/cap/src/sensitive-exposure/{SensitiveExposureLikely.md => SensitiveExposureHeuristicSource.md} (100%) rename javascript/frameworks/cap/src/sensitive-exposure/{SensitiveExposureLikely.ql => SensitiveExposureHeuristicSource.ql} (100%) create mode 100644 javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-heuristic-source.expected rename javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/{sensitive-exposure-likely.js => sensitive-exposure-heuristic-source.js} (100%) create mode 100644 javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-heuristic-source.qlref delete mode 100644 javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.expected delete mode 100644 javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.qlref diff --git a/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureLikely.md b/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.md similarity index 100% rename from javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureLikely.md rename to javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.md diff --git a/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureLikely.ql b/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.ql similarity index 100% rename from javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureLikely.ql rename to javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.ql diff --git a/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-heuristic-source.expected b/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-heuristic-source.expected new file mode 100644 index 000000000..97d6d534f --- /dev/null +++ b/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-heuristic-source.expected @@ -0,0 +1,17 @@ +WARNING: module 'PathGraph' has been deprecated and may be removed in future (SensitiveExposureHeuristicSource.ql:18,8-27) +WARNING: type 'Configuration' has been deprecated and may be removed in future (SensitiveExposureHeuristicSource.ql:20,42-70) +WARNING: type 'PathNode' has been deprecated and may be removed in future (SensitiveExposureHeuristicSource.ql:28,41-59) +WARNING: type 'PathNode' has been deprecated and may be removed in future (SensitiveExposureHeuristicSource.ql:28,68-86) +nodes +| sensitive-exposure-heuristic-source.js:6:18:6:69 | `[INFO] ... .env)}` | +| sensitive-exposure-heuristic-source.js:6:18:6:69 | `[INFO] ... .env)}` | +| sensitive-exposure-heuristic-source.js:6:41:6:67 | JSON.st ... ss.env) | +| sensitive-exposure-heuristic-source.js:6:56:6:66 | process.env | +| sensitive-exposure-heuristic-source.js:6:56:6:66 | process.env | +edges +| sensitive-exposure-heuristic-source.js:6:41:6:67 | JSON.st ... ss.env) | sensitive-exposure-heuristic-source.js:6:18:6:69 | `[INFO] ... .env)}` | +| sensitive-exposure-heuristic-source.js:6:41:6:67 | JSON.st ... ss.env) | sensitive-exposure-heuristic-source.js:6:18:6:69 | `[INFO] ... .env)}` | +| sensitive-exposure-heuristic-source.js:6:56:6:66 | process.env | sensitive-exposure-heuristic-source.js:6:41:6:67 | JSON.st ... ss.env) | +| sensitive-exposure-heuristic-source.js:6:56:6:66 | process.env | sensitive-exposure-heuristic-source.js:6:41:6:67 | JSON.st ... ss.env) | +#select +| sensitive-exposure-heuristic-source.js:6:18:6:69 | `[INFO] ... .env)}` | sensitive-exposure-heuristic-source.js:6:56:6:66 | process.env | sensitive-exposure-heuristic-source.js:6:18:6:69 | `[INFO] ... .env)}` | This logs sensitive data returned by $@ as clear text. | sensitive-exposure-heuristic-source.js:6:56:6:66 | process.env | process environment | diff --git a/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.js b/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-heuristic-source.js similarity index 100% rename from javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.js rename to javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-heuristic-source.js diff --git a/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-heuristic-source.qlref b/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-heuristic-source.qlref new file mode 100644 index 000000000..3ac31337c --- /dev/null +++ b/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-heuristic-source.qlref @@ -0,0 +1 @@ +sensitive-exposure/SensitiveExposureHeuristicSource.ql \ No newline at end of file diff --git a/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.expected b/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.expected deleted file mode 100644 index 1f4853756..000000000 --- a/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.expected +++ /dev/null @@ -1,17 +0,0 @@ -WARNING: module 'PathGraph' has been deprecated and may be removed in future (SensitiveExposureLikely.ql:18,8-27) -WARNING: type 'Configuration' has been deprecated and may be removed in future (SensitiveExposureLikely.ql:20,42-70) -WARNING: type 'PathNode' has been deprecated and may be removed in future (SensitiveExposureLikely.ql:28,41-59) -WARNING: type 'PathNode' has been deprecated and may be removed in future (SensitiveExposureLikely.ql:28,68-86) -nodes -| sensitive-exposure-likely.js:6:18:6:69 | `[INFO] ... .env)}` | -| sensitive-exposure-likely.js:6:18:6:69 | `[INFO] ... .env)}` | -| sensitive-exposure-likely.js:6:41:6:67 | JSON.st ... ss.env) | -| sensitive-exposure-likely.js:6:56:6:66 | process.env | -| sensitive-exposure-likely.js:6:56:6:66 | process.env | -edges -| sensitive-exposure-likely.js:6:41:6:67 | JSON.st ... ss.env) | sensitive-exposure-likely.js:6:18:6:69 | `[INFO] ... .env)}` | -| sensitive-exposure-likely.js:6:41:6:67 | JSON.st ... ss.env) | sensitive-exposure-likely.js:6:18:6:69 | `[INFO] ... .env)}` | -| sensitive-exposure-likely.js:6:56:6:66 | process.env | sensitive-exposure-likely.js:6:41:6:67 | JSON.st ... ss.env) | -| sensitive-exposure-likely.js:6:56:6:66 | process.env | sensitive-exposure-likely.js:6:41:6:67 | JSON.st ... ss.env) | -#select -| sensitive-exposure-likely.js:6:18:6:69 | `[INFO] ... .env)}` | sensitive-exposure-likely.js:6:56:6:66 | process.env | sensitive-exposure-likely.js:6:18:6:69 | `[INFO] ... .env)}` | This logs sensitive data returned by $@ as clear text. | sensitive-exposure-likely.js:6:56:6:66 | process.env | process environment | diff --git a/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.qlref b/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.qlref deleted file mode 100644 index 396454622..000000000 --- a/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-likely.qlref +++ /dev/null @@ -1 +0,0 @@ -sensitive-exposure/SensitiveExposureLikely.ql \ No newline at end of file From ad9e4febf24dbec0ab7fdef9150717440a599531 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Fri, 1 Aug 2025 16:54:05 -0400 Subject: [PATCH 3/5] Change query id SensitiveExposureHeuristicSource.ql --- .../src/sensitive-exposure/SensitiveExposureHeuristicSource.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.ql b/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.ql index 0d70dc2fb..d4e200ad8 100644 --- a/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.ql +++ b/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.ql @@ -6,7 +6,7 @@ * @problem.severity warning * @security-severity 7.5 * @precision low - * @id js/cap-sensitive-log-likely + * @id js/cap-sensitive-log-heurisitic-source * @tags security * external/cwe/cwe-532 */ From c6ad1237b1212b7ca408d9a2cc406ecf3e35482c Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Tue, 5 Aug 2025 12:22:11 -0400 Subject: [PATCH 4/5] Address review comments --- .../SensitiveExposureHeuristicSource.md | 5 ++-- .../SensitiveExposureHeuristicSource.ql | 27 ++++++++++++----- ...nsitive-exposure-heuristic-source.expected | 29 ++++++++++--------- .../sensitive-exposure-heuristic-source.js | 12 ++++++++ 4 files changed, 50 insertions(+), 23 deletions(-) diff --git a/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.md b/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.md index 0418e5305..986b12c58 100644 --- a/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.md +++ b/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.md @@ -6,11 +6,11 @@ Data that may expose system information such as full path names, system informat ## Recommendation -CAP applications should not log sensitive information. +CAP applications should not log sensitive information. Sensitive information can include: full path names, system information, usernames, passwords or any personally identifiable information. Make sure to log only information that is not sensitive, or obfuscate/encrypt sensitive information any time that it is logged. ## Examples -This CAP service directly logs the sensitive information. +This CAP service directly logs the sensitive information. Potential attackers may gain access to this sensitive information when the log output is displayed or when the attacker gains access to the log, and the info is not obfuscated or encrypted. ``` javascript import cds from '@sap/cds' @@ -19,6 +19,7 @@ const LOG = cds.log("logger"); class SampleVulnService extends cds.ApplicationService { init() { LOG.info(`[INFO] Environment: ${JSON.stringify(process.env)}`); // CAP log exposure alert + LOG.info(`[INFO] Environment: ${JSON.stringify(process.env)}`); // CAP log exposure alert } } ``` diff --git a/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.ql b/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.ql index d4e200ad8..8b5f24bb5 100644 --- a/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.ql +++ b/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.ql @@ -15,17 +15,30 @@ import javascript import advanced_security.javascript.frameworks.cap.CDS import advanced_security.javascript.frameworks.cap.CAPLogInjectionQuery private import semmle.javascript.security.dataflow.CleartextLoggingCustomizations::CleartextLogging as CleartextLogging -import DataFlow::PathGraph -class SensitiveLogExposureConfig extends TaintTracking::Configuration { - SensitiveLogExposureConfig() { this = "SensitiveLogExposure" } +module SensitiveLogExposureConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof CleartextLogging::Source } - override predicate isSource(DataFlow::Node source) { source instanceof CleartextLogging::Source } + predicate isSink(DataFlow::Node sink) { sink instanceof CdsLogSink } - override predicate isSink(DataFlow::Node sink) { sink instanceof CdsLogSink } + predicate isAdditionalFlowStep(DataFlow::Node src, DataFlow::Node trg) { + CleartextLogging::isAdditionalTaintStep(src, trg) + } + + predicate isBarrier(DataFlow::Node sink) { sink instanceof CleartextLogging::Barrier } + + predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet contents) { + // Assume all properties of a logged object are themselves logged. + contents = DataFlow::ContentSet::anyProperty() and + isSink(node) + } } -from SensitiveLogExposureConfig config, DataFlow::PathNode source, DataFlow::PathNode sink -where config.hasFlowPath(source, sink) +module SensitiveLogExposureFlow = TaintTracking::Global; + +import SensitiveLogExposureFlow::PathGraph + +from SensitiveLogExposureFlow::PathNode source, SensitiveLogExposureFlow::PathNode sink +where SensitiveLogExposureFlow::flowPath(source, sink) select sink, source, sink, "This logs sensitive data returned by $@ as clear text.", source.getNode(), source.getNode().(CleartextLogging::Source).describe() diff --git a/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-heuristic-source.expected b/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-heuristic-source.expected index 97d6d534f..2493e4b7a 100644 --- a/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-heuristic-source.expected +++ b/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-heuristic-source.expected @@ -1,17 +1,18 @@ -WARNING: module 'PathGraph' has been deprecated and may be removed in future (SensitiveExposureHeuristicSource.ql:18,8-27) -WARNING: type 'Configuration' has been deprecated and may be removed in future (SensitiveExposureHeuristicSource.ql:20,42-70) -WARNING: type 'PathNode' has been deprecated and may be removed in future (SensitiveExposureHeuristicSource.ql:28,41-59) -WARNING: type 'PathNode' has been deprecated and may be removed in future (SensitiveExposureHeuristicSource.ql:28,68-86) -nodes -| sensitive-exposure-heuristic-source.js:6:18:6:69 | `[INFO] ... .env)}` | -| sensitive-exposure-heuristic-source.js:6:18:6:69 | `[INFO] ... .env)}` | -| sensitive-exposure-heuristic-source.js:6:41:6:67 | JSON.st ... ss.env) | -| sensitive-exposure-heuristic-source.js:6:56:6:66 | process.env | -| sensitive-exposure-heuristic-source.js:6:56:6:66 | process.env | edges -| sensitive-exposure-heuristic-source.js:6:41:6:67 | JSON.st ... ss.env) | sensitive-exposure-heuristic-source.js:6:18:6:69 | `[INFO] ... .env)}` | -| sensitive-exposure-heuristic-source.js:6:41:6:67 | JSON.st ... ss.env) | sensitive-exposure-heuristic-source.js:6:18:6:69 | `[INFO] ... .env)}` | -| sensitive-exposure-heuristic-source.js:6:56:6:66 | process.env | sensitive-exposure-heuristic-source.js:6:41:6:67 | JSON.st ... ss.env) | -| sensitive-exposure-heuristic-source.js:6:56:6:66 | process.env | sensitive-exposure-heuristic-source.js:6:41:6:67 | JSON.st ... ss.env) | +| sensitive-exposure-heuristic-source.js:6:41:6:67 | JSON.st ... ss.env) | sensitive-exposure-heuristic-source.js:6:18:6:69 | `[INFO] ... .env)}` | provenance | | +| sensitive-exposure-heuristic-source.js:6:56:6:66 | process.env | sensitive-exposure-heuristic-source.js:6:41:6:67 | JSON.st ... ss.env) | provenance | | +| sensitive-exposure-heuristic-source.js:8:13:10:9 | obj [x] | sensitive-exposure-heuristic-source.js:11:18:11:20 | obj | provenance | | +| sensitive-exposure-heuristic-source.js:8:19:10:9 | {\\n ... } [x] | sensitive-exposure-heuristic-source.js:8:13:10:9 | obj [x] | provenance | | +| sensitive-exposure-heuristic-source.js:9:16:9:23 | password | sensitive-exposure-heuristic-source.js:8:19:10:9 | {\\n ... } [x] | provenance | | +nodes +| sensitive-exposure-heuristic-source.js:6:18:6:69 | `[INFO] ... .env)}` | semmle.label | `[INFO] ... .env)}` | +| sensitive-exposure-heuristic-source.js:6:41:6:67 | JSON.st ... ss.env) | semmle.label | JSON.st ... ss.env) | +| sensitive-exposure-heuristic-source.js:6:56:6:66 | process.env | semmle.label | process.env | +| sensitive-exposure-heuristic-source.js:8:13:10:9 | obj [x] | semmle.label | obj [x] | +| sensitive-exposure-heuristic-source.js:8:19:10:9 | {\\n ... } [x] | semmle.label | {\\n ... } [x] | +| sensitive-exposure-heuristic-source.js:9:16:9:23 | password | semmle.label | password | +| sensitive-exposure-heuristic-source.js:11:18:11:20 | obj | semmle.label | obj | +subpaths #select | sensitive-exposure-heuristic-source.js:6:18:6:69 | `[INFO] ... .env)}` | sensitive-exposure-heuristic-source.js:6:56:6:66 | process.env | sensitive-exposure-heuristic-source.js:6:18:6:69 | `[INFO] ... .env)}` | This logs sensitive data returned by $@ as clear text. | sensitive-exposure-heuristic-source.js:6:56:6:66 | process.env | process environment | +| sensitive-exposure-heuristic-source.js:11:18:11:20 | obj | sensitive-exposure-heuristic-source.js:9:16:9:23 | password | sensitive-exposure-heuristic-source.js:11:18:11:20 | obj | This logs sensitive data returned by $@ as clear text. | sensitive-exposure-heuristic-source.js:9:16:9:23 | password | an access to password | diff --git a/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-heuristic-source.js b/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-heuristic-source.js index f4de93a09..aa76e4759 100644 --- a/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-heuristic-source.js +++ b/javascript/frameworks/cap/test/queries/sensitive-exposure/sensitive-exposure-js-all-sinks/sensitive-exposure-heuristic-source.js @@ -4,5 +4,17 @@ const LOG = cds.log("logger"); class SampleVulnService extends cds.ApplicationService { init() { LOG.info(`[INFO] Environment: ${JSON.stringify(process.env)}`); // CAP log exposure alert + + var obj = { + x: password + }; + LOG.info(obj); // CAP log exposure alert + + LOG.info(obj.x.replace(/./g, "*")); // NO CAP log exposure alert - replace as sanitizer + + var user = { + password: encryptLib.encryptPassword(password) + }; + LOG.info(user); // NO CAP log exposure alert - encrypted data is fine } } \ No newline at end of file From 02910223c4987e1d0dbb5aabb1dcd0859572e466 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Tue, 5 Aug 2025 14:29:30 -0400 Subject: [PATCH 5/5] Address review comments second round --- .../SensitiveExposureHeuristicSource.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.md b/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.md index 986b12c58..00889f062 100644 --- a/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.md +++ b/javascript/frameworks/cap/src/sensitive-exposure/SensitiveExposureHeuristicSource.md @@ -4,6 +4,8 @@ If sensitive information is written to a log entry using the CAP Node.js logging Data that may expose system information such as full path names, system information, usernames and passwords should not be logged. +This query is similar to `js/cap-sensitive-log` in that the sinks are CAP logging facilities. The sources however are the same (exclusively) as the out of the box CodeQL query for [clear text logging](https://codeql.github.com/codeql-query-help/javascript/js-clear-text-logging/). + ## Recommendation CAP applications should not log sensitive information. Sensitive information can include: full path names, system information, usernames, passwords or any personally identifiable information. Make sure to log only information that is not sensitive, or obfuscate/encrypt sensitive information any time that it is logged. @@ -19,7 +21,18 @@ const LOG = cds.log("logger"); class SampleVulnService extends cds.ApplicationService { init() { LOG.info(`[INFO] Environment: ${JSON.stringify(process.env)}`); // CAP log exposure alert - LOG.info(`[INFO] Environment: ${JSON.stringify(process.env)}`); // CAP log exposure alert + var obj = { + x: password + }; + + LOG.info(obj); // CAP log exposure alert + + LOG.info(obj.x.replace(/./g, "*")); // NO CAP log exposure alert - replace call acts as sanitizer + + var user = { + password: encryptLib.encryptPassword(password) + }; + LOG.info(user); // NO CAP log exposure alert - the data is encrypted } } ```