From 42d162ab9661736a8c57a19191d50f3ffce83998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Tue, 15 Jul 2025 10:54:36 +0200 Subject: [PATCH 1/2] [TEST] C++: CWE-020/ExternalAPI: add tests based on qlhelp --- .../CountUntrustedDataToExternalAPI.expected | 0 .../CountUntrustedDataToExternalAPI.qlref | 4 ++++ .../CWE/CWE-020/ExternalAPISinkExample.cpp | 18 ++++++++++++++++++ .../CWE-020/ExternalAPITaintStepExample.cpp | 18 ++++++++++++++++++ .../IRCountUntrustedDataToExternalAPI.expected | 0 .../IRCountUntrustedDataToExternalAPI.qlref | 4 ++++ .../IRUntrustedDataToExternalAPI.expected | 4 ++++ .../CWE-020/IRUntrustedDataToExternalAPI.qlref | 4 ++++ .../UntrustedDataToExternalAPI.expected | 4 ++++ .../CWE-020/UntrustedDataToExternalAPI.qlref | 4 ++++ .../Security/CWE/CWE-020/sinks.ext..yml | 6 ++++++ .../Security/CWE/CWE-020/sources.ext.yml | 6 ++++++ 12 files changed, 72 insertions(+) create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.expected create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.qlref create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-020/ExternalAPISinkExample.cpp create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-020/ExternalAPITaintStepExample.cpp create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.expected create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.qlref create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.expected create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.qlref create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-020/UntrustedDataToExternalAPI.expected create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-020/UntrustedDataToExternalAPI.qlref create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-020/sinks.ext..yml create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-020/sources.ext.yml diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.expected new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.qlref b/cpp/ql/test/query-tests/Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.qlref new file mode 100644 index 000000000000..082405f9e404 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.qlref @@ -0,0 +1,4 @@ +query: Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/ExternalAPISinkExample.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-020/ExternalAPISinkExample.cpp new file mode 100644 index 000000000000..471ed26cb259 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-020/ExternalAPISinkExample.cpp @@ -0,0 +1,18 @@ +typedef unsigned long size_t; +typedef size_t FILE; + +char *strcat(char *s1, const char *s2); +char *fgets(char *s, int n, FILE *stream); +char *fputs(const char *s, FILE *stream); + +void do_get(FILE* request, FILE* response) { + char page[1024]; + fgets(page, 1024, request); + + char buffer[1024]; + strcat(buffer, "The page \""); + strcat(buffer, page); + strcat(buffer, "\" was not found."); + + fputs(buffer, response); +} diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/ExternalAPITaintStepExample.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-020/ExternalAPITaintStepExample.cpp new file mode 100644 index 000000000000..75205aad5ddd --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-020/ExternalAPITaintStepExample.cpp @@ -0,0 +1,18 @@ +typedef unsigned long size_t; +typedef size_t FILE; + +char *strcat(char *s1, const char *s2); +char *fgets(char *s, int n, FILE *stream); +char *fputs(const char *s, FILE *stream); + +void do_get(FILE* request, FILE* response) { + char user_id[1024]; + fgets(user_id, 1024, request); + + char buffer[1024]; + strcat(buffer, "SELECT * FROM user WHERE user_id='"); + strcat(buffer, user_id); + strcat(buffer, "'"); + + fputs(buffer, response); +} diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.expected new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.qlref b/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.qlref new file mode 100644 index 000000000000..81155a9a6375 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.qlref @@ -0,0 +1,4 @@ +query: Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.expected new file mode 100644 index 000000000000..58f42bec0c84 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.expected @@ -0,0 +1,4 @@ +#select +edges +nodes +subpaths diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.qlref b/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.qlref new file mode 100644 index 000000000000..826e00a0263f --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.qlref @@ -0,0 +1,4 @@ +query: Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/UntrustedDataToExternalAPI.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-020/UntrustedDataToExternalAPI.expected new file mode 100644 index 000000000000..58f42bec0c84 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-020/UntrustedDataToExternalAPI.expected @@ -0,0 +1,4 @@ +#select +edges +nodes +subpaths diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/UntrustedDataToExternalAPI.qlref b/cpp/ql/test/query-tests/Security/CWE/CWE-020/UntrustedDataToExternalAPI.qlref new file mode 100644 index 000000000000..a4c937bd3d8a --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-020/UntrustedDataToExternalAPI.qlref @@ -0,0 +1,4 @@ +query: Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/sinks.ext..yml b/cpp/ql/test/query-tests/Security/CWE/CWE-020/sinks.ext..yml new file mode 100644 index 000000000000..4d6e894afd7b --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-020/sinks.ext..yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/cpp-all + extensible: sinkModel + data: # namespace, type, subtypes, name, signature, ext, input, kind, provenance + - [ "", "", False, "fputs", "", "", "Argument[0]", "remote-sink", "manual"] diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/sources.ext.yml b/cpp/ql/test/query-tests/Security/CWE/CWE-020/sources.ext.yml new file mode 100644 index 000000000000..dbf121524e07 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-020/sources.ext.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/cpp-all + extensible: sourceModel + data: # namespace, type, subtypes, name, signature, ext, output, kind, provenance + - [ "", "", False, "fgets", "", "", "Argument[0]", "remote", "manual"] From 2b646feeb77ba4cddb15eb047cbe40429f83a44f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 16 Jul 2025 10:18:03 +0200 Subject: [PATCH 2/2] [DIFF-INFORMED] C++: (IR) ExternalAPIs https://github.com/d10c/codeql/blob/d10c/diff-informed-phase-3/cpp/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql#L19 https://github.com/d10c/codeql/blob/d10c/diff-informed-phase-3/cpp/ql/src/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.ql#L20 --- cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll | 4 ++++ cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIsSpecific.qll | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll b/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll index f0876800874c..5bc4ac2e2288 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll +++ b/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll @@ -51,6 +51,10 @@ private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig { } predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode } + + predicate observeDiffInformedIncrementalMode() { + none() // risky since used in library: normal use in UntrustedDataToExternalApi.ql; used via ExternalApiUsedWithUntrustedData (no location) in CountUntrustedDataToExternalAPI.ql + } } module UntrustedDataToExternalApiFlow = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIsSpecific.qll b/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIsSpecific.qll index d094439951f2..e0a037efd144 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIsSpecific.qll +++ b/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIsSpecific.qll @@ -46,6 +46,10 @@ private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode } + + predicate observeDiffInformedIncrementalMode() { + none() // risky since used in library: normal use in IRUntrustedDataToExternalApi.ql; used via ExternalApiUsedWithUntrustedData (no location) in IRCountUntrustedDataToExternalAPI.ql + } } module UntrustedDataToExternalApiFlow = TaintTracking::Global;