ci: keep public conformance credential-free#195
Merged
Conversation
Remove public live-cloud, OIDC, and self-hosted automation. Enforce the boundary with fail-closed semantic workflow policy fixtures while retaining external-loader conformance on PRs and main.
Fail closed on non-GitHub runners, provider actions, and bracket or global secret references so aliases cannot restore public cloud authority.
Reject unsafe permission shapes, computed credentials, unreviewed actions, compound guard commands, and repository path escapes before public automation can gain cloud authority.
Reject whole secret contexts, provider authority hidden in environment indirection, dynamic shell execution, and unreviewed committed scripts. Trusted scripts require exact confined paths, rationale, and matching SHA-256 content.
Use shell ASTs so wrappers, substitutions, and dynamic command words cannot bypass credential-free workflow policy. Restrict provider deny patterns to parser-proven rejection guards.
Require explicit Bash semantics and reject provider-capable program execution across inherited workflow shells. Keep parser dependencies and tests outside the plugin runtime graph, with exact source-integrity binding.
Run pull-request policy from trusted base authority and treat candidate policy files as data. Bind complete workflow context, reject unreviewed execution surfaces, and keep public checks credential-free.
Permit audited workflow updates without weakening trusted-base enforcement. Verify push governance and reject exported Bash function injection across nested command wrappers.
Keep candidate CI scripts on candidate-root hashing while the policy guard uses trusted-root authority. Require exact bootstrap, strict branch checks, and explicit present/absent lifecycle groups so workflow and executable changes remain reviewable without cloud credentials.
A name-only required check can be impersonated by another producer. Require GitHub Actions app/integration ID 15368 with strict freshness in classic protection and rulesets.
Keep pull-request workflows credential-free and bind release tags through quoted environment values. Require force-push/deletion rules and resolve default-branch selectors against repository metadata.
Pull request target workflows carry the same untrusted contribution boundary as pull requests. Reject repository-secret authority on both triggers and inherited job secrets in every public workflow.
Trigger-based checks miss transitive reusable-workflow authority. Allow only the automatic GitHub token in every public workflow and remove release-time repository credentials.
Keep contribution and reusable-workflow paths credential-free while permitting one exact noncloud registry token on the trusted tag-only release path. Public dependency resolution no longer uses GOPRIVATE.
Bind the registry dispatch token to owner-controlled release tags and commits already contained in protected main. Keep privileged governance inspection in the operator prerequisite because GitHub hides bypass actors from read-only workflow tokens.
Move registry synchronization ownership out of the plugin release workflow. Public workflows now reject every named repository secret except the automatic GitHub token, independent of trigger shape or allowlist data.
There was a problem hiding this comment.
Pull request overview
This PR removes DigitalOcean live/credentialed automation from the public repository and replaces it with a credential-free CI posture enforced by a new “public workflow policy” analyzer plus explicit allowlists/trust manifests. It also tightens release integrity by requiring tag commits to already be contained in protected main, and removes private Git credential rewrites / named secret usage from retained public workflows.
Changes:
- Removes all DigitalOcean live/budget/scrub/integration workflows and related scripts/assets, keeping public CI credential-free.
- Adds a new
.github/workflows/public-workflow-policy.ymlworkflow plus a Go-based policy tool and fixtures/allowlists to fail-closed on workflow/action/command/executable trust. - Updates existing CI/release/conformance workflows to use SHA-pinned actions and
github.tokenonly, and adds a release ancestry check againstorigin/main.
Reviewed changes
Copilot reviewed 56 out of 57 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/drivers/database_trusted_sources_integration_test.go | Redacts identifiers in live integration test failure output. |
| docs/public-workflow-policy.md | Documents the new public workflow policy model, bootstrap, and governance expectations. |
| docs/conformance-runbook.md | Removes the live DigitalOcean conformance runbook and operational guidance. |
| .goreleaser.yaml | Removes GOPRIVATE / private credential assumptions during validation/build. |
| .github/workflows/scripts/verify-public-workflow-branch-protection.sh | Adds a read-only verifier for required branch/tag governance and required check producer binding. |
| .github/workflows/scripts/test-conformance-workflows.sh | Deletes legacy conformance workflow structure gate script. |
| .github/workflows/scripts/test-conformance-workflow-mutations.sh | Deletes legacy conformance mutation tests. |
| .github/workflows/scripts/test-conformance-scrub-safety.sh | Deletes legacy scrubber safety tests. |
| .github/workflows/scripts/test-conformance-safety-helpers.sh | Deletes legacy safety helper tests. |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject.yml | Adds fixture workflow expected to be rejected by policy (secrets, self-hosted, provider usage, etc.). |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject-yaml-structure.yml | Adds fixture for rejecting YAML aliases/duplicate keys. |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject-unsafe-programs.yml | Adds fixture for rejecting dynamic/provider-capable programs and wrappers. |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject-unreviewed-uses.yml | Adds fixture for rejecting unreviewed/floaty action refs and local/docker actions. |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject-statement-authority.yml | Adds fixture for rejecting unsafe shell statement shapes (redirects, PATH hijack, env-file writes, etc.). |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject-shell.yml | Adds fixture for rejecting disallowed shell selection. |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject-shell-inheritance.yml | Adds fixture for rejecting inherited/dynamic effective shell behavior. |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject-secret-syntax.yml | Adds fixture for rejecting bracket/dynamic/global secret reference patterns. |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject-script-execution.yml | Adds fixture for rejecting committed-script execution from workflows. |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject-runners.yml | Adds fixture for rejecting nonstandard/dynamic runner selectors. |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject-provider-uses.yml | Adds fixture for rejecting provider actions/reusable workflows. |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject-permissions.yml | Adds fixture for rejecting forbidden permission shapes. |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject-missing-shell.yml | Adds fixture for rejecting workflows without explicit effective shell. |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject-guard-suffix.yml | Adds fixture for rejecting guard-suffix bypass patterns. |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject-global.yml | Adds fixture for rejecting global permission/secret markers. |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject-execution-context.yml | Adds fixture for rejecting execution-affecting context (working-directory, env overrides, etc.). |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject-env-indirection.yml | Adds fixture for rejecting environment indirection/dynamic shells/eval patterns. |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject-dynamic-secrets.yml | Adds fixture for rejecting dynamic secret selectors and whole-context secret usage. |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject-deny-pattern-execution.yml | Adds fixture for rejecting deny-pattern execution bypass. |
| .github/workflows/scripts/fixtures/public-workflow-policy/reject-command-analysis.yml | Adds fixture for rejecting disallowed command wrapper/subshell/substitution shapes. |
| .github/workflows/scripts/fixtures/public-workflow-policy/pass.yml | Adds fixture workflow expected to pass policy (credential-free shapes + pinned actions). |
| .github/workflows/scripts/fixtures/public-workflow-policy/pass-negative-guard.yml | Adds fixture demonstrating allowed negative provider guard usage. |
| .github/workflows/scripts/fixtures/public-workflow-policy/pass_expression-and-deny-guard.yml | Adds fixture showing allowed expressions while keeping deny-pattern confined. |
| .github/workflows/scripts/fixtures/public-workflow-policy/lifecycle-old.yml | Adds lifecycle fixture for staged/active trust transitions (old). |
| .github/workflows/scripts/fixtures/public-workflow-policy/lifecycle-future.yml | Adds lifecycle fixture for staged/active trust transitions (future). |
| .github/workflows/scripts/file-or-comment-leak-issue.sh | Removes legacy issue filing helper for conformance leak/budget incidents. |
| .github/workflows/scripts/conformance-safety.sh | Removes legacy conformance safety helper (budget parsing / DO response checks). |
| .github/workflows/scripts/check-public-workflow-policy.sh | Adds trusted wrapper that verifies policytool integrity and runs policytool in readonly mode. |
| .github/workflows/scripts/test-public-workflow-policy.sh | Adds tests for bootstrap behavior, governance verifier fixtures, and fail-closed policy mutation coverage. |
| .github/workflows/release.yml | Pins actions by SHA, removes private token rewrites, uses github.token, and adds main-ancestry requirement for tags. |
| .github/workflows/public-workflow-policy.yml | Adds pull_request_target + push-to-main workflow to scan candidate workflows using a trusted base policy. |
| .github/workflows/policytool/main.go | Introduces the Go-based workflow policy analyzer. |
| .github/workflows/policytool/main_test.go | Adds unit tests covering shell/YAML parsing and allowlist/trust semantics. |
| .github/workflows/policytool/go.mod | Adds standalone module definition for the policy tool. |
| .github/workflows/policytool/go.sum | Adds pinned dependency sums for the policy tool. |
| .github/workflows/integration.yml | Removes the manual live integration workflow that required DigitalOcean credentials. |
| .github/workflows/iac-host-conformance.yml | Removes private Git credential rewriting and enforces bash defaults + github.token only. |
| .github/workflows/grpc-version-sync.yml | Removes private Git credential rewriting and enforces bash defaults + github.token only. |
| .github/workflows/conformance-smoke.yml | Removes live conformance smoke workflow (including self-hosted runner usage). |
| .github/workflows/conformance-leak-scrubber.yml | Removes scheduled live scrubber workflow. |
| .github/workflows/conformance-budget-check.yml | Removes reusable live budget gate workflow. |
| .github/workflows/ci.yml | Consolidates credential-free conformance/policy checks into main CI; pins actions by SHA; removes GOPRIVATE/token rewrite behavior. |
| .github/public-workflow-secret-allowlist.json | Adds empty secret allowlist (no named secrets allowed). |
| .github/public-workflow-presence-allowlist.json | Adds workflow presence/context digest allowlist for tracked public workflows. |
| .github/public-workflow-executable-allowlist.json | Adds executable allowlist (hash-pinned scripts allowed to run). |
| .github/public-workflow-command-allowlist.json | Adds command allowlist (exact statement digests permitted per workflow/context). |
| .github/public-workflow-action-allowlist.json | Adds action allowlist (exact action pins permitted per workflow/context). |
| .github/conformance/cleanup.yaml | Removes live provider-local conformance cleanup fixture. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Avoid privileged PR-head checkout and cache exposure by exporting an exact credential-free Git commit as inert archive data. Fail closed on identity, attribute-hiding, symlink, and ambient credential paths while preserving the exact post-merge bootstrap.
Derive the trusted policy root from the canonical wrapper location so the one-time bootstrap can scan an inert archive without repository metadata. Reject symlinked entry paths and invalid layouts before loading policy assets.
Resolve explicit relative workflow paths against the selected scan root so policy checks cannot read from the policytool working directory. Preserve lexical and symlink escape rejection.
intel352
marked this pull request as ready for review
July 12, 2026 01:12
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
github.tokenremains.v*tags and a remote-mainancestry check. Registry synchronization remains registry-owned through its existing daily/manual sync.Why
The framework/provider boundary was corrected in the wrong direction: live DigitalOcean automation was moved from Workflow core into another public repository, where it still represented public cloud authority and attempted to use self-hosted runners. Public CI should prove plugin behavior with fakes and the real external loader, not receive cloud credentials or mutate provider resources.
Bootstrap note
The default branch has no existing workflow-policy assets. This PR atomically installs the final active trust state from exact predecessor
0d368a29ba572e050c62cba90ae56908abbd4156; after merge, all workflow-authority changes use the documented three-PR staged lifecycle. The required policy status check is bound immediately after this one-time bootstrap merge.Validation
./.github/workflows/scripts/test-public-workflow-policy.sh./.github/workflows/scripts/check-public-workflow-policy.shactionlint .github/workflows/*.ymlshellcheck .github/workflows/scripts/*.sh scripts/*.shbash -n .github/workflows/scripts/*.sh scripts/*.shgo test -race,go vet, and buildGOWORK=off go test -race ./...GOWORK=off go vet ./...wfctl v0.85.4strict validation and typed-IaC conformance (status=pass)No package version or release is created by this CI-only correction.