Skip to content

fix(actions-lock): accept lockfile v0.0.3 (github.com dependencies) - #928

Merged
hyperpolymath merged 4 commits into
mainfrom
claude/actions-lock-v0.0.3
Oct 20, 2026
Merged

hyperpolymath merged 4 commits into
mainfrom
claude/actions-lock-v0.0.3

Conversation

@hyperpolymath

@hyperpolymath hyperpolymath commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

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.ActionsLock accepts only v0.0.2.

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:

  • the same workflows: and dependencies: sections;
  • the same record fields (ref, commit, owner_id, repo_id, uses);
  • the same '<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.
  • Every other version string is still {:unsupported_version, v}, and a second version: 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 has json:"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;
  • any other host is refused by name, {:unsupported_dependency_hostname, host};
  • in a v0.0.2 lock, the field is still malformed.

The moduledoc records both points.

Tests

test/rules/actions_lock_test.exs gains three cases:

  • v0.0.3 is accepted with the same association semantics, and a malformed v0.0.3 lock still fails closed.
  • v0.0.1, v0.0.4, v0.1.0 and a bare 0.0.3 are each refused, and a second version line is a duplicate.
  • hostname behaves as listed above, including a duplicate hostname line.

I couldn't run the full suite in my sandbox, because repo.hex.pm is blocked there, so mix deps.get cannot run. Instead I ran this test file standalone against the compiled module with Elixir 1.14. I left out only the legacy Hypatia.Rules case, which needs the full engine.

Module Result
patched 15 / 15 pass
unpatched (main) the own-lock test fails

The patched parser also reads four real locks:

  • this repo's: v0.0.3, 40 dependencies;
  • rsr-template-repo's: v0.0.3, 37;
  • palimpsest-license's: v0.0.2, 38;
  • standards': v0.0.2, 26.

lib/rules/actions_lock.ex is 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.yml and governance-reusable.yml can move their default hypatia-ref from 51ab649 to the merge commit. That makes the estate scanner accept v0.0.3 locks.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LET2eHeDbN3b4WuxYjMUX9

…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
@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: ef70675d-263e-4607-94e5-baa3078af003
📥 Commits

Reviewing files that changed from the base of the PR and between fd7db07 and c6ef113.

📒 Files selected for processing: 2
  • lib/rules/actions_lock.ex
  • test/rules/actions_lock_test.exs
📜 Recent review details
⏰ Context from checks skipped due to timeout: 6
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: docs
  • GitHub Check: Validate Documentation
  • GitHub Check: lint
  • GitHub Check: Build AsciiDoc
  • GitHub Check: Language Policy
🔇 Additional comments: 2
lib/rules/actions_lock.ex: 1

6-7: LGTM!

Also applies to: 17-18, 20-26, 28-34, 37-37, 58-58, 156-157, 159-159, 166-166, 233-235, 237-241

test/rules/actions_lock_test.exs: 1

86-97: LGTM!

Also applies to: 99-124, 126-139

📝 Summary

Summary by CodeRabbit

  • Compatibility
    • Lockfiles using versions v0.0.2 and v0.0.3 are supported.
    • For v0.0.3 dependencies, github.com is accepted as the hostname; dependencies specifying other hostnames are rejected. The parser supports GitHub-hosted dependencies only.

The lockfile parser now accepts versions v0.0.2 and v0.0.3. For v0.0.3, it accepts an explicit github.com hostname and rejects other hostnames. Tests cover version and hostname parsing.

Changes: Actions lockfile parsing

Layer / File(s) Summary
Supported lockfile versions
lib/rules/actions_lock.ex, test/rules/actions_lock_test.exs
The parser accepts v0.0.2 and v0.0.3. Tests cover supported and unsupported versions, duplicate version lines, and parsing dependencies with pinning.
v0.0.3 hostname handling
lib/rules/actions_lock.ex, test/rules/actions_lock_test.exs
For v0.0.3, the parser accepts github.com as the hostname and rejects other hostnames. Tests cover hostname handling, including duplicate fields and the v0.0.2 restriction.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to c6ef1

No actionable issue remains in the supplied review evidence. This change is mergeable after normal checks.

Security architecture risk: 🔵 Low · up to c6ef1

The change extends lockfile compatibility while retaining GitHub-only hostname handling and whole-file validation. No new cross-host bypass was identified. Commit authenticity still depends on separate lock verification.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — A contributor able to alter a scanned repository's lock content can influence pinning diagnostics for workflow/ref pairs associated by that lock. The newly reachable outcome is diagnostic suppression for valid v0.0.3 input, using the same authority previously available through v0.0.2.

Trust Boundaries and Controls

  • observed — The host boundary remains github.com-only. Non-default hosts cannot enter the hostless dependency identity model, and pin lookup still requires both the current workflow's normalized ref and a matching validated dependency.

Resilience and Maintainability Implications

  • observed — Each parse starts with fresh local state, halts on a line error, and exposes no partial lock. Duplicate dependency fields are rejected, and terminal validation errors propagate rather than authorizing the remaining entries. The v0.0.3 extension retains this failure-containment behavior.
Pre-merge checks: Passed 5
Check name Status Explanation
Title check Passed The title clearly and concisely states the main change: accepting lockfile v0.0.3 for github.com dependencies.
Description check Passed The description directly explains the v0.0.3 compatibility change, hostname handling, tests, validation results, and known test limitations.
Docstring Coverage Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2 files.

✨ Finishing Touches
📝 Generate docstrings
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copy link
Copy Markdown
Owner Author

The red checks here do not come from this PR's change, which touches only lib/rules/actions_lock.ex and its test.

  • Governance jobs, Hypatia Neurosymbolic Analysis, and the Secret Scanner jobs (gitleaks, rust-secrets, shell-secrets). Every one dies at Set up job with invalid lockfile pin for actions/checkout@3d3c42e….
  • abi-codegen-drift. idris2 --version fails with incompatible fasl-object version … idris2.so: the cached Idris2 build (idris2-v0.7.0-Linux-3) no longer matches the runner's Chez Scheme. This is a runner and cache problem, unrelated to Elixir.
  • Rust License & Ban Check. This PR changes no Rust code or Cargo files.

The checks that cover this change passed: Test, Escript packaging soundness, Aspect — Rule Module Coverage, Estate rules and sweep structure and Language Policy.


Generated by Claude Code

@hyperpolymath
hyperpolymath marked this pull request as ready for review October 19, 2026 12:12
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-20T14:58:22.262517Z 8f63ed6 New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

hyperpolymath pushed a commit that referenced this pull request Oct 19, 2026
…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

Copy link
Copy Markdown
Owner Author

#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
hyperpolymath pushed a commit that referenced this pull request Oct 19, 2026
…tions-lock code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LET2eHeDbN3b4WuxYjMUX9
@hyperpolymath hyperpolymath changed the title fix(actions-lock): accept lockfile v0.0.3, which shares the v0.0.2 grammar fix(actions-lock): accept lockfile v0.0.3 (github.com dependencies) Oct 19, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread lib/rules/actions_lock.ex Outdated
Comment on lines +239 to +241
match = state.version == "v0.0.3" && Regex.run(~r/^ hostname: '([^']+)'$/, line) ->
[_, host] = match
line_error(line_number, {:unsupported_dependency_hostname, host})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 hostname binds a pin to the repository's home host.
  • On github.com, hostname must be omitted or github.com, and any other value is rejected.
  • Producers write github.com explicitly only on a GHE.com data-residency instance, and never write a *.ghe.com value.

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 hostname too.
  • Pass the repository host into parsing. That needs host plumbing through Rules.scan_workflow and 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

@hyperpolymath
hyperpolymath enabled auto-merge (squash) October 19, 2026 15:02
@coderabbitai

coderabbitai Bot commented Oct 19, 2026

Copy link
Copy Markdown
Contributor

Add Carrot credits or activate Agent usage billing to use Autofix

hyperpolymath pushed a commit that referenced this pull request Oct 19, 2026
…ch so governance, scan and the lock parser test run green here too

Ported, not re-authored: the same commits as #929 (which carries #928). It no-ops once main carries them.
@coderabbitai

coderabbitai Bot commented Oct 19, 2026

Copy link
Copy Markdown
Contributor

❌ Failed to create Coding Agent finishing-touch task. Please try again.

@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Copy link
Copy Markdown
Owner Author

Closing as superseded. Both parts are on main:

I tried merging current main into this branch. It conflicts in lib/rules/actions_lock.ex, and taking main's parser leaves nothing of this PR. The standards hypatia-ref follow-up this PR proposed has also landed: #940 (61023d1) passes hypatia-ref aa34a4c to the standards scanner reusables.


Generated by Claude Code

auto-merge was automatically disabled October 20, 2026 13:48

Pull request was closed

@hyperpolymath hyperpolymath reopened this Oct 20, 2026

Copy link
Copy Markdown
Owner Author

Reopened. The owner hadn't decided on closing it, so the closure is withdrawn until they do. The analysis above stands: #938 on main covers the parser, and #931 the tests. The PR stays as it was, and its merge conflict with main is unresolved.


Generated by Claude Code

Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
@hyperpolymath
hyperpolymath merged commit 7cc34c6 into main Oct 20, 2026
66 of 75 checks passed
@hyperpolymath
hyperpolymath deleted the claude/actions-lock-v0.0.3 branch October 20, 2026 14:57
hyperpolymath added a commit that referenced this pull request Oct 20, 2026
…#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>
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