From 358617f53365db5b808bc668f0aae704e56790c2 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Wed, 30 Jul 2025 09:49:04 +0000 Subject: [PATCH 1/8] Move CORS misconfiguration query from experimental to Security --- .../semmle/javascript/frameworks}/Apollo.qll | 0 .../semmle/javascript/frameworks}/Cors.qll | 0 .../CorsPermissiveConfigurationCustomizations.qll | 10 +++++----- .../security}/CorsPermissiveConfigurationQuery.qll | 0 .../CWE-942/CorsPermissiveConfiguration.qhelp | 0 .../Security/CWE-942/CorsPermissiveConfiguration.ql | 11 ++++++----- .../examples/CorsPermissiveConfigurationBad.js | 0 .../examples/CorsPermissiveConfigurationGood.js | 0 .../CWE-942/CorsPermissiveConfiguration.qlref | 1 - .../CWE-942/CorsPermissiveConfiguration.expected | 0 .../CWE-942/CorsPermissiveConfiguration.qlref | 1 + .../Security/CWE-942/apollo-test.js | 0 .../Security/CWE-942/express-test.js | 0 13 files changed, 12 insertions(+), 11 deletions(-) rename javascript/ql/{src/experimental/Security/CWE-942 => lib/semmle/javascript/frameworks}/Apollo.qll (100%) rename javascript/ql/{src/experimental/Security/CWE-942 => lib/semmle/javascript/frameworks}/Cors.qll (100%) rename javascript/ql/{src/experimental/Security/CWE-942 => lib/semmle/javascript/security}/CorsPermissiveConfigurationCustomizations.qll (94%) rename javascript/ql/{src/experimental/Security/CWE-942 => lib/semmle/javascript/security}/CorsPermissiveConfigurationQuery.qll (100%) rename javascript/ql/src/{experimental => }/Security/CWE-942/CorsPermissiveConfiguration.qhelp (100%) rename javascript/ql/src/{experimental => }/Security/CWE-942/CorsPermissiveConfiguration.ql (53%) rename javascript/ql/src/{experimental => }/Security/CWE-942/examples/CorsPermissiveConfigurationBad.js (100%) rename javascript/ql/src/{experimental => }/Security/CWE-942/examples/CorsPermissiveConfigurationGood.js (100%) delete mode 100644 javascript/ql/test/experimental/Security/CWE-942/CorsPermissiveConfiguration.qlref rename javascript/ql/test/{experimental => query-tests}/Security/CWE-942/CorsPermissiveConfiguration.expected (100%) create mode 100644 javascript/ql/test/query-tests/Security/CWE-942/CorsPermissiveConfiguration.qlref rename javascript/ql/test/{experimental => query-tests}/Security/CWE-942/apollo-test.js (100%) rename javascript/ql/test/{experimental => query-tests}/Security/CWE-942/express-test.js (100%) diff --git a/javascript/ql/src/experimental/Security/CWE-942/Apollo.qll b/javascript/ql/lib/semmle/javascript/frameworks/Apollo.qll similarity index 100% rename from javascript/ql/src/experimental/Security/CWE-942/Apollo.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Apollo.qll diff --git a/javascript/ql/src/experimental/Security/CWE-942/Cors.qll b/javascript/ql/lib/semmle/javascript/frameworks/Cors.qll similarity index 100% rename from javascript/ql/src/experimental/Security/CWE-942/Cors.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Cors.qll diff --git a/javascript/ql/src/experimental/Security/CWE-942/CorsPermissiveConfigurationCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll similarity index 94% rename from javascript/ql/src/experimental/Security/CWE-942/CorsPermissiveConfigurationCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll index 8876373a3d24..b642b98b35ba 100644 --- a/javascript/ql/src/experimental/Security/CWE-942/CorsPermissiveConfigurationCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll @@ -5,8 +5,8 @@ */ import javascript -import Cors::Cors -import Apollo::Apollo +private import semmle.javascript.frameworks.Apollo +private import semmle.javascript.frameworks.Cors /** Module containing sources, sinks, and sanitizers for overly permissive CORS configurations. */ module CorsPermissiveConfiguration { @@ -105,7 +105,7 @@ module CorsPermissiveConfiguration { */ class CorsApolloServer extends Sink, DataFlow::ValueNode { CorsApolloServer() { - exists(ApolloServer agql | + exists(Apollo::ApolloServer agql | this = agql.getOptionArgument(0, "cors").getALocalSource().getAPropertyWrite("origin").getRhs() ) @@ -125,7 +125,7 @@ module CorsPermissiveConfiguration { * An express route setup configured with the `cors` package. */ class CorsConfiguration extends DataFlow::MethodCallNode { - Cors corsConfig; + Cors::Cors corsConfig; CorsConfiguration() { exists(Express::RouteSetup setup | this = setup | @@ -136,6 +136,6 @@ module CorsPermissiveConfiguration { } /** Gets the expression that configures `cors` on this route setup. */ - Cors getCorsConfiguration() { result = corsConfig } + Cors::Cors getCorsConfiguration() { result = corsConfig } } } diff --git a/javascript/ql/src/experimental/Security/CWE-942/CorsPermissiveConfigurationQuery.qll b/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationQuery.qll similarity index 100% rename from javascript/ql/src/experimental/Security/CWE-942/CorsPermissiveConfigurationQuery.qll rename to javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationQuery.qll diff --git a/javascript/ql/src/experimental/Security/CWE-942/CorsPermissiveConfiguration.qhelp b/javascript/ql/src/Security/CWE-942/CorsPermissiveConfiguration.qhelp similarity index 100% rename from javascript/ql/src/experimental/Security/CWE-942/CorsPermissiveConfiguration.qhelp rename to javascript/ql/src/Security/CWE-942/CorsPermissiveConfiguration.qhelp diff --git a/javascript/ql/src/experimental/Security/CWE-942/CorsPermissiveConfiguration.ql b/javascript/ql/src/Security/CWE-942/CorsPermissiveConfiguration.ql similarity index 53% rename from javascript/ql/src/experimental/Security/CWE-942/CorsPermissiveConfiguration.ql rename to javascript/ql/src/Security/CWE-942/CorsPermissiveConfiguration.ql index 87db66ad98d9..050842028585 100644 --- a/javascript/ql/src/experimental/Security/CWE-942/CorsPermissiveConfiguration.ql +++ b/javascript/ql/src/Security/CWE-942/CorsPermissiveConfiguration.ql @@ -1,5 +1,5 @@ /** - * @name overly CORS configuration + * @name Permissive CORS configuration * @description Misconfiguration of CORS HTTP headers allows CSRF attacks. * @kind path-problem * @problem.severity error @@ -11,11 +11,12 @@ */ import javascript -import CorsPermissiveConfigurationQuery -import CorsPermissiveConfigurationFlow::PathGraph +import semmle.javascript.security.CorsPermissiveConfigurationQuery as CorsQuery +import CorsQuery::CorsPermissiveConfigurationFlow::PathGraph from - CorsPermissiveConfigurationFlow::PathNode source, CorsPermissiveConfigurationFlow::PathNode sink -where CorsPermissiveConfigurationFlow::flowPath(source, sink) + CorsQuery::CorsPermissiveConfigurationFlow::PathNode source, + CorsQuery::CorsPermissiveConfigurationFlow::PathNode sink +where CorsQuery::CorsPermissiveConfigurationFlow::flowPath(source, sink) select sink.getNode(), source, sink, "CORS Origin misconfiguration due to a $@.", source.getNode(), "too permissive or user controlled value" diff --git a/javascript/ql/src/experimental/Security/CWE-942/examples/CorsPermissiveConfigurationBad.js b/javascript/ql/src/Security/CWE-942/examples/CorsPermissiveConfigurationBad.js similarity index 100% rename from javascript/ql/src/experimental/Security/CWE-942/examples/CorsPermissiveConfigurationBad.js rename to javascript/ql/src/Security/CWE-942/examples/CorsPermissiveConfigurationBad.js diff --git a/javascript/ql/src/experimental/Security/CWE-942/examples/CorsPermissiveConfigurationGood.js b/javascript/ql/src/Security/CWE-942/examples/CorsPermissiveConfigurationGood.js similarity index 100% rename from javascript/ql/src/experimental/Security/CWE-942/examples/CorsPermissiveConfigurationGood.js rename to javascript/ql/src/Security/CWE-942/examples/CorsPermissiveConfigurationGood.js diff --git a/javascript/ql/test/experimental/Security/CWE-942/CorsPermissiveConfiguration.qlref b/javascript/ql/test/experimental/Security/CWE-942/CorsPermissiveConfiguration.qlref deleted file mode 100644 index 1e6a39679c0d..000000000000 --- a/javascript/ql/test/experimental/Security/CWE-942/CorsPermissiveConfiguration.qlref +++ /dev/null @@ -1 +0,0 @@ -./experimental/Security/CWE-942/CorsPermissiveConfiguration.ql \ No newline at end of file diff --git a/javascript/ql/test/experimental/Security/CWE-942/CorsPermissiveConfiguration.expected b/javascript/ql/test/query-tests/Security/CWE-942/CorsPermissiveConfiguration.expected similarity index 100% rename from javascript/ql/test/experimental/Security/CWE-942/CorsPermissiveConfiguration.expected rename to javascript/ql/test/query-tests/Security/CWE-942/CorsPermissiveConfiguration.expected diff --git a/javascript/ql/test/query-tests/Security/CWE-942/CorsPermissiveConfiguration.qlref b/javascript/ql/test/query-tests/Security/CWE-942/CorsPermissiveConfiguration.qlref new file mode 100644 index 000000000000..4f4178905a29 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-942/CorsPermissiveConfiguration.qlref @@ -0,0 +1 @@ +Security/CWE-942/CorsPermissiveConfiguration.ql \ No newline at end of file diff --git a/javascript/ql/test/experimental/Security/CWE-942/apollo-test.js b/javascript/ql/test/query-tests/Security/CWE-942/apollo-test.js similarity index 100% rename from javascript/ql/test/experimental/Security/CWE-942/apollo-test.js rename to javascript/ql/test/query-tests/Security/CWE-942/apollo-test.js diff --git a/javascript/ql/test/experimental/Security/CWE-942/express-test.js b/javascript/ql/test/query-tests/Security/CWE-942/express-test.js similarity index 100% rename from javascript/ql/test/experimental/Security/CWE-942/express-test.js rename to javascript/ql/test/query-tests/Security/CWE-942/express-test.js From 92daa7d42cd2835a00c5e17deea4cc1a44401112 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Wed, 30 Jul 2025 10:27:14 +0000 Subject: [PATCH 2/8] Updated suite expectations --- .../query-suite/javascript-code-scanning.qls.expected | 1 + .../query-suite/javascript-security-and-quality.qls.expected | 1 + .../query-suite/javascript-security-extended.qls.expected | 1 + .../integration-tests/query-suite/not_included_in_qls.expected | 1 - 4 files changed, 3 insertions(+), 1 deletion(-) diff --git a/javascript/ql/integration-tests/query-suite/javascript-code-scanning.qls.expected b/javascript/ql/integration-tests/query-suite/javascript-code-scanning.qls.expected index 652ac0ebc1b9..0c417e661c79 100644 --- a/javascript/ql/integration-tests/query-suite/javascript-code-scanning.qls.expected +++ b/javascript/ql/integration-tests/query-suite/javascript-code-scanning.qls.expected @@ -83,5 +83,6 @@ ql/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql ql/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql ql/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql ql/javascript/ql/src/Security/CWE-918/RequestForgery.ql +ql/javascript/ql/src/Security/CWE-942/CorsPermissiveConfiguration.ql ql/javascript/ql/src/Summary/LinesOfCode.ql ql/javascript/ql/src/Summary/LinesOfUserCode.ql diff --git a/javascript/ql/integration-tests/query-suite/javascript-security-and-quality.qls.expected b/javascript/ql/integration-tests/query-suite/javascript-security-and-quality.qls.expected index dd5877683082..f87cd2bf505a 100644 --- a/javascript/ql/integration-tests/query-suite/javascript-security-and-quality.qls.expected +++ b/javascript/ql/integration-tests/query-suite/javascript-security-and-quality.qls.expected @@ -184,6 +184,7 @@ ql/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql ql/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql ql/javascript/ql/src/Security/CWE-918/ClientSideRequestForgery.ql ql/javascript/ql/src/Security/CWE-918/RequestForgery.ql +ql/javascript/ql/src/Security/CWE-942/CorsPermissiveConfiguration.ql ql/javascript/ql/src/Statements/DanglingElse.ql ql/javascript/ql/src/Statements/IgnoreArrayResult.ql ql/javascript/ql/src/Statements/InconsistentLoopOrientation.ql diff --git a/javascript/ql/integration-tests/query-suite/javascript-security-extended.qls.expected b/javascript/ql/integration-tests/query-suite/javascript-security-extended.qls.expected index 9b7cfd22ed6f..ac5e0e2c4984 100644 --- a/javascript/ql/integration-tests/query-suite/javascript-security-extended.qls.expected +++ b/javascript/ql/integration-tests/query-suite/javascript-security-extended.qls.expected @@ -99,5 +99,6 @@ ql/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql ql/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql ql/javascript/ql/src/Security/CWE-918/ClientSideRequestForgery.ql ql/javascript/ql/src/Security/CWE-918/RequestForgery.ql +ql/javascript/ql/src/Security/CWE-942/CorsPermissiveConfiguration.ql ql/javascript/ql/src/Summary/LinesOfCode.ql ql/javascript/ql/src/Summary/LinesOfUserCode.ql diff --git a/javascript/ql/integration-tests/query-suite/not_included_in_qls.expected b/javascript/ql/integration-tests/query-suite/not_included_in_qls.expected index 1b119f60c75e..fa52a97a4e4a 100644 --- a/javascript/ql/integration-tests/query-suite/not_included_in_qls.expected +++ b/javascript/ql/integration-tests/query-suite/not_included_in_qls.expected @@ -75,7 +75,6 @@ ql/javascript/ql/src/experimental/Security/CWE-347/decodeJwtWithoutVerificationL ql/javascript/ql/src/experimental/Security/CWE-444/InsecureHttpParser.ql ql/javascript/ql/src/experimental/Security/CWE-522-DecompressionBombs/DecompressionBombs.ql ql/javascript/ql/src/experimental/Security/CWE-918/SSRF.ql -ql/javascript/ql/src/experimental/Security/CWE-942/CorsPermissiveConfiguration.ql ql/javascript/ql/src/experimental/StandardLibrary/MultipleArgumentsToSetConstructor.ql ql/javascript/ql/src/experimental/heuristics/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql ql/javascript/ql/src/experimental/heuristics/ql/src/Security/CWE-078/CommandInjection.ql From 95743d7109180c7076fe732c2e51ff1ee88d14ab Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Wed, 30 Jul 2025 10:42:55 +0000 Subject: [PATCH 3/8] Added inline test expectations for cors permissive config --- .../Security/CWE-942/CorsPermissiveConfiguration.qlref | 3 ++- .../ql/test/query-tests/Security/CWE-942/apollo-test.js | 8 ++++---- .../ql/test/query-tests/Security/CWE-942/express-test.js | 6 +++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/javascript/ql/test/query-tests/Security/CWE-942/CorsPermissiveConfiguration.qlref b/javascript/ql/test/query-tests/Security/CWE-942/CorsPermissiveConfiguration.qlref index 4f4178905a29..b38b30eb842d 100644 --- a/javascript/ql/test/query-tests/Security/CWE-942/CorsPermissiveConfiguration.qlref +++ b/javascript/ql/test/query-tests/Security/CWE-942/CorsPermissiveConfiguration.qlref @@ -1 +1,2 @@ -Security/CWE-942/CorsPermissiveConfiguration.ql \ No newline at end of file +query: Security/CWE-942/CorsPermissiveConfiguration.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Security/CWE-942/apollo-test.js b/javascript/ql/test/query-tests/Security/CWE-942/apollo-test.js index f55d5dc2c3ec..22019a722584 100644 --- a/javascript/ql/test/query-tests/Security/CWE-942/apollo-test.js +++ b/javascript/ql/test/query-tests/Security/CWE-942/apollo-test.js @@ -5,10 +5,10 @@ var https = require('https'), var server = https.createServer(function () { }); server.on('request', function (req, res) { - let user_origin = url.parse(req.url, true).query.origin; + let user_origin = url.parse(req.url, true).query.origin; // $ Source // BAD: CORS too permissive const server_1 = new ApolloServer({ - cors: { origin: true } + cors: { origin: true } // $ Alert }); // GOOD: restrictive CORS @@ -18,11 +18,11 @@ server.on('request', function (req, res) { // BAD: CORS too permissive const server_3 = new ApolloServer({ - cors: { origin: null } + cors: { origin: null } // $ Alert }); // BAD: CORS is controlled by user const server_4 = new ApolloServer({ - cors: { origin: user_origin } + cors: { origin: user_origin } // $ Alert }); }); \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Security/CWE-942/express-test.js b/javascript/ql/test/query-tests/Security/CWE-942/express-test.js index 3ad31a6a31a8..9b21ed56873b 100644 --- a/javascript/ql/test/query-tests/Security/CWE-942/express-test.js +++ b/javascript/ql/test/query-tests/Security/CWE-942/express-test.js @@ -7,7 +7,7 @@ var https = require('https'), var server = https.createServer(function () { }); server.on('request', function (req, res) { - let user_origin = url.parse(req.url, true).query.origin; + let user_origin = url.parse(req.url, true).query.origin; // $ Source // BAD: CORS too permissive, default value is * var app1 = express(); @@ -23,14 +23,14 @@ server.on('request', function (req, res) { // BAD: CORS too permissive var app3 = express(); var corsOption3 = { - origin: '*' + origin: '*' // $ Alert }; app3.use(cors(corsOption3)); // BAD: CORS is controlled by user var app4 = express(); var corsOption4 = { - origin: user_origin + origin: user_origin // $ Alert }; app4.use(cors(corsOption4)); }); \ No newline at end of file From 84ffbbec33cbff31393da847b815f2c56ae076c2 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Wed, 30 Jul 2025 10:51:38 +0000 Subject: [PATCH 4/8] Added missing doc strings --- .../security/CorsPermissiveConfigurationCustomizations.qll | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll index b642b98b35ba..4751ace2a608 100644 --- a/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll @@ -26,6 +26,7 @@ module CorsPermissiveConfiguration { this = TWildcard() and result = "wildcard" } + /** DEPRECATED: Converts this flow state to a flow label. */ deprecated DataFlow::FlowLabel toFlowLabel() { this = TTaint() and result.isTaint() or @@ -37,6 +38,7 @@ module CorsPermissiveConfiguration { /** Predicates for working with flow states. */ module FlowState { + /** DEPRECATED: Gets a flow state from a flow label. */ deprecated FlowState fromFlowLabel(DataFlow::FlowLabel label) { result.toFlowLabel() = label } /** A tainted value. */ @@ -81,6 +83,7 @@ module CorsPermissiveConfiguration { TrueAndNull() { this = "TrueAndNull" } } + /** DEPRECATED: Gets a flow label representing `true` and `null` values. */ deprecated TrueAndNull truenullLabel() { any() } /** A flow label representing `*` value. */ @@ -88,6 +91,7 @@ module CorsPermissiveConfiguration { Wildcard() { this = "Wildcard" } } + /** DEPRECATED: Gets a flow label representing `*` value. */ deprecated Wildcard wildcardLabel() { any() } /** An overly permissive value for `origin` (Apollo) */ From fd4233e30edc5b828c53f1b4b8cfe76becf154b3 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Thu, 31 Jul 2025 10:53:03 +0200 Subject: [PATCH 5/8] Moved apollo modeling to MaD --- javascript/ql/lib/ext/apollo-server.model.yml | 12 +++++++ .../semmle/javascript/frameworks/Apollo.qll | 36 ------------------- ...sPermissiveConfigurationCustomizations.qll | 4 +-- 3 files changed, 14 insertions(+), 38 deletions(-) delete mode 100644 javascript/ql/lib/semmle/javascript/frameworks/Apollo.qll diff --git a/javascript/ql/lib/ext/apollo-server.model.yml b/javascript/ql/lib/ext/apollo-server.model.yml index ffceb6a6d5af..5962b8ee7d08 100644 --- a/javascript/ql/lib/ext/apollo-server.model.yml +++ b/javascript/ql/lib/ext/apollo-server.model.yml @@ -5,6 +5,12 @@ extensions: data: - ["@apollo/server", "Member[ApolloServer,ApolloServerBase].Argument[0].AnyMember.AnyMember.AnyMember.Parameter[1]", "remote"] + - addsTo: + pack: codeql/javascript-all + extensible: sinkModel + data: + - ["@apollo/server", "Member[gql].Argument[0]", "sql-injection"] + - addsTo: pack: codeql/javascript-all extensible: typeModel @@ -13,3 +19,9 @@ extensions: - ["@apollo/server", "apollo-server-express", ""] - ["@apollo/server", "apollo-server-core", ""] - ["@apollo/server", "apollo-server", ""] + - ["@apollo/server", "@apollo/apollo-server-express", ""] + - ["@apollo/server", "apollo-server-express", ""] + - ["@apollo/server", "@apollo/server", ""] + - ["@apollo/server", "@apollo/apollo-server-core", ""] + - ["ApolloServer", "@apollo/server", "Member[ApolloServer]"] + - ["GraphQLApollo", "@apollo/server", "Member[gql]"] diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Apollo.qll b/javascript/ql/lib/semmle/javascript/frameworks/Apollo.qll deleted file mode 100644 index 983c0a8ac89c..000000000000 --- a/javascript/ql/lib/semmle/javascript/frameworks/Apollo.qll +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Provides classes for working with Apollo GraphQL connectors. - */ - -import javascript - -/** Provides classes modeling the apollo packages [@apollo/server](https://npmjs.com/package/@apollo/server`) */ -module Apollo { - /** Get a reference to the `ApolloServer` class. */ - private API::Node apollo() { - result = - API::moduleImport([ - "@apollo/server", "@apollo/apollo-server-express", "@apollo/apollo-server-core", - "apollo-server", "apollo-server-express" - ]).getMember("ApolloServer") - } - - /** Gets a reference to the `gql` function that parses GraphQL strings. */ - private API::Node gql() { - result = - API::moduleImport([ - "@apollo/server", "@apollo/apollo-server-express", "@apollo/apollo-server-core", - "apollo-server", "apollo-server-express" - ]).getMember("gql") - } - - /** An instantiation of an `ApolloServer`. */ - class ApolloServer extends API::NewNode { - ApolloServer() { this = apollo().getAnInstantiation() } - } - - /** A string that is interpreted as a GraphQL query by a `apollo` package. */ - private class ApolloGraphQLString extends GraphQL::GraphQLString { - ApolloGraphQLString() { this = gql().getACall().getArgument(0) } - } -} diff --git a/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll index 4751ace2a608..a504f66ba22e 100644 --- a/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll @@ -5,7 +5,6 @@ */ import javascript -private import semmle.javascript.frameworks.Apollo private import semmle.javascript.frameworks.Cors /** Module containing sources, sinks, and sanitizers for overly permissive CORS configurations. */ @@ -109,7 +108,8 @@ module CorsPermissiveConfiguration { */ class CorsApolloServer extends Sink, DataFlow::ValueNode { CorsApolloServer() { - exists(Apollo::ApolloServer agql | + exists(API::NewNode agql | + agql = ModelOutput::getATypeNode("ApolloServer").getAnInstantiation() and this = agql.getOptionArgument(0, "cors").getALocalSource().getAPropertyWrite("origin").getRhs() ) From 2baca58b278827703fd803889555c71b5bd05a8e Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Thu, 31 Jul 2025 11:08:22 +0200 Subject: [PATCH 6/8] Removed deprecations from cors as it was moved out experimental --- ...sPermissiveConfigurationCustomizations.qll | 33 ------------------- .../CorsPermissiveConfigurationQuery.qll | 28 ---------------- 2 files changed, 61 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll index a504f66ba22e..583847ab0d98 100644 --- a/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll @@ -24,22 +24,10 @@ module CorsPermissiveConfiguration { or this = TWildcard() and result = "wildcard" } - - /** DEPRECATED: Converts this flow state to a flow label. */ - deprecated DataFlow::FlowLabel toFlowLabel() { - this = TTaint() and result.isTaint() - or - this = TTrueOrNull() and result instanceof TrueAndNull - or - this = TWildcard() and result instanceof Wildcard - } } /** Predicates for working with flow states. */ module FlowState { - /** DEPRECATED: Gets a flow state from a flow label. */ - deprecated FlowState fromFlowLabel(DataFlow::FlowLabel label) { result.toFlowLabel() = label } - /** A tainted value. */ FlowState taint() { result = TTaint() } @@ -65,11 +53,6 @@ module CorsPermissiveConfiguration { */ abstract class Sanitizer extends DataFlow::Node { } - /** - * DEPRECATED: Use `ActiveThreatModelSource` from Concepts instead! - */ - deprecated class RemoteFlowSourceAsSource = ActiveThreatModelSourceAsSource; - /** * An active threat-model source, considered as a flow source. */ @@ -77,22 +60,6 @@ module CorsPermissiveConfiguration { ActiveThreatModelSourceAsSource() { not this instanceof ClientSideRemoteFlowSource } } - /** A flow label representing `true` and `null` values. */ - abstract deprecated class TrueAndNull extends DataFlow::FlowLabel { - TrueAndNull() { this = "TrueAndNull" } - } - - /** DEPRECATED: Gets a flow label representing `true` and `null` values. */ - deprecated TrueAndNull truenullLabel() { any() } - - /** A flow label representing `*` value. */ - abstract deprecated class Wildcard extends DataFlow::FlowLabel { - Wildcard() { this = "Wildcard" } - } - - /** DEPRECATED: Gets a flow label representing `*` value. */ - deprecated Wildcard wildcardLabel() { any() } - /** An overly permissive value for `origin` (Apollo) */ class TrueNullValue extends Source { TrueNullValue() { this.mayHaveBooleanValue(true) or this.asExpr() instanceof NullLiteral } diff --git a/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationQuery.qll b/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationQuery.qll index 3605a1adaa93..0db678e43afd 100644 --- a/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationQuery.qll @@ -39,31 +39,3 @@ module CorsPermissiveConfigurationConfig implements DataFlow::StateConfigSig { module CorsPermissiveConfigurationFlow = TaintTracking::GlobalWithState; - -/** - * DEPRECATED. Use the `CorsPermissiveConfigurationFlow` module instead. - */ -deprecated class Configuration extends TaintTracking::Configuration { - Configuration() { this = "CorsPermissiveConfiguration" } - - override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { - CorsPermissiveConfigurationConfig::isSource(source, FlowState::fromFlowLabel(label)) - } - - override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { - CorsPermissiveConfigurationConfig::isSink(sink, FlowState::fromFlowLabel(label)) - } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - CorsPermissiveConfigurationConfig::isBarrier(node) - } -} - -deprecated private class WildcardActivated extends DataFlow::FlowLabel, Wildcard { - WildcardActivated() { this = this } -} - -deprecated private class TrueAndNullActivated extends DataFlow::FlowLabel, TrueAndNull { - TrueAndNullActivated() { this = this } -} From 791a7e242e5ca1e9ad68c21a49cd76730bdb0370 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Thu, 31 Jul 2025 11:31:10 +0200 Subject: [PATCH 7/8] Updated qhelp for cors permissive configuration --- .../CWE-942/CorsPermissiveConfiguration.qhelp | 92 ++++++++++--------- 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/javascript/ql/src/Security/CWE-942/CorsPermissiveConfiguration.qhelp b/javascript/ql/src/Security/CWE-942/CorsPermissiveConfiguration.qhelp index fc79eee743bf..04796dfbc189 100644 --- a/javascript/ql/src/Security/CWE-942/CorsPermissiveConfiguration.qhelp +++ b/javascript/ql/src/Security/CWE-942/CorsPermissiveConfiguration.qhelp @@ -3,69 +3,71 @@ "qhelp.dtd"> - -

+ +

- A server can use CORS (Cross-Origin Resource Sharing) to relax the - restrictions imposed by the SOP (Same-Origin Policy), allowing controlled, secure - cross-origin requests when necessary. + A server can use CORS (Cross-Origin Resource Sharing) to relax the + restrictions imposed by the Same-Origin Policy, allowing controlled, secure + cross-origin requests when necessary. - A server with an overly permissive CORS configuration may inadvertently - expose sensitive data or lead to CSRF which is an attack that allows attackers to trick - users into performing unwanted operations in websites they're authenticated to. +

+

-

+ A server with an overly permissive CORS configuration may inadvertently + expose sensitive data or enable CSRF attacks, which allow attackers to trick + users into performing unwanted operations on websites they're authenticated to. -
+

+ - -

+ +

- When the origin is set to true, it signifies that the server - is accepting requests from any origin, potentially exposing the system to - CSRF attacks. This can be fixed using false as origin value or using a whitelist. + When the origin is set to true, the server + accepts requests from any origin, potentially exposing the system to + CSRF attacks. Use false as the origin value or implement a whitelist + of allowed origins instead. -

-

+

+

- On the other hand, if the origin is - set to null, it can be exploited by an attacker to deceive a user into making - requests from a null origin form, often hosted within a sandboxed iframe. + When the origin is set to null, it can be + exploited by an attacker who can deceive a user into making + requests from a null origin, often hosted within a sandboxed iframe. -

+

+

-

+ If the origin value is user-controlled, ensure that the data + is properly sanitized and validated against a whitelist of allowed origins. - If the origin value is user controlled, make sure that the data - is properly sanitized. +

+
-

- + +

- -

+ In the following example, server_1 accepts requests from any origin + because the value of origin is set to true. + server_2 uses user-controlled data for the origin without validation. - In the example below, the server_1 accepts requests from any origin - since the value of origin is set to true. - And server_2's origin is user-controlled. +

-

+ - +

-

+ To fix these issues, server_1 uses a restrictive CORS configuration + that is not vulnerable to CSRF attacks. server_2 properly validates + user-controlled data against a whitelist before using it. - In the example below, the server_1 CORS is restrictive so it's not - vulnerable to CSRF attacks. And server_2's is using properly sanitized - user-controlled data. +

-

+ +
- - - - -
  • Mozilla Developer Network: CORS, Access-Control-Allow-Origin.
  • -
  • W3C: CORS for developers, Advice for Resource Owners
  • -
    + +
  • Mozilla Developer Network: CORS, Access-Control-Allow-Origin.
  • +
  • W3C: CORS for developers, Advice for Resource Owners.
  • +
    From 021aa13ee2d544de36bcb26f16857c9c085401d2 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Thu, 31 Jul 2025 12:45:34 +0200 Subject: [PATCH 8/8] Added change note --- .../change-notes/2025-07-31-cors-move-out-of-experimental.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 javascript/ql/src/change-notes/2025-07-31-cors-move-out-of-experimental.md diff --git a/javascript/ql/src/change-notes/2025-07-31-cors-move-out-of-experimental.md b/javascript/ql/src/change-notes/2025-07-31-cors-move-out-of-experimental.md new file mode 100644 index 000000000000..112fb0c628ff --- /dev/null +++ b/javascript/ql/src/change-notes/2025-07-31-cors-move-out-of-experimental.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The query "CORS misconfiguration" (`js/cors-misconfiguration`) has been promoted from experimental and is now part of the default security suite.