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.