Skip to content

fix(ci): detect orphaned Actions workflow identities - #279

Draft
seonghobae wants to merge 20 commits into
mainfrom
fix/actions-workflow-registry-audit-278
Draft

fix(ci): detect orphaned Actions workflow identities#279
seonghobae wants to merge 20 commits into
mainfrom
fix/actions-workflow-registry-audit-278

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Closes #278.

Boundary

This Draft is the read-only Actions workflow-registry evidence lane. The detector never calls GitHub, reads credentials, disables/restores workflows, mutates refs, or creates workflow-control authority. Operational workflow disablement remains an authorized control-plane action after a fresh complete registry observation.

Protected main is independently resolved at e8109ec2a17de8bd6594487aa12c8c8a93cb2c03. The PR metadata base is historical (a430b1c153702de3b6439def801732d7453b4940); exact comparison against live protected main reports this branch diverged, 20 commits ahead / 5 behind. This branch is therefore not integrated-live-base proof and must remain Draft.

Detector contract

  • exact protected-main SHA/time evidence and optional end-SHA stability proof;
  • complete pagination receipts and advertised-total accounting;
  • source-backed, active-orphan, explicitly owned repair, disabled, GitHub-dynamic, path-mismatch, unresolved-path, and ambiguous-identity classification without filename/name heuristics;
  • bounded path/page/workflow counts, strict schema/state validation and fail-closed duplicate/incomplete pagination;
  • bounded regular-file fixture ingestion, strict UTF-8 and JSON validation; and
  • no silent path case/percent-encoding normalization.

Exact repair-owner evidence — RED → GREEN

A fresh audit found that ownedActiveRepairPaths could classify an active workflow identity as owned_active_repair using only its path. That did not retain the exact PR/head authority supporting the exemption and therefore weakened acquisition/control-plane evidence.

Hosted RED — a9f207cccad000521bcbca9a2a170ca96f55fd1e

Test-only src/actionsWorkflowRegistryAuditRepairOwnership.test.ts required legacy path-only repair exemptions to fail closed and structured { path, prNumber, headSha } evidence to be retained in output. CI 31827066178, build/test job 94853582276, checked out that exact SHA, completed immutable install and typecheck, then failed exactly the two new assertions while the pre-existing suite remained green.

Contract migration — 81bccd014ef5231219887420d61283d73a597b66

The existing registry-audit fixture was migrated to the same exact repair-owner contract; no production relaxation was introduced.

GREEN — current exact head 955e5228446926f0583ef08f434431a757584f79

Production now accepts only optional ownedActiveRepairs, where every exemption is an exact object containing a canonical workflow path, positive safe-integer PR number, and lowercase 40-hex head SHA. Duplicate repair paths fail closed. owned_active_repair evidence includes the exact { prNumber, headSha } owner. Legacy path-only input is rejected by the strict top-level contract. The detector remains offline/read-only and gains no credential, ref, workflow-disable, network, or execution authority.

Exact-head proof and browser RCA

For unchanged head 955e5228446926f0583ef08f434431a757584f79:

  • repository CI 31827389419: completed / success after same-SHA retry;
  • build/test passed immutable install, typecheck, repository 100% owned-production coverage, library/package/demo verification;
  • Office Python 3.11–3.14 jobs passed on the exact head;
  • first browser attempt failed during WebKit setup at clipboard.browser.spec.ts beforeEach after a 20 s timeout, before the detector could influence browser behavior;
  • the normal GitHub failed-job rerun was executed without changing source or SHA; exact same-head browser job 94855718608 then completed success, including the real-engine rich-clipboard evidence;
  • predecessor test-only head a9f207... had also passed the browser lane, supporting transient WebKit startup/setup RCA rather than a detector regression;
  • formal reviews: 0; unresolved inline review threads: 0.

At this evidence generation, exact-head Security Scan 31827389442 and SAST Semgrep 31827389440 remain queued / non-passing. Queued, pending, skipped, cancelled, absent, predecessor, status-only, and model-only evidence is not represented as passing proof.

Integration boundary

Live organization policy requires one qualifying independent approval, last-push approval by someone other than the pusher, review-thread resolution, and all applicable central required workflows. The exact current branch is also 5 protected-main commits behind, and this invocation has no supported non-destructive branch-sync mutation; that exact reconciliation action is therefore unavailable rather than inferred as repository state. Do not force-push, destructively rebase, or manufacture merge/tag/release identity.

Issue #118 continues to own exact v0.6.0 publication from protected main. Fresh Actions registry observation remains larger than protected-main workflow source inventory; operational disablement must use a fresh complete registry snapshot and preserve current repair/dynamic identities. Any source-head or live-base movement invalidates this evidence.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0ee59505-d711-4380-bf4c-6baf60a8b581

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

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.

[Fleet incident] Disable orphaned one-shot and finalizer workflow identities

1 participant