Repository navigation
fix(actions-lock): accept lockfile v0.0.3 (github.com dependencies) - #928
Conversation
…ammar gh-actions-lock v0.2.0 writes lockfile v0.0.3, and the estate gate now pins v0.2.0 (standards#1250). ActionsLock accepted only v0.0.2, so any relocked repository raised a high-severity invalid_actions_lock from workflow_audit and workflow_hardening (palimpsest-license alerts 347 and 349). Hypatia's own lock has been v0.0.3 since #926, so its own "parses the repository's authoritative generated lockfile" test failed. v0.0.3 has the v0.0.2 line grammar: same sections, same record fields, same `'<path>': []` form (measured on this repo's lock and on rsr-template-repo's). Both versions are now parsed by the one strict grammar; every other version string is still refused, and a second version line is still a duplicate. Tests: one case for v0.0.3 (accepted; malformed v0.0.3 still fails closed), one for unsupported versions and a duplicate line. Run standalone against the module: 14/14 pass; the unpatched module fails 3 of them, including the existing own-lock test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LET2eHeDbN3b4WuxYjMUX9
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📜 Recent review details
📝 Summary
Merge Risk: ⚪ Minimal · up to
|
|
The red checks here do not come from this PR's change, which touches only
The checks that cover this change passed: Generated by Claude Code |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
…suites pass E2E — Elixir Scanner Pipeline and Integration Tests fail on main since #926: the repository's own lock is now v0.0.3, and Hypatia.Rules.ActionsLock rejects it ("parses the repository's authoritative generated lockfile": unsupported_version "v0.0.3"). #928 fixes that. This brings in its commit unchanged, so the two PRs merge in either order. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LET2eHeDbN3b4WuxYjMUX9
|
#929 now contains this PR's commit (114d015, merged in unchanged). With the standards repin, the UUID fixture fix and the gitleaks fingerprints, that gives one PR that should take the governance, secret-scanner, E2E and Integration checks green together. Merge order does not matter:
This PR's own remaining reds are covered in #929's triage comment:
Generated by Claude Code |
…generic error
v0.0.3 is not quite the v0.0.2 grammar. gh-actions-lock v0.2.0 adds one
optional per-dependency field, `hostname` (`json:"hostname,omitempty"`,
confirmed in the v0.2.0 binary). It writes the field only for a GHE.com
data-residency tenant, never for github.com, so neither real v0.0.3 lock
in the estate (this repo's, rsr-template-repo's) carries it.
Make the parser say so instead of reporting a generic
:malformed_dependency_entry:
- In a v0.0.3 lock, `hostname: 'github.com'` is accepted. It states the
default.
- In a v0.0.3 lock, any other host is refused as
{:unsupported_dependency_hostname, host}. Repository identity
(owner_id/repo_id uniqueness) is validated per host, and this parser
models github.com only.
- In a v0.0.2 lock, a hostname line is still malformed: the field did not
exist then.
The moduledoc now describes the restricted schema accurately.
Tests: a new case covers all three behaviours and a duplicate hostname
line. The real locks still parse: hypatia v0.0.3 (40 deps),
rsr-template-repo v0.0.3 (37), palimpsest-license v0.0.2 (38), standards
v0.0.2 (26).
Addresses CodeRabbit's finding on #929.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LET2eHeDbN3b4WuxYjMUX9
…tions-lock code Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LET2eHeDbN3b4WuxYjMUX9
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a50c0e5ea8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| match = state.version == "v0.0.3" && Regex.run(~r/^ hostname: '([^']+)'$/, line) -> | ||
| [_, host] = match | ||
| line_error(line_number, {:unsupported_dependency_hostname, host}) |
There was a problem hiding this comment.
Pass the home host before accepting omitted hostnames
When scanning a v0.0.3 lock generated on a GHE.com data-residency repository, home-tenant dependencies omit hostname: the authoritative schema notes that producers must omit it for home-host pins. This condition rejects only an explicitly non-GitHub hostname, while parse/1 has no home-host context, so omitted tenant dependencies finalize successfully and pinned?/3 can suppress WH004 as though their repository identities belonged to github.com. Pass the repository host into parsing or otherwise fail closed for ambiguous omitted-host v0.0.3 locks.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
The ambiguity is real, but only for a repository this scanner doesn't see. So I've left the code as is.
The schema README (github/actions-lockfile) gives the rules:
- An omitted
hostnamebinds a pin to the repository's home host. - On github.com,
hostnamemust be omitted orgithub.com, and any other value is rejected. - Producers write
github.comexplicitly only on a GHE.com data-residency instance, and never write a*.ghe.comvalue.
parse/1 assumes the home host is github.com. On that host it now enforces the same rule GitHub does: omitted or github.com is accepted, and anything else is {:unsupported_dependency_hostname, host}.
The misread you describe needs Hypatia to scan a lock produced in a GHE.com tenant repository. Every repository in this estate is on github.com, and no lock in it has a hostname line. Neither suggested fix is in proportion:
- Fail closed on omitted-host v0.0.3 locks. That would refuse every github.com v0.0.3 lock, including this repo's own, because they omit
hostnametoo. - Pass the repository host into parsing. That needs host plumbing through
Rules.scan_workflowand every scan path, for a host the estate doesn't use.
Even in that case, the effect is limited to cross-host owner/repo identity checks. The workflow-ref-to-commit pinning that pinned?/3 relies on is still checked structurally. I've raised this with the repository owner; if they want tenant support, the host parameter is the route.
Generated by Claude Code
|
Add Carrot credits or activate Agent usage billing to use Autofix |
|
❌ Failed to create Coding Agent finishing-touch task. Please try again. |
|
Closing as superseded. Both parts are on
I tried merging current Generated by Claude Code |
|
Reopened. The owner hadn't decided on closing it, so the closure is withdrawn until they do. The analysis above stands: #938 on Generated by Claude Code |
Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
…#929) ## Why GitHub started enforcing `actions.lock` when each job is set up (around 2026-10-15). Since then, every job in a workflow that calls a standards reusable has died at `Set up job` with `invalid lockfile pin`. That covers Governance, Hypatia Security Scan and Secret Scanner. GitHub checks a reusable workflow's actions against the **callee's** `actions.lock` at the called SHA. Standards' lock at the commits this repo pinned (`da2c748`, `571cc73`, `2479cf7`) gives leaf actions their own SHA as `ref:`, which the runner rejects; `lock-selfcheck` rates all three POISON. ## What 1. **Repin (e68277c).** All five standards callers now pin **`75bd599`**, standards `main`. It is green, and `lock-selfcheck` rates it SELF-CONSISTENT. The interfaces are compatible, and `actions.lock` needs no change. 2. **Placeholder UUIDs in the Bitbucket mock (366009f).** The strict `UUID v8/v7 conformance` jobs now run. They flagged four invented UUIDs in an unused fixture, which now get a version nibble of 8 and a variant nibble from 8 to b. 3. **`.gitleaksignore` (abbe382).** 75bd599 adds a gating full-history gitleaks pass. Its five historical false positives sit in files f2fe2df deleted: a k8s Secret *template*'s `CHANGE_ME_IN_PRODUCTION` placeholders, and a Prometheus recording-rule name. They are ignored by exact `commit:file:rule:line` fingerprint only. 4. **Merges #928 (114d015, unchanged).** It makes `ActionsLock` accept this repo's own v0.0.3 lock, which turns E2E/Integration green. The two PRs merge in either order. 5. **Explicit secrets (6162439).** `secrets: inherit` is replaced with exactly what each callee declares: `HYPATIA_SCAN_PAT` for hypatia-scan, the seven forge keys for mirror, and nothing for scorecard and secret-scanner (standards#1108 §6b). This clears four WH008 baseline findings. 6. **Cargo workspace exclude (c19c465).** The governance JS-runtimes job stages standards' crate at `.standards-js/`, and this repo's root workspace made cargo refuse to build it. The root fix is hyperpolymath/standards#1299; this exclude is harmless after it lands. ## Verified - Governance lock gate at `75bd599` (gh-actions-lock v0.2.0): exit 0. - `check-uuid-v8.sh --strict .`: exit 0. - Gitleaks 8.18.4 (the pinned binary) with the 75bd599 baseline: history pass 5 leaks, then 0; tree pass clean. A planted secret at the same path and line is still caught. - With the crate staged as CI does, `cargo metadata` fails before c19c465 and passes after. The job's `cargo install --locked` builds, and `js-runtimes provision .` exits 0. - **Same repin as hyperpolymath/palimpsest-license#187**, which passes all its checks. ## Open - **`Validate Hypatia Baseline` needs an owner decision.** The scanner pin moved from `0e91342` to `51ab649`, which surfaces 36 findings the baseline never covered: 2 `invalid_actions_lock` (cleared by the pending standards `hypatia-ref` bump past #928), and 34 from newer rules (WH013, RE001, RE004/5, `hardcoded_tmp`, `eval_in_shell`). Details and options are in the PR comments. - **Already red on `main`:** - `abi-codegen-drift`: stale Idris2 cache key; - `Rust License & Ban Check`: `deny.toml` schema; - `Rust Dependency Audit`: RustSec advisories; - Mirror: Bitbucket access. Proposed fixes for each are in the PR comments. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01LET2eHeDbN3b4WuxYjMUX9 --------- Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
Why
gh-actions-lock v0.2.0 writes lockfile v0.0.3, and the estate's lock gate now pins v0.2.0 (hyperpolymath/standards#1250).
Hypatia.Rules.ActionsLockaccepts only v0.0.2.workflow_auditandworkflow_hardening, at high severity. It happened on ci: add actions.lock, run governance at standards b26d3fb, repin dtolnay/rust-toolchain palimpsest-license#177 as code-scanning alerts 347 and 349.actions.lockhas been v0.0.3 since chore(deps): bump the actions group across 1 directory with 7 updates #926. Its existing test"parses the repository's authoritative generated lockfile"therefore fails against the unpatched module.What
114d015. For github.com dependencies, v0.0.3 uses the v0.0.2 line grammar. I measured this on this repo's lock and on
rsr-template-repo's, both v0.0.3:workflows:anddependencies:sections;ref,commit,owner_id,repo_id,uses);'<path>': []form for a workflow with nothing to lock.So:
@supported_version "v0.0.2"becomes@supported_versions ["v0.0.2", "v0.0.3"], both parsed by the one strict grammar.{:unsupported_version, v}, and a secondversion:line is still:duplicate_version.a50c0e5 is for CodeRabbit's finding on #929. v0.0.3 adds one optional per-dependency field,
hostname. The v0.2.0 binary hasjson:"hostname,omitempty", and it is written only for GHE.com data-residency tenants, never for github.com. Neither real v0.0.3 lock in the estate carries it. Rather than model multi-host identity for hosts the estate doesn't use:hostname: 'github.com'is accepted, as the default it states;{:unsupported_dependency_hostname, host};The moduledoc records both points.
Tests
test/rules/actions_lock_test.exsgains three cases:v0.0.1,v0.0.4,v0.1.0and a bare0.0.3are each refused, and a second version line is a duplicate.hostnamebehaves as listed above, including a duplicatehostnameline.I couldn't run the full suite in my sandbox, because repo.hex.pm is blocked there, so
mix deps.getcannot run. Instead I ran this test file standalone against the compiled module with Elixir 1.14. I left out only the legacyHypatia.Rulescase, which needs the full engine.main)The patched parser also reads four real locks:
lib/rules/actions_lock.exis formatter-clean. I left the untouched test lines as CI's Elixir 1.17 formatter has them.Relation to #929
#929 merges this branch unchanged (114d015 and a50c0e5), so CI there exercises this code too. The two PRs merge in either order.
Follow-up
When this merges, standards'
hypatia-scan-reusable.ymlandgovernance-reusable.ymlcan move their defaulthypatia-reffrom51ab649to the merge commit. That makes the estate scanner accept v0.0.3 locks.🤖 Generated with Claude Code
https://claude.ai/code/session_01LET2eHeDbN3b4WuxYjMUX9