Skip to content

Conversation

@owen-mc
Copy link
Contributor

@owen-mc owen-mc commented Nov 28, 2025

Fixes https://github.com/github/codeql-team/issues/4370 . Includes a test demonstrating this.

In general I think the filtering between different severity levels for many queries should probably be modified to be more like this, so that it's clearer that we aren't letting some alerts fall between the cracks.

Copilot AI review requested due to automatic review settings November 28, 2025 23:25
@owen-mc owen-mc requested a review from a team as a code owner November 28, 2025 23:25
@github-actions github-actions bot added documentation Actions Analysis of GitHub Actions labels Nov 28, 2025
Copilot finished reviewing on behalf of owen-mc November 28, 2025 23:27
Copy link
Contributor

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 fixes a filtering gap in code injection queries where alerts could be missed when neither the medium nor critical severity query would report them.

  • Introduces a new helper predicate getRelevantCriticalEventForSourceSink that checks both sink context and source event matching
  • Updates the medium query to explicitly exclude critical query results rather than using complementary context checks
  • Adds test case demonstrating the fix with a workflow triggered by both push and workflow_dispatch events

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
actions/ql/lib/codeql/actions/security/CodeInjectionQuery.qll Adds new predicate combining sink context and source event checks
actions/ql/src/Security/CWE-094/CodeInjectionCritical.ql Simplifies query to use new combined predicate
actions/ql/src/Security/CWE-094/CodeInjectionMedium.ql Changes to explicitly exclude critical results using new predicate
actions/ql/test/query-tests/Security/CWE-094/.github/workflows/push_and_workflow_dispatch.yml New test case demonstrating the filtering fix
actions/ql/test/query-tests/Security/CWE-094/CodeInjectionMedium.expected Updated expected test results
actions/ql/test/query-tests/Security/CWE-094/CodeInjectionCritical.expected Updated expected test results
actions/ql/lib/change-notes/2025-11-28-fix-code-injection-alert-filtering.md Documents the majorAnalysis change

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@owen-mc owen-mc force-pushed the actions/fix/code-injection-privileged-context branch from 6f75eb7 to 6d3ee98 Compare November 29, 2025 01:06
@owen-mc owen-mc requested review from a team and adityasharad December 2, 2025 13:16
Copy link
Collaborator

@adityasharad adityasharad left a comment

Choose a reason for hiding this comment

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

Nice work. I think this looks right, and appreciate the tests and structure. Some questions to make sure I fully understand, or that may let us make it even cleaner.

pragma[inline]
predicate criticalSeverity(DataFlow::Node source, DataFlow::Node sink, Event event) {
event = getRelevantCriticalEventForSink(sink) and
source.(RemoteFlowSource).getEventName() = event.getName()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Minor: maybe just declare sink with this type.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Other refactors meant that this isn't possible.

predicate mediumSeverity(DataFlow::Node source, DataFlow::Node sink) {
not criticalSeverity(source, sink, _) and
// exclude cases where the sink is a JS script and the expression uses toJson
not exists(UsesStep script |
Copy link
Collaborator

Choose a reason for hiding this comment

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

Minor: put Expression expr as a variable here, and equate that to sink.asExpr() for reuse.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This logic is actually used in two places, so I've put the logic into a separate predicate which takes an argument Expression expr.


/** Holds if the flow from `source` to `sink` has medium severity. */
pragma[inline]
predicate mediumSeverity(DataFlow::Node source, DataFlow::Node sink) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Don't we need a positive statement in this logic? Or are we assuming we're in a context where we've checked flowPath(source, sink), and this predicate gets inlined?

I wonder if we should expose flowPathCriticalSeverity and flowPathMediumSeverity predicates directly on CodeInjectionFlow.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's probably more robust and easier to understand to have CodeInjectionFlow::flowPath(source, sink) in the same predicate. I've made that change. I have a slight preference for not putting the predicates in the flow config module, because I want this to be a standard pattern that all the other queries can use, and it allows more consistency for the non-flow queries.

@owen-mc owen-mc requested a review from adityasharad December 3, 2025 13:01
@adityasharad
Copy link
Collaborator

adityasharad commented Dec 3, 2025

Code changes LGTM, once you have tests passing happy to approve. What does a DCA run look like?

@owen-mc
Copy link
Contributor Author

owen-mc commented Dec 4, 2025

DCA looks uneventful. Merging in main got some of the failing tests to pass (or maybe they would have passed if I'd just rerun them), but the QLDoc is failing repeatedly with some kind of bazel dependency issue. I can't see how it could be related to my PR. I've asked on slack for help.

INFO: Found applicable config definition common:linux in file /home/runner/work/semmle-code/semmle-code/.bazelrc: --@rules_rust//rust/settings:experimental_use_cc_common_link
Computing main repo mapping: 
ERROR: Error computing the main repository mapping: module [email protected] not found in registries:
* file:////home/runner/work/semmle-code/semmle-code/ql/misc/bazel/registry/modules/fmt/12.1.0-codeql.1/MODULE.bazel: not found
* https://bcr.bazel.build/modules/fmt/12.1.0-codeql.1/MODULE.bazel: not found
BAZEL FAILED
Error: Process completed with exit code 48.

@owen-mc owen-mc force-pushed the actions/fix/code-injection-privileged-context branch from 849c5ff to 4a16de2 Compare December 4, 2025 16:50
@owen-mc
Copy link
Contributor Author

owen-mc commented Dec 5, 2025

@adityasharad This is ready to merge but needs re-approval because I had to rebase and force-push.

@owen-mc owen-mc merged commit 6d301f2 into github:main Dec 5, 2025
18 checks passed
@owen-mc owen-mc deleted the actions/fix/code-injection-privileged-context branch December 5, 2025 07:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Actions Analysis of GitHub Actions documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants