ci: audit orphaned Actions workflow identities - #203
Conversation
|
Warning Review limit reached
Next review available in: 14 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
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. Comment |
|
@coderabbitai review exact head |
|
@opencode-agent review exact head |
|
@cwl-noema-review independently review exact head |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
expected_head='9ac4bc2de5bdba2e92be184e46a42ef55627bd77'
actual_head="$(git rev-parse HEAD)"
printf 'expected_head=%s\nactual_head=%s\n' "$expected_head" "$actual_head"
git diff --no-ext-diff --unified=80 "${expected_head}^" "${expected_head}" -- \
scripts/ci/audit_workflow_registry.py \
tests/test_workflow_registry_audit.py \
tests/test_workflow_registry_partial_transfer.py \
tests/test_workflow_registry_state_integrity.py
printf '\n== Production module outline ==\n'
ast-grep outline scripts/ci/audit_workflow_registry.py --items all --view expanded
printf '\n== Focused test outlines ==\n'
ast-grep outline tests/test_workflow_registry_audit.py --items all --view expanded
ast-grep outline tests/test_workflow_registry_partial_transfer.py --items all --view expanded
ast-grep outline tests/test_workflow_registry_state_integrity.py --items all --view expanded
printf '\n== Focused implementation symbols ==\n'
rg -n -C 8 -e '^(def|class) ' \
-e 'urlopen|IncompleteRead|HTTPError|URLError|AuditError' \
-e 'pagination|page|workflow|lifecycle|state|active|disabled' \
scripts/ci/audit_workflow_registry.py
printf '\n== Focused test assertions ==\n'
rg -n -C 6 -e 'IncompleteRead|__cause__|__context__' \
-e 'future_state|lifecycle|disabled_absent|active_orphan' \
-e 'pagination|page|partial' \
tests/test_workflow_registry_audit.py \
tests/test_workflow_registry_partial_transfer.py \
tests/test_workflow_registry_state_integrity.pyLength of output: 71186 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Exact changed-file scope =='
git diff-tree --no-commit-id --name-status -r 9ac4bc2de5bdba2e92be184e46a42ef55627bd77
printf '%s\n' '== Live audit control flow =='
sed -n '124,570p' scripts/ci/audit_workflow_registry.py
printf '%s\n' '== Complete focused tests =='
cat -n tests/test_workflow_registry_audit.py
cat -n tests/test_workflow_registry_partial_transfer.py
cat -n tests/test_workflow_registry_state_integrity.py
printf '%s\n' '== HTTP request construction and potential mutation surface =='
ast-grep run --lang python \
--pattern 'urllib.request.Request($URL, headers=$HEADERS, method=$METHOD)' \
scripts/ci/audit_workflow_registry.py
rg -n -C 3 \
-e 'method\s*=' \
-e 'actions/workflows|branches/|pulls/|contents/' \
-e '\b(POST|PUT|PATCH|DELETE)\b' \
scripts/ci/audit_workflow_registry.py
printf '%s\n' '== State validation and classification call paths =='
rg -n -C 5 \
-e '_require_workflow_state\s*\(' \
-e 'classification\s*=' \
-e 'collect_registry_pages\s*\(' \
-e '_collect_open_pr_workflow_snapshot\s*\(' \
scripts/ci/audit_workflow_registry.pyLength of output: 45409 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Final lines with end-of-line markers =='
tail -n 20 tests/test_workflow_registry_audit.py | sed -n 'l'
printf '%s\n' '== File length and final bytes =='
wc -l tests/test_workflow_registry_audit.py
tail -c 160 tests/test_workflow_registry_audit.py | od -An -tx1c
printf '%s\n' '== Standard-library tokenization check; repository code is not executed =='
python - <<'PY'
from pathlib import Path
import io
import tokenize
path = Path("tests/test_workflow_registry_audit.py")
source = path.read_bytes()
try:
list(tokenize.tokenize(io.BytesIO(source).readline))
except (tokenize.TokenError, IndentationError, SyntaxError) as exc:
print(f"tokenization_error={type(exc).__name__}: {exc}")
else:
print("tokenization_ok")
PYLength of output: 2111
I found no valid findings in the requested scope.
The last verification command could not run
|
Purpose
Progress issue #202 with a read-only recurrence detector for GitHub Actions registry identities that remain active after their repository workflow source disappears. This PR does not disable workflows, add workflow-write authority, mint credentials, or restore historical one-shot workflow sources.
Exact current identity
7faf7a3b8a47980113982914000e724ab6a6cda5;9ac4bc2de5bdba2e92be184e46a42ef55627bd77;scripts/ci/audit_workflow_registry.py,tests/test_workflow_registry_audit.py,tests/test_workflow_registry_partial_transfer.py, andtests/test_workflow_registry_state_integrity.py;Implemented audit contract
The auditor is finite and read-only. It:
active,deleted,disabled_fork,disabled_inactivity, anddisabled_manually; an unknown provider/future state fails closed instead of being silently treated as disabled;AuditErrorwhose__cause__and__context__are both absent;It never disables a workflow, updates a branch, comments on a PR, requests a reviewer, publishes status, or changes repository state.
Test-first lineage added on this lane
Partial-transfer boundary
06f5fbf3a96f77bae9ba2e8bd674813773a761e9;31662731204, Python 3.14 job94330765367:1 failed, 1043 passed; rawIncompleteRead(11 bytes read, 100 more expected)escaped;d936687d94ec26911854ceac8cb87aba1e173909caught the transfer failure;31663075087, Python 3.14 job94331810126:1 failed, 1043 passed; the genericAuditErrorstill retainedIncompleteReadin__context__;7d3edee15b184c308b7fa77670a239218989c57erecords a bounded failure classification inside the handler and raises a fresh generic error only after leaving the active exception context.Unknown lifecycle state boundary
A further audit found that any non-empty state string other than
activewas previously classified asdisabled_absent. A future or malformed provider state could therefore be misrepresented as safely disabled.ee0a630d7f94f8f61d7a7c56e6e4b95799de3ff4;31663714501, Python 3.11 job94333748752: exact checkout and Ruff passed; pytest reported1 failed, 1044 passedbecauseprovider_future_statedid not raise;9ac4bc2de5bdba2e92be184e46a42ef55627bd77introduces one exact lifecycle-state validator and applies it in both the final audit and registry recheck snapshot.Exact-current-head proof
On unchanged
9ac4bc2de5bdba2e92be184e46a42ef55627bd77:31663948791: completed success across wheel/sdist package acceptance and Python 3.10, 3.11, 3.12, 3.13, and 3.14;94334452103: checked out exact9ac4bc2..., ran CPython 3.14.7, Ruff,1045 passed, product guard and compileall successfully;1758/1758statements and588/588branches, zero misses/partials;31663948803, Security Scan31663948798, dependency-review job/check94334454133, and required Strix run31663947448/ check94334450406remain queued at the latest refetch. Queued evidence is non-passing.Remaining acceptance
Dependency reviewaction to execute and succeed. Aggregate wrapper green with that action skipped remains non-passing; the root fail-closed repair is read-only central PRContextualWisdomLab/.github#897or a freshly verified protected successor.Direct lifecycle disablement remains a separate operator/control-plane action. Do not reintroduce removed YAML, create a self-deleting cleanup workflow, invent a PAT, weaken a required gate, or disable workflows by display name.