Actions: Add four experimental queries#21624
Conversation
actions/ql/src/experimental/Security/CWE-798/HardcodedContainerCredentials.ql
Fixed
Show fixed
Hide fixed
actions/ql/src/experimental/Security/CWE-798/HardcodedContainerCredentials.ql
Fixed
Show fixed
Hide fixed
actions/ql/src/experimental/Security/CWE-798/HardcodedContainerCredentials.ql
Fixed
Show fixed
Hide fixed
actions/ql/src/experimental/Security/CWE-798/HardcodedContainerCredentials.ql
Fixed
Show fixed
Hide fixed
| @@ -0,0 +1 @@ | |||
| experimental/Security/CWE-183/UnsoundContains.ql | |||
| @@ -0,0 +1 @@ | |||
| experimental/Security/CWE-200/SecretsInherit.ql | |||
| @@ -0,0 +1 @@ | |||
| experimental/Security/CWE-290/SpoofableActorCheck.ql | |||
| @@ -0,0 +1 @@ | |||
| experimental/Security/CWE-798/HardcodedContainerCredentials.ql | |||
There was a problem hiding this comment.
Pull request overview
Adds four new experimental GitHub Actions security queries (structural @kind problem) to catch common workflow misconfigurations that can lead to secret exposure or bypassable security controls.
Changes:
- Added 4 experimental Actions security queries:
actions/secrets-inherit,actions/hardcoded-container-credentials,actions/unsound-contains, andactions/spoofable-actor-check. - Added per-query help (
.md) documentation. - Added query-tests with positive/negative workflow fixtures and
.expectedresults.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| actions/ql/src/experimental/Security/CWE-200/SecretsInherit.ql | New query flagging secrets: inherit on reusable workflow calls. |
| actions/ql/src/experimental/Security/CWE-200/SecretsInherit.md | Help text for actions/secrets-inherit. |
| actions/ql/test/query-tests/Security/CWE-200/SecretsInherit.qlref | Test registration for SecretsInherit. |
| actions/ql/test/query-tests/Security/CWE-200/SecretsInherit.expected | Expected results for SecretsInherit tests. |
| actions/ql/test/query-tests/Security/CWE-200/.github/workflows/secrets-inherit.yml | Positive/negative workflow fixtures for SecretsInherit. |
| actions/ql/src/experimental/Security/CWE-798/HardcodedContainerCredentials.ql | New query flagging hardcoded container/service credential passwords. |
| actions/ql/src/experimental/Security/CWE-798/HardcodedContainerCredentials.md | Help text for actions/hardcoded-container-credentials. |
| actions/ql/test/query-tests/Security/CWE-798/HardcodedContainerCredentials.qlref | Test registration for HardcodedContainerCredentials. |
| actions/ql/test/query-tests/Security/CWE-798/HardcodedContainerCredentials.expected | Expected results for HardcodedContainerCredentials tests. |
| actions/ql/test/query-tests/Security/CWE-798/.github/workflows/hardcoded-credentials.yml | Positive/negative workflow fixtures for hardcoded container/service credentials. |
| actions/ql/src/experimental/Security/CWE-183/UnsoundContains.ql | New query flagging substring-based contains() membership checks using string literals. |
| actions/ql/src/experimental/Security/CWE-183/UnsoundContains.md | Help text for actions/unsound-contains. |
| actions/ql/test/query-tests/Security/CWE-183/UnsoundContains.qlref | Test registration for UnsoundContains. |
| actions/ql/test/query-tests/Security/CWE-183/UnsoundContains.expected | Expected results for UnsoundContains tests. |
| actions/ql/test/query-tests/Security/CWE-183/.github/workflows/unsound-contains.yml | Positive/negative workflow fixtures for unsound contains() usage. |
| actions/ql/src/experimental/Security/CWE-290/SpoofableActorCheck.ql | New query flagging bot-name checks against spoofable actor contexts on externally triggerable events. |
| actions/ql/src/experimental/Security/CWE-290/SpoofableActorCheck.md | Help text for actions/spoofable-actor-check. |
| actions/ql/test/query-tests/Security/CWE-290/SpoofableActorCheck.qlref | Test registration for SpoofableActorCheck. |
| actions/ql/test/query-tests/Security/CWE-290/SpoofableActorCheck.expected | Expected results for SpoofableActorCheck tests. |
| actions/ql/test/query-tests/Security/CWE-290/.github/workflows/bot-conditions.yml | Positive/negative workflow fixtures for spoofable actor checks. |
Comments suppressed due to low confidence (1)
actions/ql/src/experimental/Security/CWE-183/UnsoundContains.md:37
- This second
fromJSON()example also escapes the JSON quotes (it includes backslashes before the quotes). Please remove the backslashes so the JSON is written with normal double-quotes for copy/paste correctness.
```yaml
steps:
- run: terraform apply
if: contains(fromJSON('["refs/heads/main", "refs/heads/develop"]'), github.ref)
</details>
actions/ql/src/experimental/Security/CWE-290/SpoofableActorCheck.md
Outdated
Show resolved
Hide resolved
actions/ql/src/experimental/Security/CWE-183/UnsoundContains.md
Outdated
Show resolved
Hide resolved
actions/ql/test/query-tests/Security/CWE-798/.github/workflows/hardcoded-credentials.yml
Show resolved
Hide resolved
New experimental security queries for GitHub Actions:
- actions/secrets-inherit (CWE-200): Flags \`secrets: inherit\` on
reusable workflow calls. This passes all org/repo secrets to the
callee, violating least privilege.
- actions/hardcoded-container-credentials (CWE-798): Flags hardcoded
passwords in \`container.credentials\` and \`services.*.credentials\`.
- actions/unsound-contains (CWE-183): Flags \`contains()\` with a
string-literal first argument. This does substring matching, not
array membership, so \`contains('refs/heads/main', github.ref)\`
also matches a branch named \`mai\`.
- actions/spoofable-actor-check (CWE-290): Flags \`github.actor\`
or \`github.triggering_actor\` compared to a \`[bot]\` name on
externally triggerable events. \`github.actor\` refers to the last
actor on the context, not the triggering actor, so an attacker can
spoof it.
Includes .md help files and tests for each query.
68bdbbe to
b6388da
Compare
Is this actually true? If so, do you have a source for that? As far as I'm aware, only secrets to which the caller workflow already has access are getting inherited. Fun fact, the GitHub blog explicitly lists |
Four new experimental queries that catch GitHub Actions issues Zizmor flags but CodeQL currently misses. All are structural pattern-matching (
@kind problem), no dataflow.actions/secrets-inherit(CWE-200):secrets: inheriton reusable workflow calls forwards every org and repo secret to the callee. Almost nobody actually needs that; the fix is listing the specific secrets the workflow uses.actions/hardcoded-container-credentials(CWE-798): Literal passwords incontainer.credentials.passwordorservices.*.credentials.password. Checks that the value isn't a${{ }}expression.actions/unsound-contains(CWE-183):contains('refs/heads/main refs/heads/develop', github.ref)looks like a membership check but is actually a substring match. A branch namedmaiwould pass. The fix iscontains(fromJSON('["refs/heads/main", "refs/heads/develop"]'), github.ref).actions/spoofable-actor-check(CWE-290):github.actor == 'dependabot[bot]'as a security gate onpull_request_target.github.actoris the last actor to touch the context, not the one who opened the PR, so an attacker can spoof it. The existingActorIfCheckin ControlChecks.qll already excludes[bot]patterns from being treated as security guards, which confirms the framework considers these checks insufficient.Each query has an
.mdhelp file and test fixtures with both positive and negative cases.