Repository navigation
fix(ci): replace the three actions the estate policy rejects at start-up (editorconfig-checker, webfactory/ssh-agent, dtolnay/rust-toolchain) #1147
Description
Four actions are named in rhodium-standard-repositories/actions-allowlist/
allowed-actions.json but are NOT accepted by the live organisation setting,
because they are neither GitHub-owned nor Marketplace-verified creators:
editorconfig-checker/action-editorconfig-checker governance-reusable.yml
webfactory/ssh-agent mirror-reusable.yml (6x)
dtolnay/rust-toolchain mirror-reusable.yml
goto-bus-stop/setup-zig (consumers, see #103)
A rejected uses: does not fail a job — it fails the WORKFLOW, before a
single step runs, with startup_failure and zero check runs. Because these
live in reusable workflows, one rejected action takes out every caller at
once. Measured on hyperpolymath/game-server-admin: Governance and
Mirror to Git Forges produce no check runs at all (game-server-admin#103).
Per the owner's ruling on #103 the allow-list is not to be widened, so the
actions go and their behaviour is kept:
- EditorConfig check — install the pinned module with
go install ...@v4.0.2
and run the binary.go installverifies against the Go checksum
database, a stronger guarantee than the action gave. The step stays
advisory (continue-on-error) exactly as before. - ssh-agent — start
ssh-agentandssh-addthe key from the caller's
secret, exporting SSH_AUTH_SOCK/SSH_AGENT_PID for the push steps. No
third-party code involved. - Rust toolchain — GitHub-hosted runners already carry stable Rust, so
select it withrustup default stableinstead of installing another.
actions.lock: the two now-unreferenced dependency blocks are dropped and
their entries removed from the affected workflow sections.
dtolnay/rust-toolchain stays in the dependencies map — rust-ci-reusable.yml
still uses it, and that workflow is out of scope here.
Verified with this repo's own .githooks/validate-actions-lock.sh:
24 SHA-pinned refs checked against 23 lockfile keys, 0 errors.
Why this needs a human with push access
The credential available to the agent that produced this patch is a GitHub
App installation without contents: write on hyperpolymath/standards —
git push returns Permission to hyperpolymath/standards.git denied to hyperpolymath, and POST /git/refs returns Resource not accessible by integration. So this is filed as an issue with the patch attached rather
than as a pull request. git am applies it cleanly on top of a41f3692.
What is broken, precisely
rhodium-standard-repositories/actions-allowlist/allowed-actions.json lists
89 patterns, including all three of the actions below. The live
organisation setting does not accept them: they are neither GitHub-owned nor
created by a verified Marketplace creator. That gap between the file and the
setting is itself worth closing, but the owner's ruling on
game-server-admin#103 was not to widen the allow-list, so the callers change
instead.
A rejected uses: does not fail a job — it fails the workflow, before a
single step runs, with startup_failure and zero check runs. Because
these three sit inside reusable workflows, one rejected action takes out
every caller at once.
Measured on hyperpolymath/game-server-admin at e6836310:
| workflow | result | rejected action |
|---|---|---|
| Governance | startup_failure, no check runs |
editorconfig-checker/action-editorconfig-checker@840e866d |
| Mirror to Git Forges | startup_failure, no check runs |
webfactory/ssh-agent@e8387483, dtolnay/rust-toolchain@02cb101e |
Both have been in these reusable workflows since they were created
(#187 for mirror, #81 for governance), so there is no earlier clean
commit to re-pin to.
What the patch does
- EditorConfig check —
go install github.com/editorconfig-checker/editorconfig-checker/v4/cmd/editorconfig-checker@v4.0.2, then run the binary.go installverifies the module against the Go checksum database, which is a stronger guarantee than the action ever gave. The step stays advisory (continue-on-error: true), exactly as before. - ssh-agent (6 call sites) — start
ssh-agent,ssh-addthe key from the caller's secret, exportSSH_AUTH_SOCK/SSH_AGENT_PIDfor the push steps. No third-party code involved. - Rust toolchain (Radicle job) — GitHub-hosted runners already ship stable Rust, so
rustup default stableinstead of installing another. - actions.lock — the two now-unreferenced dependency blocks are dropped and their entries removed from the affected workflow sections.
dtolnay/rust-toolchainstays in the dependencies map becauserust-ci-reusable.ymlstill uses it.
Verified with this repo's own .githooks/validate-actions-lock.sh:
24 SHA-pinned refs checked against 23 lockfile keys, 0 errors.
Out of scope here, but the same bug
rust-ci-reusable.yml still uses dtolnay/rust-toolchain five times, so
every consumer of that reusable is in the same state. It was left alone
because swapping it changes toolchain selection semantics for Rust repos,
which needs its own decision.
Unified diff (329 lines, applies on a41f369)
diff --git a/.github/workflows/actions.lock b/.github/workflows/actions.lock
index 4b140c82..0ebc5d2d 100644
--- a/.github/workflows/actions.lock
+++ b/.github/workflows/actions.lock
@@ -66,7 +66,6 @@ workflows:
'.github/workflows/governance-reusable.yml':
- 'actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9'
- 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1'
- - 'editorconfig-checker/action-editorconfig-checker@51f63319f592f97930c73d9c46184d20bd206393'
- 'erlef/setup-beam@54075bcc5e249e4758d363f27d099f55d843f124'
'.github/workflows/governance.yml': []
'.github/workflows/hypatia-scan-reusable.yml':
@@ -94,8 +93,6 @@ workflows:
- 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1'
'.github/workflows/mirror-reusable.yml':
- 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1'
- - 'dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de'
- - 'webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555'
'.github/workflows/mirror.yml': []
'.github/workflows/no-js-scan.yml':
- 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1'
@@ -225,11 +222,6 @@ dependencies:
commit: 'sha1-02cb101ec7c40f2c49e1d9714d64511d8e1b74de'
owner_id: 1940490
repo_id: 260749683
- 'editorconfig-checker/action-editorconfig-checker@51f63319f592f97930c73d9c46184d20bd206393':
- ref: 'v3.0.0'
- commit: 'sha1-51f63319f592f97930c73d9c46184d20bd206393'
- owner_id: 26415196
- repo_id: 297874902
'erlef/setup-beam@54075bcc5e249e4758d363f27d099f55d843f124':
ref: '54075bcc5e249e4758d363f27d099f55d843f124'
commit: 'sha1-54075bcc5e249e4758d363f27d099f55d843f124'
@@ -285,8 +277,3 @@ dependencies:
commit: 'sha1-d1b6cd204f8dceda5b3eaad7f1f767be390056cd'
owner_id: 48932923
repo_id: 360548653
- 'webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555':
- ref: 'e83874834305fe9a4a2997156cb26c5de65a8555'
- commit: 'sha1-e83874834305fe9a4a2997156cb26c5de65a8555'
- owner_id: 135788
- repo_id: 208510314
diff --git a/.github/workflows/governance-reusable.yml b/.github/workflows/governance-reusable.yml
index 6150c2b2..f7fe6d62 100644
--- a/.github/workflows/governance-reusable.yml
+++ b/.github/workflows/governance-reusable.yml
@@ -1054,15 +1054,33 @@ jobs:
else
echo "No files larger than 1M found."
fi
+ # The editorconfig-checker ACTION cannot be used here: it is neither
+ # GitHub-owned nor a verified Marketplace creator, so the estate's
+ # Actions policy rejects it at start-up — and a rejected `uses:` takes
+ # the whole caller workflow with it, startup_failure, zero check runs
+ # (game-server-admin#103). The checker itself is a plain Go binary, so
+ # install the pinned module instead. `go install` verifies the module
+ # against the Go checksum database, which is a stronger guarantee than
+ # the action ever offered.
+ #
+ # advisory-by-design, fails OPEN not closed: formatting hygiene is
+ # reported from the reusable estate bundle; the follow-up step below
+ # emits ::warning:: explicitly when this fails instead of silently
+ # swallowing it. Repos opt into blocking formatter checks locally.
+ # hypatia: allow research_extensions/RE005 -- advisory-by-design, fails OPEN; see comment above.
- name: EditorConfig check
id: editorconfig_check
- uses: editorconfig-checker/action-editorconfig-checker@51f63319f592f97930c73d9c46184d20bd206393 # v3.0.0
- # advisory-by-design, fails OPEN not closed: formatting hygiene is
- # reported from the reusable estate bundle; the follow-up step below
- # emits ::warning:: explicitly when this fails instead of silently
- # swallowing it. Repos opt into blocking formatter checks locally.
- # hypatia: allow research_extensions/RE005 -- advisory-by-design, fails OPEN; see comment above.
continue-on-error: true
+ env:
+ EC_VERSION: v4.0.2
+ run: |
+ set -uo pipefail
+ if ! go install \
+ "github.com/editorconfig-checker/editorconfig-checker/v4/cmd/editorconfig-checker@${EC_VERSION}"; then
+ echo "::warning::could not install editorconfig-checker ${EC_VERSION}; EditorConfig check skipped"
+ exit 0
+ fi
+ "$(go env GOPATH)/bin/editorconfig-checker" .
- name: EditorConfig check - surface result
if: steps.editorconfig_check.outcome == 'failure'
run: echo "::warning::EditorConfig check found formatting issues (advisory only — see the 'EditorConfig check' step's own log above; repos opt into blocking locally when ready)."
diff --git a/.github/workflows/mirror-reusable.yml b/.github/workflows/mirror-reusable.yml
index 7338c426..f5aba0cb 100644
--- a/.github/workflows/mirror-reusable.yml
+++ b/.github/workflows/mirror-reusable.yml
@@ -82,10 +82,23 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- - uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0
+ # webfactory/ssh-agent is neither GitHub-owned nor a verified Marketplace
+ # creator, so the estate's Actions policy rejects it at start-up and
+ # every caller's mirror workflow dies with startup_failure
+ # (game-server-admin#103). Nothing in it is hard to do by hand: start an
+ # agent and load the key.
+ - name: Start ssh-agent
if: ${{ env.GITLAB_KEY != '' }}
- with:
- ssh-private-key: ${{ secrets.GITLAB_SSH_KEY }}
+ env:
+ GITLAB_KEY: ${{ secrets.GITLAB_SSH_KEY }}
+ run: |
+ set -euo pipefail
+ eval "$(ssh-agent -s)"
+ key="$(mktemp)"
+ printf '%s\n' "$GITLAB_KEY" > "$key"
+ ssh-add "$key"
+ rm -f "$key"
+ printf 'SSH_AUTH_SOCK=%s\nSSH_AGENT_PID=%s\n' "$SSH_AUTH_SOCK" "$SSH_AGENT_PID" >> "$GITHUB_ENV"
- name: Verify gitlab SSH host
if: ${{ env.GITLAB_KEY != '' }}
env:
@@ -139,10 +152,23 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- - uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0
+ # webfactory/ssh-agent is neither GitHub-owned nor a verified Marketplace
+ # creator, so the estate's Actions policy rejects it at start-up and
+ # every caller's mirror workflow dies with startup_failure
+ # (game-server-admin#103). Nothing in it is hard to do by hand: start an
+ # agent and load the key.
+ - name: Start ssh-agent
if: ${{ env.BITBUCKET_KEY != '' }}
- with:
- ssh-private-key: ${{ secrets.BITBUCKET_SSH_KEY }}
+ env:
+ BITBUCKET_KEY: ${{ secrets.BITBUCKET_SSH_KEY }}
+ run: |
+ set -euo pipefail
+ eval "$(ssh-agent -s)"
+ key="$(mktemp)"
+ printf '%s\n' "$BITBUCKET_KEY" > "$key"
+ ssh-add "$key"
+ rm -f "$key"
+ printf 'SSH_AUTH_SOCK=%s\nSSH_AGENT_PID=%s\n' "$SSH_AUTH_SOCK" "$SSH_AGENT_PID" >> "$GITHUB_ENV"
- name: Verify bitbucket SSH host
if: ${{ env.BITBUCKET_KEY != '' }}
env:
@@ -190,10 +216,23 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- - uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0
+ # webfactory/ssh-agent is neither GitHub-owned nor a verified Marketplace
+ # creator, so the estate's Actions policy rejects it at start-up and
+ # every caller's mirror workflow dies with startup_failure
+ # (game-server-admin#103). Nothing in it is hard to do by hand: start an
+ # agent and load the key.
+ - name: Start ssh-agent
if: ${{ env.CODEBERG_KEY != '' }}
- with:
- ssh-private-key: ${{ secrets.CODEBERG_SSH_KEY }}
+ env:
+ CODEBERG_KEY: ${{ secrets.CODEBERG_SSH_KEY }}
+ run: |
+ set -euo pipefail
+ eval "$(ssh-agent -s)"
+ key="$(mktemp)"
+ printf '%s\n' "$CODEBERG_KEY" > "$key"
+ ssh-add "$key"
+ rm -f "$key"
+ printf 'SSH_AUTH_SOCK=%s\nSSH_AGENT_PID=%s\n' "$SSH_AUTH_SOCK" "$SSH_AGENT_PID" >> "$GITHUB_ENV"
- name: Verify codeberg SSH host
if: ${{ env.CODEBERG_KEY != '' }}
env:
@@ -241,10 +280,23 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- - uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0
+ # webfactory/ssh-agent is neither GitHub-owned nor a verified Marketplace
+ # creator, so the estate's Actions policy rejects it at start-up and
+ # every caller's mirror workflow dies with startup_failure
+ # (game-server-admin#103). Nothing in it is hard to do by hand: start an
+ # agent and load the key.
+ - name: Start ssh-agent
if: ${{ env.SOURCEHUT_KEY != '' }}
- with:
- ssh-private-key: ${{ secrets.SOURCEHUT_SSH_KEY }}
+ env:
+ SOURCEHUT_KEY: ${{ secrets.SOURCEHUT_SSH_KEY }}
+ run: |
+ set -euo pipefail
+ eval "$(ssh-agent -s)"
+ key="$(mktemp)"
+ printf '%s\n' "$SOURCEHUT_KEY" > "$key"
+ ssh-add "$key"
+ rm -f "$key"
+ printf 'SSH_AUTH_SOCK=%s\nSSH_AGENT_PID=%s\n' "$SSH_AUTH_SOCK" "$SSH_AGENT_PID" >> "$GITHUB_ENV"
- name: Verify sourcehut SSH host
if: ${{ env.SOURCEHUT_KEY != '' }}
env:
@@ -292,10 +344,23 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- - uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0
+ # webfactory/ssh-agent is neither GitHub-owned nor a verified Marketplace
+ # creator, so the estate's Actions policy rejects it at start-up and
+ # every caller's mirror workflow dies with startup_failure
+ # (game-server-admin#103). Nothing in it is hard to do by hand: start an
+ # agent and load the key.
+ - name: Start ssh-agent
if: ${{ env.DISROOT_KEY != '' }}
- with:
- ssh-private-key: ${{ secrets.DISROOT_SSH_KEY }}
+ env:
+ DISROOT_KEY: ${{ secrets.DISROOT_SSH_KEY }}
+ run: |
+ set -euo pipefail
+ eval "$(ssh-agent -s)"
+ key="$(mktemp)"
+ printf '%s\n' "$DISROOT_KEY" > "$key"
+ ssh-add "$key"
+ rm -f "$key"
+ printf 'SSH_AUTH_SOCK=%s\nSSH_AGENT_PID=%s\n' "$SSH_AUTH_SOCK" "$SSH_AGENT_PID" >> "$GITHUB_ENV"
- name: Verify disroot SSH host
if: ${{ env.DISROOT_KEY != '' }}
env:
@@ -343,10 +408,23 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- - uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0
+ # webfactory/ssh-agent is neither GitHub-owned nor a verified Marketplace
+ # creator, so the estate's Actions policy rejects it at start-up and
+ # every caller's mirror workflow dies with startup_failure
+ # (game-server-admin#103). Nothing in it is hard to do by hand: start an
+ # agent and load the key.
+ - name: Start ssh-agent
if: ${{ env.GITEA_KEY != '' }}
- with:
- ssh-private-key: ${{ secrets.GITEA_SSH_KEY }}
+ env:
+ GITEA_KEY: ${{ secrets.GITEA_SSH_KEY }}
+ run: |
+ set -euo pipefail
+ eval "$(ssh-agent -s)"
+ key="$(mktemp)"
+ printf '%s\n' "$GITEA_KEY" > "$key"
+ ssh-add "$key"
+ rm -f "$key"
+ printf 'SSH_AUTH_SOCK=%s\nSSH_AGENT_PID=%s\n' "$SSH_AUTH_SOCK" "$SSH_AGENT_PID" >> "$GITHUB_ENV"
- name: Verify gitea SSH host
if: ${{ env.GITEA_KEY != '' }}
env:
@@ -406,11 +484,19 @@ jobs:
# Caught 26 estate repos on the 2026-05-30 audit. The vars gate
# answers "is Radicle mirror desired here?"; the secret gate
# answers "are we configured to actually do it?".
- - name: Setup Rust
+ # dtolnay/rust-toolchain is neither GitHub-owned nor a verified
+ # Marketplace creator (game-server-admin#103): its presence here
+ # startup_fails every caller of this reusable. GitHub-hosted runners
+ # already ship a stable Rust toolchain, so select that one rather than
+ # installing another.
+ - name: Select the runner's Rust toolchain
if: ${{ env.RADICLE_KEY != '' }}
- uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de # stable
- with:
- toolchain: stable
+ run: |
+ set -euo pipefail
+ echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
+ rustup default stable
+ rustc --version
+ cargo --version
- name: Install Radicle
if: ${{ env.RADICLE_KEY != '' }}
run: |
--
2.39.5
Activity
fix(ci): restore the required-check producers — allow-list, actions.l…