-
Notifications
You must be signed in to change notification settings - Fork 1.8k
JS: Move cors-misconfiguration query from experimental to Security #20146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
JS: Move cors-misconfiguration query from experimental to Security #20146
Conversation
QHelp previews: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR moves the CORS misconfiguration query from experimental to the main Security suite, making it part of the default security analysis.
- Relocates the CORS permissive configuration query and supporting files from
experimental/Security/CWE-942/
toSecurity/CWE-942/
- Updates library imports to use the standard location and removes deprecated functionality
- Adds Apollo Server modeling through external model files instead of custom QL code
Reviewed Changes
Copilot reviewed 16 out of 20 changed files in this pull request and generated no comments.
Show a summary per file
File | Description |
---|---|
javascript/ql/src/Security/CWE-942/CorsPermissiveConfiguration.ql |
Updates query imports and improves naming from "overly CORS configuration" to "Permissive CORS configuration" |
javascript/ql/src/Security/CWE-942/CorsPermissiveConfiguration.qhelp |
Adds comprehensive help documentation with improved formatting and clearer explanations |
javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationQuery.qll |
Removes deprecated Configuration class and flow label classes |
javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll |
Updates imports to use standard Cors framework and replaces custom Apollo modeling with model-based approach |
javascript/ql/lib/ext/apollo-server.model.yml |
Adds Apollo Server type models and sink models to replace custom QL implementations |
javascript/ql/test/query-tests/Security/CWE-942/CorsPermissiveConfiguration.qlref |
Creates new test reference pointing to the moved query location |
Multiple test expectation files | Updates expected query suite contents to include the new security query |
Comments suppressed due to low confidence (1)
javascript/ql/src/Security/CWE-942/CorsPermissiveConfiguration.ql:2
- The query name should be 'CORS misconfiguration' to match the title mentioned in the change notes and maintain consistency with existing naming conventions.
* @name Permissive CORS configuration
The query is a near duplicate of the existing |
227071b
to
1c33a0a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I'm not sure merging the queries was actually the right call. There are real use-cases for using *
as the origin, especially when not allowing credential transfer, and AFAIU the new query just flags *
origin as bad without further context.
The original name, permissive configuration, was more apt as it didn't imply mis-configuration, it just detected permissive configurations.
|
||
/** An overly permissive value for `origin` (Apollo) */ | ||
class TrueNullValue extends Source { | ||
TrueNullValue() { this.mayHaveBooleanValue(true) or this.asExpr() instanceof NullLiteral } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The null case is already covered by the NullToStringValue
class right above here.
Also, while you're at it, could you change mayHaveStringValue()
to use getStringValue()
. Since we're defining a data flow source, we should only use the actual string literal as the source, not its local aliases. Same for mayHaveBooleanValue
.
@@ -75,4 +76,58 @@ module CorsMisconfigurationForCredentials { | |||
this.asExpr().mayHaveStringValue("null") | |||
} | |||
} | |||
|
|||
/** An overly permissive value for `origin` (Apollo) */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/** An overly permissive value for `origin` (Apollo) */ | |
/** An overly permissive value for `origin` */ |
Not specific to Apollo in any way.
TrueNullValue() { this.mayHaveBooleanValue(true) or this.asExpr() instanceof NullLiteral } | ||
} | ||
|
||
/** An overly permissive value for `origin` (Express) */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/** An overly permissive value for `origin` (Express) */ | |
/** An overly permissive value for `origin`. */ |
The *
value is not specific to Express in any way. The CORS-related headers are checked by the browser.
Maybe just merge all these classes.
/** | ||
* The value of cors origin when initializing the application. | ||
*/ | ||
class ExpressCors extends Sink, DataFlow::ValueNode { | ||
ExpressCors() { | ||
exists(CorsConfiguration config | this = config.getCorsConfiguration().getOrigin()) | ||
} | ||
|
||
override Http::HeaderDefinition getCredentialsHeader() { none() } | ||
} | ||
|
||
/** | ||
* An express route setup configured with the `cors` package. | ||
*/ | ||
class CorsConfiguration extends DataFlow::MethodCallNode { | ||
Cors::Cors corsConfig; | ||
|
||
CorsConfiguration() { | ||
exists(Express::RouteSetup setup | this = setup | | ||
if setup.isUseCall() | ||
then corsConfig = setup.getArgument(0) | ||
else corsConfig = setup.getArgument(any(int i | i > 0)) | ||
) | ||
} | ||
|
||
/** Gets the expression that configures `cors` on this route setup. */ | ||
Cors::Cors getCorsConfiguration() { result = corsConfig } | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These classes taken together don't end up doing much useful work.
We are effectively treating cors;Argument[0].Member[origin]
as a sink (which is fine), but these classes ensure that we only actually use the sink in these two specific situations:
- The cors middleware is used in an express app (why not other frameworks?)
- It is set up with the first argument to a use call, or a non-first argument to another kind of route setup. I don't understand the rationale behind this requirement.
I would just replace the sink with API::moduleImport("cors").getArgument(0).getMember("origin").asSink()
and use that as the sink (or add a sink kind for it and use MaD). And then remove Cors.qll
as I think it's not used anywhere else. Too many wrappers that just end up adding unhelpful restrictions.
e043692
to
83cb788
Compare
c360425
to
58f1371
Compare
Moved cors-misconfiguration query outside experimental and merged it into existing
js/cors-misconfiguration-for-credentials
DCA: https://github.com/github/codeql-dca-main/blob/data/Napalys/PR-20146-0-javascript/reports/alert-comparison.md looks good to me, we got 2 new alerts due to
*
being used.