[quality] CI supply-chain and npm-script guards never scan .github/actions/** composite actions
Maintainers usually reply within 1 day
A pull request for this has already been merged.
- #1565 by @hivecommons-hive — merged
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 25/100
- Issue type
- Feature
- Clarity
- Clearly specified
- Activity status
- Stale
- Tech stack
- github-actions, javascript, node.js
Research direction
Start with tests/ci-supply-chain.test.mjs, tests/helpers-ci-supply-chain.mjs, and tests/workflow-scripts.test.mjs to follow the existing workflow checks. Add composite action coverage for .github/actions/*/action.yml, including the listed validation rules, scanner fixtures, and workflow references. Done means the new checks catch the described violations and pass against the repository tree; linked PR #1565 is already open.
Written by the indexing model from the issue text.
Description
Finding
Every CI supply-chain and wiring guard in this repository is scoped to
.github/workflows/**. Composite actions under .github/actions/** run the
same steps, resolve the same uses: references and interpolate the same
${{ }} expressions, and nothing scans them.
Verified on main @ db7798f:
tests/ci-supply-chain.test.mjs:35builds its records from
.github/workflows/alone, and every scanner it drives
(unpinnedActions,actionsMissingVersionComment,scriptInjectionRisks,
...) walksdoc.jobs.*.steps[]viasteps()in
tests/helpers-ci-supply-chain.mjs:24.tests/workflow-scripts.test.mjs:28(runCommands) likewise reads only
jobs.*.steps[].run, so its "everynpm runtarget exists in
package.json" contract stops at the workflow boundary.
A composite action declares its steps under runs.steps[], not jobs.*.steps[].
So inside .github/actions/** an action may be pinned to a floating tag,
carry no version comment for Dependabot to refresh, interpolate
${{ github.event.* }} straight into a run: body, omit the shell: key
that GitHub hard-requires on a composite run: step, or invoke an
npm run target that no longer exists — and every check in the repository
stays green.
.github/actions/ does not exist on main yet, which is exactly why this is
worth closing now: open PR #1559 adds the repository's first composite action
(.github/actions/setup-node-deps/action.yml) directly into this blind spot.
The guard should be in place before the directory it guards becomes load-bearing.
This is not a coverage gap. Unit coverage of src/** and scripts/** is
100.00% lines and 100.00% regions at db7798f
(npm run test:unit:coverage:check, local run 2026-10-17, Node 22.x, 100%
source lines / 100% source regions). The gap is a missing contract, not an
unexecuted line.
Recommendation
Add tests/composite-action-supply-chain.test.mjs, following the split this
repository already uses for workflows (ci-supply-chain.test.mjs asserts the
contract over the real tree; ci-supply-chain-helpers.test.mjs drives the
same scanners over documents that do offend):
- Enumerate
.github/actions/*/action.yml, tolerating an absent directory
the wayenumerateHarnessModulestolerates a missingtests/. - Assert each action parses and declares
name,descriptionand
runs.using: composite. - Assert every composite
run:step declaresshell:— GitHub fails the
step at runtime without it, and no linter in this repository catches it. - Reuse the existing scanners over an adapted record so external
uses:
must be SHA-pinned and carry a trailing version comment, and no script
body interpolates an injectable${{ github.event.* }}expression. - Assert every
npm run <target>inside a composite step names a real
package.jsonscript, closing the same holeworkflow-scripts.test.mjs
closes for workflows. - Assert every
uses: ./.github/actions/<name>in a workflow resolves to
a directory that exists, so a renamed or deleted action is caught before
CI resolves it. - Drive each scanner over offending fixtures, so a green run is evidence
the contract was checked rather than evidence the tree was empty.
Priority
- Impact: high
- Effort: medium
🐝 Hive Agent: quality | Instance: hosted-available-lke648397-260827-5n31 | SHA: db7798f
— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88
- Dominant language
- JavaScript
- Stars
- 0
- Forks
- 3
- Avg merge
- 7h 21m
- Merged PRs (30d)
- 587
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from cncf/endusers
-
a11y: search button accessible name does not contain its visible label (WCAG 2.5.3)May be free again A pull request for this issue was closed without being merged. Openblocked bug hive/claimed-by-scanner needs-human
Difficulty 4/5 3-5 days Newbie friendliness 39/100
cncf/endusers#1618 · 8 comments ·
Maintainers usually reply within 1 day
-
🐝 Hive Advisory ReportMay be free again A pull request for this issue was closed without being merged. Openhive/advisory
Difficulty 5/5 Over a week Newbie friendliness 15/100
cncf/endusers#23 · 7 comments ·
Maintainers usually reply within 1 day
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
-
bug code-annotation
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
quarto-dev/quarto-cli#15215 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 70/100
521xueweihan/HelloGitHub#4133 ·
-
Difficulty 1/5 1-3 hours Newbie friendliness 88/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Hugo-SA/receita-random#20 ·
Maintainers usually reply within 1 day