Skip to content

Extend actions/unpinned-tag to analyze composite action metadata (action.yml / action.yaml)#21692

Draft
Copilot wants to merge 2 commits intomainfrom
copilot/update-codeql-query-for-composite-actions
Draft

Extend actions/unpinned-tag to analyze composite action metadata (action.yml / action.yaml)#21692
Copilot wants to merge 2 commits intomainfrom
copilot/update-codeql-query-for-composite-actions

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 10, 2026

actions/unpinned-tag currently only reports uses: refs from workflow files because it filters on getEnclosingWorkflow(). This change broadens coverage to also report unpinned refs in composite action metadata (runs.steps[].uses) while preserving existing workflow behavior and message shape.

  • Query scope expansion (workflow + composite action)

    • Refactored container-name resolution into a helper predicate that accepts either:
      • UsesStep in a Workflow (existing logic retained: workflow name, else workflow file basename), or
      • UsesStep in a CompositeAction (new logic: composite metadata file basename, e.g. action.yml).
    • Main query now uses this generalized predicate instead of requiring uses.getEnclosingWorkflow() = workflow.
  • Behavior preserved for existing workflow alerts

    • Workflow matching and formatting remain unchanged for existing cases.
    • Existing immutable/pinned checks and trusted-owner filtering are untouched.
  • CWE-829 test coverage extended

    • Added composite action fixture with:
      • unpinned tag (foo/bar@v2) → alert expected
      • pinned SHA (foo/bar@<40-hex>) → no alert expected
    • Updated UnpinnedActionsTag.expected with the new composite action alert.
private predicate getStepContainerName(UsesStep uses, string name) {
  exists(Workflow workflow | ... )
  or
  exists(CompositeAction action |
    uses.getEnclosingCompositeAction() = action and
    name = action.getLocation().getFile().getBaseName()
  )
}

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • releases.bazel.build
    • Triggering command: /usr/local/lib/node_modules/@bazel/bazelisk/bazelisk-linux_amd64 /usr/local/lib/node_modules/@bazel/bazelisk/bazelisk-linux_amd64 query kind(&#34;.*test&#34;, //actions/...) (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

Implement support for scanning composite action metadata files (action.yml / action.yaml) in the actions/unpinned-tag CodeQL query so that unpinned action refs used in composite actions are reported.

Context:

  • Current query: actions/ql/src/Security/CWE-829/UnpinnedActionsTag.ql in github/codeql requires uses.getEnclosingWorkflow() = workflow, so it only reports workflow uses steps.
  • Support escalation issue: github/codeql-team#4594 requests the rule also evaluate composite actions’ metadata.

Requirements:

  1. Update the query (and/or shared library predicates) so that uses: references inside composite action metadata files are included.
    • Composite actions are defined in action.yml / action.yaml and contain runs.steps[].uses.
    • Ensure both workflow steps and composite action steps are analyzed.
  2. Preserve existing behavior for workflows and ensure message formatting remains reasonable.
    • Ideally include a “name” for the container: for workflows use workflow name/file base name; for composite actions use something like the file base name (action.yml) or action name: if present.
  3. Add/extend tests under actions/ql/test/... to cover:
    • A workflow file with an unpinned tag should still alert.
    • A composite action metadata file with an unpinned tag should now alert.
    • A pinned SHA should not alert.
  4. Run/adjust any query suite expected files or baselines if needed.

Notes:

  • Prefer using existing Actions AST classes. Look for CompositeAction or UsesStep context APIs.
  • If needed, refactor by introducing a helper predicate (e.g., uses.getEnclosingWorkflow() OR uses.getEnclosingCompositeAction()), or generalizing to a shared “step container”.

Repository: github/codeql

The following is the prior conversation context from the user's chat exploration (may be truncated):

User: can you answer the question on the support escalation? use https://github.com/github/semmle-code and https://github.com/github/codeql-action codebases to investigate

Assistant: This looks like expected behavior of the current actions/unpinned-tag query: it’s (effectively) a workflow-only check today, so it will flag uses: owner/repo@tag inside .github/workflows/*.yml|*.yaml, but it won’t (currently) evaluate composite action metadata (action.yml / action.yaml) for runs.steps[].uses. Your repro matches that gap.

What I found from the two codebases you asked me to use

1) github/semmle-code: the Actions “surface” being targeted is workflows

In semmle-code there’s explicit “Actions workflow” handling that’s scoped to .github/workflows (even in internal tooling). For example, the repo’s actionlint genrule only targets .github/workflows/*.yml and doesn’t mention action.yml at all:

That doesn’t prove the CodeQL query itself filters to workflows, but it’s consistent with what you’re seeing: “Actions language” checks in this repo historically center on workflow files, not composite-action metadata.

Also: I attempted to locate UnpinnedActionsTag.ql in github/semmle-code via code search and didn’t get a hit in this repo snapshot, so I can’t point at the exact ql/actions/.../UnpinnedActionsTag.ql implementation here. (The issue links to github/codeql, not semmle-code, which likely explains the mismatch.)

2) github/codeql-action: it runs CodeQL CLI, but it doesn’t add special handling for composite action metadata

From codeql-action, the “analyze” step orchestrates database finalization and then runs queries (runQueries(...)). Nothing I found suggests it separately enumerates “workflow vs action metadata” files itself; it delegates that to the CodeQL CLI and the selected query packs/suites.

So: if the query pack for the actions language doesn’t model action.yml, codeql-action won’t “pick it up” magically.


Direct answer to the escalation question (“is this expected?”)

Yes, this is expected given the current implementation/coverage of the rule: it is designed (or at least currently implemented) to analyze workflow files and doesn’t currently treat composite action metadata (action.yml/action.yaml) as part of the analyzed surface for this query. That means a composite action can bypass the check today by placing uses: owner/repo@tag inside runs.steps in the action metadata file.

Recommendation / what Engineering should do next

  1. Confirm intended scope: If the goal of `actions/unpinned...

This pull request was created from Copilot chat.

Copilot AI changed the title [WIP] Update CodeQL query to support composite action metadata Extend actions/unpinned-tag to analyze composite action metadata (action.yml / action.yaml) Apr 10, 2026
Copilot AI requested a review from oscarsj April 10, 2026 11:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants