From aad9d93b69194020f4a76f6c75a895559a257fc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Tue, 3 Jun 2025 20:09:40 +0200 Subject: [PATCH 1/2] Go: mass enable diff-informed data flow An auto-generated patch that enables diff-informed data flow in the obvious cases. Builds on https://github.com/github/codeql/pull/18345 and https://github.com/github/codeql-patch/pull/88 --- go/ql/lib/semmle/go/security/CleartextLogging.qll | 2 ++ go/ql/lib/semmle/go/security/ExternalAPIs.qll | 2 ++ go/ql/lib/semmle/go/security/LogInjection.qll | 2 ++ go/ql/lib/semmle/go/security/MissingJwtSignatureCheck.qll | 2 ++ go/ql/lib/semmle/go/security/OpenUrlRedirect.qll | 2 ++ go/ql/lib/semmle/go/security/SqlInjection.qll | 2 ++ go/ql/lib/semmle/go/security/StoredCommand.qll | 2 ++ go/ql/lib/semmle/go/security/StoredXss.qll | 2 ++ go/ql/lib/semmle/go/security/StringBreak.qll | 2 ++ go/ql/lib/semmle/go/security/TaintedPath.qll | 2 ++ go/ql/lib/semmle/go/security/UncontrolledAllocationSize.qll | 2 ++ go/ql/lib/semmle/go/security/UnsafeUnzipSymlink.qll | 2 ++ go/ql/lib/semmle/go/security/XPathInjection.qll | 2 ++ go/ql/lib/semmle/go/security/ZipSlip.qll | 2 ++ go/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql | 2 ++ go/ql/src/Security/CWE-020/MissingRegexpAnchor.ql | 2 ++ go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql | 2 ++ go/ql/src/Security/CWE-209/StackTraceExposure.ql | 2 ++ go/ql/src/Security/CWE-326/InsufficientKeySize.ql | 2 ++ go/ql/src/Security/CWE-352/ConstantOauth2State.ql | 2 ++ go/ql/src/Security/CWE-640/EmailInjection.qll | 2 ++ go/ql/src/experimental/CWE-090/LDAPInjection.qll | 2 ++ go/ql/src/experimental/CWE-203/Timing.ql | 2 ++ go/ql/src/experimental/CWE-285/PamAuthBypass.ql | 4 ++++ .../experimental/CWE-287/ImproperLdapAuthCustomizations.qll | 2 ++ go/ql/src/experimental/CWE-321-V2/HardCodedKeys.ql | 2 ++ .../CWE-327/WeakCryptoAlgorithmCustomizations.qll | 2 ++ go/ql/src/experimental/CWE-369/DivideByZero.ql | 2 ++ go/ql/src/experimental/CWE-74/DsnInjectionCustomizations.qll | 2 ++ go/ql/src/experimental/frameworks/DecompressionBombs.qll | 2 ++ 30 files changed, 62 insertions(+) diff --git a/go/ql/lib/semmle/go/security/CleartextLogging.qll b/go/ql/lib/semmle/go/security/CleartextLogging.qll index 2e0c9665c4b6..5218d03d9081 100644 --- a/go/ql/lib/semmle/go/security/CleartextLogging.qll +++ b/go/ql/lib/semmle/go/security/CleartextLogging.qll @@ -46,6 +46,8 @@ module CleartextLogging { // Also exclude protobuf field fetches, since they amount to single field reads. not any(Protobuf::GetMethod gm).taintStep(src, trg) } + + predicate observeDiffInformedIncrementalMode() { any() } } /** diff --git a/go/ql/lib/semmle/go/security/ExternalAPIs.qll b/go/ql/lib/semmle/go/security/ExternalAPIs.qll index 6799099b999f..4a561c17136e 100644 --- a/go/ql/lib/semmle/go/security/ExternalAPIs.qll +++ b/go/ql/lib/semmle/go/security/ExternalAPIs.qll @@ -197,6 +197,8 @@ private module UntrustedDataToUnknownExternalApiConfig implements DataFlow::Conf predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource } predicate isSink(DataFlow::Node sink) { sink instanceof UnknownExternalApiDataNode } + + predicate observeDiffInformedIncrementalMode() { any() } } /** diff --git a/go/ql/lib/semmle/go/security/LogInjection.qll b/go/ql/lib/semmle/go/security/LogInjection.qll index d8bc586ed916..3db7e27c7815 100644 --- a/go/ql/lib/semmle/go/security/LogInjection.qll +++ b/go/ql/lib/semmle/go/security/LogInjection.qll @@ -21,6 +21,8 @@ module LogInjection { predicate isSink(DataFlow::Node sink) { sink instanceof Sink } predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof Sanitizer } + + predicate observeDiffInformedIncrementalMode() { any() } } /** Tracks taint flow for reasoning about log injection vulnerabilities. */ diff --git a/go/ql/lib/semmle/go/security/MissingJwtSignatureCheck.qll b/go/ql/lib/semmle/go/security/MissingJwtSignatureCheck.qll index 73605d65b024..15afe81944ff 100644 --- a/go/ql/lib/semmle/go/security/MissingJwtSignatureCheck.qll +++ b/go/ql/lib/semmle/go/security/MissingJwtSignatureCheck.qll @@ -23,6 +23,8 @@ module MissingJwtSignatureCheck { predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { any(AdditionalFlowStep s).step(nodeFrom, nodeTo) } + + predicate observeDiffInformedIncrementalMode() { any() } } /** Tracks taint flow for reasoning about JWT vulnerabilities. */ diff --git a/go/ql/lib/semmle/go/security/OpenUrlRedirect.qll b/go/ql/lib/semmle/go/security/OpenUrlRedirect.qll index bfe47f260cd6..1d2d7a1c60bb 100644 --- a/go/ql/lib/semmle/go/security/OpenUrlRedirect.qll +++ b/go/ql/lib/semmle/go/security/OpenUrlRedirect.qll @@ -54,6 +54,8 @@ module OpenUrlRedirect { or hostnameSanitizingPrefixEdge(node, _) } + + predicate observeDiffInformedIncrementalMode() { any() } } /** Tracks taint flow from unvalidated, untrusted data to URL redirections. */ diff --git a/go/ql/lib/semmle/go/security/SqlInjection.qll b/go/ql/lib/semmle/go/security/SqlInjection.qll index e24b30f40d38..5b7513090258 100644 --- a/go/ql/lib/semmle/go/security/SqlInjection.qll +++ b/go/ql/lib/semmle/go/security/SqlInjection.qll @@ -23,6 +23,8 @@ module SqlInjection { } predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer } + + predicate observeDiffInformedIncrementalMode() { any() } } /** Tracks taint flow for reasoning about SQL-injection vulnerabilities. */ diff --git a/go/ql/lib/semmle/go/security/StoredCommand.qll b/go/ql/lib/semmle/go/security/StoredCommand.qll index 38555370cfcc..983f739bdab2 100644 --- a/go/ql/lib/semmle/go/security/StoredCommand.qll +++ b/go/ql/lib/semmle/go/security/StoredCommand.qll @@ -26,6 +26,8 @@ module StoredCommand { predicate isSink(DataFlow::Node sink) { sink instanceof CommandInjection::Sink } predicate isBarrier(DataFlow::Node node) { node instanceof CommandInjection::Sanitizer } + + predicate observeDiffInformedIncrementalMode() { any() } } /** Tracks taint flow for reasoning about command-injection vulnerabilities. */ diff --git a/go/ql/lib/semmle/go/security/StoredXss.qll b/go/ql/lib/semmle/go/security/StoredXss.qll index 2bf6bf248048..3bea8e8c1e00 100644 --- a/go/ql/lib/semmle/go/security/StoredXss.qll +++ b/go/ql/lib/semmle/go/security/StoredXss.qll @@ -22,6 +22,8 @@ module StoredXss { predicate isSink(DataFlow::Node sink) { sink instanceof Sink } predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer } + + predicate observeDiffInformedIncrementalMode() { any() } } /** Tracks taint flow for reasoning about XSS. */ diff --git a/go/ql/lib/semmle/go/security/StringBreak.qll b/go/ql/lib/semmle/go/security/StringBreak.qll index 02b4c5b3313b..87a676b6f97f 100644 --- a/go/ql/lib/semmle/go/security/StringBreak.qll +++ b/go/ql/lib/semmle/go/security/StringBreak.qll @@ -26,6 +26,8 @@ module StringBreak { predicate isBarrier(DataFlow::Node node, FlowState state) { state = node.(Sanitizer).getQuote() } + + predicate observeDiffInformedIncrementalMode() { any() } } /** diff --git a/go/ql/lib/semmle/go/security/TaintedPath.qll b/go/ql/lib/semmle/go/security/TaintedPath.qll index 674cda1157cf..b814ad5d4ac6 100644 --- a/go/ql/lib/semmle/go/security/TaintedPath.qll +++ b/go/ql/lib/semmle/go/security/TaintedPath.qll @@ -17,6 +17,8 @@ module TaintedPath { predicate isSink(DataFlow::Node sink) { sink instanceof Sink } predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer } + + predicate observeDiffInformedIncrementalMode() { any() } } /** Tracks taint flow for reasoning about path-traversal vulnerabilities. */ diff --git a/go/ql/lib/semmle/go/security/UncontrolledAllocationSize.qll b/go/ql/lib/semmle/go/security/UncontrolledAllocationSize.qll index 885aa7a7053c..91bbcfaa1edd 100644 --- a/go/ql/lib/semmle/go/security/UncontrolledAllocationSize.qll +++ b/go/ql/lib/semmle/go/security/UncontrolledAllocationSize.qll @@ -27,6 +27,8 @@ module UncontrolledAllocationSize { node2 = cn.getResult(0) ) } + + predicate observeDiffInformedIncrementalMode() { any() } } /** Tracks taint flow for reasoning about uncontrolled allocation size issues. */ diff --git a/go/ql/lib/semmle/go/security/UnsafeUnzipSymlink.qll b/go/ql/lib/semmle/go/security/UnsafeUnzipSymlink.qll index 1d18ac5f639a..19047b12b788 100644 --- a/go/ql/lib/semmle/go/security/UnsafeUnzipSymlink.qll +++ b/go/ql/lib/semmle/go/security/UnsafeUnzipSymlink.qll @@ -44,6 +44,8 @@ module UnsafeUnzipSymlink { predicate isSink(DataFlow::Node sink) { sink instanceof SymlinkSink } predicate isBarrier(DataFlow::Node node) { node instanceof SymlinkSanitizer } + + predicate observeDiffInformedIncrementalMode() { any() } } /** diff --git a/go/ql/lib/semmle/go/security/XPathInjection.qll b/go/ql/lib/semmle/go/security/XPathInjection.qll index 61bd00977daf..900b81053370 100644 --- a/go/ql/lib/semmle/go/security/XPathInjection.qll +++ b/go/ql/lib/semmle/go/security/XPathInjection.qll @@ -19,6 +19,8 @@ module XPathInjection { predicate isSink(DataFlow::Node sink) { sink instanceof Sink } predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer } + + predicate observeDiffInformedIncrementalMode() { any() } } /** diff --git a/go/ql/lib/semmle/go/security/ZipSlip.qll b/go/ql/lib/semmle/go/security/ZipSlip.qll index f16daf84c3dd..6de2be91509a 100644 --- a/go/ql/lib/semmle/go/security/ZipSlip.qll +++ b/go/ql/lib/semmle/go/security/ZipSlip.qll @@ -17,6 +17,8 @@ module ZipSlip { predicate isSink(DataFlow::Node sink) { sink instanceof Sink } predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer } + + predicate observeDiffInformedIncrementalMode() { any() } } /** Tracks taint flow for reasoning about zip-slip vulnerabilities. */ diff --git a/go/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql b/go/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql index 89954b08f991..f6e3df7d1d91 100644 --- a/go/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql +++ b/go/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql @@ -103,6 +103,8 @@ module IncompleteHostNameRegexpConfig implements DataFlow::ConfigSig { predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { StringOps::Concatenation::taintStep(node1, node2) } + + predicate observeDiffInformedIncrementalMode() { any() } } module Flow = DataFlow::Global; diff --git a/go/ql/src/Security/CWE-020/MissingRegexpAnchor.ql b/go/ql/src/Security/CWE-020/MissingRegexpAnchor.ql index a478968e58b9..d1c501b37ecc 100644 --- a/go/ql/src/Security/CWE-020/MissingRegexpAnchor.ql +++ b/go/ql/src/Security/CWE-020/MissingRegexpAnchor.ql @@ -72,6 +72,8 @@ module Config implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { isSourceString(source, _) } predicate isSink(DataFlow::Node sink) { sink instanceof RegexpPattern } + + predicate observeDiffInformedIncrementalMode() { any() } } module Flow = DataFlow::Global; diff --git a/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql b/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql index e58cf8644904..96688298ec39 100644 --- a/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql +++ b/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql @@ -40,6 +40,8 @@ module SuspiciousCharacterInRegexpConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { isSourceString(source, _) } predicate isSink(DataFlow::Node sink) { sink instanceof RegexpPattern } + + predicate observeDiffInformedIncrementalMode() { any() } } /** diff --git a/go/ql/src/Security/CWE-209/StackTraceExposure.ql b/go/ql/src/Security/CWE-209/StackTraceExposure.ql index 3440fdba3148..408e12b3c15e 100644 --- a/go/ql/src/Security/CWE-209/StackTraceExposure.ql +++ b/go/ql/src/Security/CWE-209/StackTraceExposure.ql @@ -62,6 +62,8 @@ module StackTraceExposureConfig implements DataFlow::ConfigSig { cgn.dominates(node.getBasicBlock()) ) } + + predicate observeDiffInformedIncrementalMode() { any() } } /** diff --git a/go/ql/src/Security/CWE-326/InsufficientKeySize.ql b/go/ql/src/Security/CWE-326/InsufficientKeySize.ql index 19db3ef63ae4..6fa421baaeb3 100644 --- a/go/ql/src/Security/CWE-326/InsufficientKeySize.ql +++ b/go/ql/src/Security/CWE-326/InsufficientKeySize.ql @@ -25,6 +25,8 @@ module Config implements DataFlow::ConfigSig { predicate isBarrier(DataFlow::Node node) { node = DataFlow::BarrierGuard::getABarrierNode() } + + predicate observeDiffInformedIncrementalMode() { any() } } /** diff --git a/go/ql/src/Security/CWE-352/ConstantOauth2State.ql b/go/ql/src/Security/CWE-352/ConstantOauth2State.ql index 31b6907ffddf..8898a6bb1018 100644 --- a/go/ql/src/Security/CWE-352/ConstantOauth2State.ql +++ b/go/ql/src/Security/CWE-352/ConstantOauth2State.ql @@ -40,6 +40,8 @@ module ConstantStateFlowConfig implements DataFlow::ConfigSig { } predicate isSink(DataFlow::Node sink) { isSinkCall(sink, _) } + + predicate observeDiffInformedIncrementalMode() { any() } } /** diff --git a/go/ql/src/Security/CWE-640/EmailInjection.qll b/go/ql/src/Security/CWE-640/EmailInjection.qll index 35b7795ad55f..e3016b44aa1a 100644 --- a/go/ql/src/Security/CWE-640/EmailInjection.qll +++ b/go/ql/src/Security/CWE-640/EmailInjection.qll @@ -20,6 +20,8 @@ module EmailInjection { predicate isSource(DataFlow::Node source) { source instanceof Source } predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + predicate observeDiffInformedIncrementalMode() { any() } } /** Tracks taint flow for reasoning about email-injection vulnerabilities. */ diff --git a/go/ql/src/experimental/CWE-090/LDAPInjection.qll b/go/ql/src/experimental/CWE-090/LDAPInjection.qll index fd138fa06458..a770666fe93e 100644 --- a/go/ql/src/experimental/CWE-090/LDAPInjection.qll +++ b/go/ql/src/experimental/CWE-090/LDAPInjection.qll @@ -101,6 +101,8 @@ private module LdapInjectionConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { sink instanceof LdapSink } predicate isBarrier(DataFlow::Node node) { node instanceof LdapSanitizer } + + predicate observeDiffInformedIncrementalMode() { any() } } /** diff --git a/go/ql/src/experimental/CWE-203/Timing.ql b/go/ql/src/experimental/CWE-203/Timing.ql index ab0b50a657a9..e488adf2f97f 100644 --- a/go/ql/src/experimental/CWE-203/Timing.ql +++ b/go/ql/src/experimental/CWE-203/Timing.ql @@ -102,6 +102,8 @@ module Config implements DataFlow::ConfigSig { } predicate isSink(DataFlow::Node sink) { sink instanceof Sink and not isBadResult(sink) } + + predicate observeDiffInformedIncrementalMode() { any() } } module Flow = TaintTracking::Global; diff --git a/go/ql/src/experimental/CWE-285/PamAuthBypass.ql b/go/ql/src/experimental/CWE-285/PamAuthBypass.ql index 02f47ba2b738..db2dc94f8f07 100644 --- a/go/ql/src/experimental/CWE-285/PamAuthBypass.ql +++ b/go/ql/src/experimental/CWE-285/PamAuthBypass.ql @@ -42,6 +42,8 @@ module PamStartToAcctMgmtConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { exists(PamAcctMgmt p | p.getACall().getReceiver() = sink) } + + predicate observeDiffInformedIncrementalMode() { any() } } module PamStartToAcctMgmtFlow = TaintTracking::Global; @@ -55,6 +57,8 @@ module PamStartToAuthenticateConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { exists(PamAuthenticate p | p.getACall().getReceiver() = sink) } + + predicate observeDiffInformedIncrementalMode() { any() } } module PamStartToAuthenticateFlow = TaintTracking::Global; diff --git a/go/ql/src/experimental/CWE-287/ImproperLdapAuthCustomizations.qll b/go/ql/src/experimental/CWE-287/ImproperLdapAuthCustomizations.qll index 7a62041a774a..0a2739eabc79 100644 --- a/go/ql/src/experimental/CWE-287/ImproperLdapAuthCustomizations.qll +++ b/go/ql/src/experimental/CWE-287/ImproperLdapAuthCustomizations.qll @@ -74,6 +74,8 @@ module ImproperLdapAuth { predicate isSink(DataFlow::Node sink) { sink instanceof LdapAuthSink } predicate isBarrier(DataFlow::Node node) { node instanceof LdapSanitizer } + + predicate observeDiffInformedIncrementalMode() { any() } } /** diff --git a/go/ql/src/experimental/CWE-321-V2/HardCodedKeys.ql b/go/ql/src/experimental/CWE-321-V2/HardCodedKeys.ql index 39cc2ca99176..0cd5246519bf 100644 --- a/go/ql/src/experimental/CWE-321-V2/HardCodedKeys.ql +++ b/go/ql/src/experimental/CWE-321-V2/HardCodedKeys.ql @@ -33,6 +33,8 @@ module JwtParseWithConstantKeyConfig implements DataFlow::ConfigSig { // second part is the JWT Parsing Functions that get a string or byte as an argument sink = any(JwtParse jp).getKeyArg() } + + predicate observeDiffInformedIncrementalMode() { any() } } module GolangJwtKeyFuncConfig implements DataFlow::ConfigSig { diff --git a/go/ql/src/experimental/CWE-327/WeakCryptoAlgorithmCustomizations.qll b/go/ql/src/experimental/CWE-327/WeakCryptoAlgorithmCustomizations.qll index 1d64d731f507..b9104f1fe096 100644 --- a/go/ql/src/experimental/CWE-327/WeakCryptoAlgorithmCustomizations.qll +++ b/go/ql/src/experimental/CWE-327/WeakCryptoAlgorithmCustomizations.qll @@ -54,6 +54,8 @@ module WeakCryptoAlgorithm { predicate isSink(DataFlow::Node sink) { sink instanceof Sink } predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer } + + predicate observeDiffInformedIncrementalMode() { any() } } /** diff --git a/go/ql/src/experimental/CWE-369/DivideByZero.ql b/go/ql/src/experimental/CWE-369/DivideByZero.ql index b6709b97d712..99cd120dbf8b 100644 --- a/go/ql/src/experimental/CWE-369/DivideByZero.ql +++ b/go/ql/src/experimental/CWE-369/DivideByZero.ql @@ -45,6 +45,8 @@ module Config implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { sink = DataFlow::exprNode(any(QuoExpr e).getRightOperand()) } + + predicate observeDiffInformedIncrementalMode() { any() } } /** diff --git a/go/ql/src/experimental/CWE-74/DsnInjectionCustomizations.qll b/go/ql/src/experimental/CWE-74/DsnInjectionCustomizations.qll index 2c3208550720..88a45d70ba52 100644 --- a/go/ql/src/experimental/CWE-74/DsnInjectionCustomizations.qll +++ b/go/ql/src/experimental/CWE-74/DsnInjectionCustomizations.qll @@ -19,6 +19,8 @@ private module DsnInjectionConfig implements DataFlow::ConfigSig { } predicate isBarrier(DataFlow::Node node) { node instanceof RegexpCheckBarrier } + + predicate observeDiffInformedIncrementalMode() { any() } } /** diff --git a/go/ql/src/experimental/frameworks/DecompressionBombs.qll b/go/ql/src/experimental/frameworks/DecompressionBombs.qll index 5828cd60e523..170104ebd43b 100644 --- a/go/ql/src/experimental/frameworks/DecompressionBombs.qll +++ b/go/ql/src/experimental/frameworks/DecompressionBombs.qll @@ -56,6 +56,8 @@ module DecompressionBomb { addStep.isAdditionalFlowStep(fromNode, fromState, toNode, toState) ) } + + predicate observeDiffInformedIncrementalMode() { any() } } /** Tracks taint flow for reasoning about decompression bomb vulnerabilities. */ From 16f38ff5bdd8ffe429991eaf930eedfd63e2890b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 4 Jun 2025 14:15:14 +0200 Subject: [PATCH 2/2] Add change note --- go/ql/lib/change-notes/2025-06-04-diff-informed.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 go/ql/lib/change-notes/2025-06-04-diff-informed.md diff --git a/go/ql/lib/change-notes/2025-06-04-diff-informed.md b/go/ql/lib/change-notes/2025-06-04-diff-informed.md new file mode 100644 index 000000000000..82527fb70fb3 --- /dev/null +++ b/go/ql/lib/change-notes/2025-06-04-diff-informed.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* A number of built-in Go queries can now run in diff-informed mode.