Skip to content

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

Open
wants to merge 15 commits into
base: main
Choose a base branch
from

Conversation

Napalys
Copy link
Contributor

@Napalys Napalys commented Jul 31, 2025

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.

Copy link
Contributor

github-actions bot commented Jul 31, 2025

QHelp previews:

@Napalys Napalys marked this pull request as ready for review July 31, 2025 11:15
@Napalys Napalys requested a review from a team as a code owner July 31, 2025 11:15
@Copilot Copilot AI review requested due to automatic review settings July 31, 2025 11:15
Copy link
Contributor

@Copilot Copilot AI left a 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/ to Security/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

@asgerf
Copy link
Contributor

asgerf commented Aug 13, 2025

The query is a near duplicate of the existing js/cors-misconfiguration-for-credentials query. It should be merged into one query, or renamed and described in a way that makes it clear why there are two queries.

@Napalys Napalys force-pushed the js/move-cors-query-from-experimental branch from 227071b to 1c33a0a Compare August 19, 2025 08:06
Copy link
Contributor

@asgerf asgerf left a 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 }
Copy link
Contributor

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) */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/** 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) */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/** 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.

Comment on lines 105 to 132
/**
* 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 }
}
Copy link
Contributor

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.

@Napalys Napalys force-pushed the js/move-cors-query-from-experimental branch from e043692 to 83cb788 Compare August 21, 2025 11:12
@Napalys Napalys force-pushed the js/move-cors-query-from-experimental branch from c360425 to 58f1371 Compare August 22, 2025 07:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants