Not necessarily. A composite action is a list of steps, and each step can call another action. GitHub strongly recommends including a version on those calls, but it does not force a full commit SHA. So pinning the outer action does not automatically pin the actions inside it, and those inner actions run in your job.
How composite actions work
GitHub's metadata reference says composite actions define a list of steps, which can be run steps or uses steps. For a uses step it says: we strongly recommend that you include the version of the action you are using. For a run step, the shell is required.
The action you reference from your workflow is the outer layer. Whatever its steps call is the inner layer. All of it executes inside your job, with the job's token and secrets in reach.
Why pinning the outer layer is not enough
Say your workflow references the outer action at a full commit SHA. That fixes the outer action's metadata file and its steps. If one of those steps uses another action at a tag, then the inner action is a moving target. If the tag moves, what runs changes, even though your file did not.
GitHub's secure use guidance says tags can be moved or deleted if a repository is compromised, and recommends pinning to a full commit SHA. The same logic applies at every layer of a composite action. This is the kind of thing that made tag repointing incidents hurt, since many users pinned only what they could see. For background, see pin GitHub Actions to a commit SHA after tag repointing.
How to find nested references
- Open the outer action's metadata file at the pinned SHA.
- Read the steps list and note every uses line, with its version reference.
- For each inner action, repeat, since it may itself be composite.
- Write down the full tree: outer, inner, and any deeper ones.
- Mark each reference as SHA, tag, or branch.
For a reusable workflow, GitHub allows up to ten levels of nesting, and the same tree thinking applies. See does require SHA pinning cover reusable workflows.
What you can do about it
| Option | Effect |
|---|---|
| Ask the maintainer to pin inner actions by SHA | Fixes it for everyone, if they agree |
| Fork the outer action and pin the inner references yourself | You control the tree and sync it |
| Replace the composite action with explicit steps in your own workflow | Every reference is visible in your file |
| Accept the risk for low-privilege jobs | Reasonable when the job holds no secrets and a read-only token |
For authors of composite actions
If you publish one, pin your inner actions to full SHAs, and keep them current with an update tool. Your users inherit your choices. Use the same discipline you would want from an action you depend on.
Keep the inventory honest
A list of the actions in your workflows that shows only the outer references understates your exposure. Where you can, list the nested ones as well. An advisory against an inner action will not mention your outer action by name.
Quick check
Does the org policy that requires SHA pinning catch inner references?
Do not assume so. Check how your policy treats nested references and test it with a sample composite action, since a policy applies to the references it can evaluate.
Is a composite action riskier than a JavaScript action?
Not by type. What matters is whether you can read everything that will run, including nested calls, and whether each reference is fixed.
Sources
- GitHub Docs: Metadata syntax for GitHub Actions
- GitHub Docs: Secure use reference
- GitHub Docs: Reusing workflows
Last reviewed: 19 October 2026.