Skip to content

Actions: vacuous if: condition suppresses code-injection alert #22367

Description

@computersarebad

Description of the issue

The actions/code-injection query doesn't flag an injectable workflow if the job has an if: condition that looks like an actor check, even when that check can never do anything for the event that triggers the workflow.

Repro (CodeQL CLI 2.26.3, codeql/actions-queries default suite):

name: repro
on:
  issues:
    types: [opened]
jobs:
  j:
    runs-on: ubuntu-latest
    if: github.event.pull_request.user.login != 'some-bot[bot]'
    steps:
      - run: |
          echo '${{ github.event.issue.title }}'

No alert is reported. Remove the if: line and actions/code-injection/critical fires.

The if: condition provides no protection here. The workflow only triggers on issues events, and github.event.pull_request doesn't exist in an issues payload, so the comparison is always true. Any user who opens an issue reaches the injectable run: step.

The query misses this because of how ActorIfCheck works. It uses a regex to look for actor fields like github.event.pull_request.user.login anywhere in the condition. If it finds one, the job counts as protected. It never checks whether that field actually exists for the event that triggers the workflow, so this always-true condition suppresses the alert.

I started digging into this after reading the Wiz write-up on the snowflakedb/snowflake-connector-net injection and wondering why the code-injection query never alerted on the vulnerable workflow. Running that workflow file through the current query locally confirmed the gate is what suppresses the alert:

Variant Alert?
Full workflow as committed (with its if: gate) no
Same file, if: removed yes
if: reduced to only the pull_request.user.login != '...' clause no

When I searched for existing issues/PRs on this topic I found #22154, which fixed the same kind of problem for EnvironmentCheck. The PR description there even suggested reviewing whether other check types have this issue. ActorIfCheck (and possibly the other If-based checks) appears to.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions