Add sink-visibility to write-sink guard policy to prevent GitLost exfiltration#8895
Merged
Conversation
…iltration Implement the sink-visibility field on the write-sink guard policy that declares the visibility of the safe-outputs target repository. When set to "public", the WriteSinkGuard sets resource secrecy to EMPTY — blocking any agent with non-empty secrecy from writing. This prevents the GitLost vulnerability class where prompt injection causes an agent to read private repo data and exfiltrate it to a public comment. Changes: - WriteSinkPolicy struct: add SinkVisibility field (public/private/internal) - WriteSinkGuard: add NewWriteSinkGuardWithVisibility constructor - WriteSinkGuard.LabelResource: when sink-visibility=public, resource secrecy is empty (blocks tainted agents); otherwise uses accept patterns - Validation: validate sink-visibility values (public/private/internal) - guard_init.go: pass SinkVisibility when constructing WriteSinkGuard - Documentation: CONFIGURATION.md, config.example.toml updated with sink-visibility usage, security rationale, and compiler requirements - Tests: comprehensive sink-visibility tests for guard behavior and validation The gh-aw compiler MUST check the safe-outputs target repository visibility and set sink-visibility accordingly to prevent data exfiltration. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR hardens the DIFC write-sink guard against the “GitLost” exfiltration pattern by introducing a sink-visibility policy field, allowing public sinks to be treated as having empty resource secrecy so tainted (non-empty secrecy) agents are blocked from writing.
Changes:
- Add
sink-visibilityto write-sink guard policy config and validate allowed values (public|private|internal, case-insensitive). - Extend the WriteSinkGuard with visibility-aware behavior;
publicleaves resource secrecy empty to block tainted agents. - Add test coverage for public/private/internal/unset modes and update user-facing configuration documentation/examples.
Show a summary per file
| File | Description |
|---|---|
| internal/server/guard_init.go | Passes configured SinkVisibility into the write-sink guard constructor and improves DIFC logging context. |
| internal/guard/write_sink.go | Adds visibility-aware constructor + logic to enforce “public sink blocks tainted agents” via empty resource secrecy. |
| internal/guard/write_sink_test.go | Adds sink-visibility-focused tests covering the core security property and backward compatibility. |
| internal/config/guard_policy.go | Extends WriteSinkPolicy with SinkVisibility and documents semantics/requirements. |
| internal/config/guard_policy_validation.go | Validates sink-visibility values (case-insensitive) when provided. |
| internal/config/config_guardpolicies_test.go | Adds validation tests for sink-visibility accepted/rejected values. |
| docs/CONFIGURATION.md | Documents sink-visibility, rationale, and examples for public/private targets. |
| config.example.toml | Updates example configuration guidance to include sink-visibility usage. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 8/8 changed files
- Comments generated: 1
- Review effort level: Low
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
lpcox
added a commit
that referenced
this pull request
Jul 8, 2026
## Summary Adds runtime repo visibility verification as defense-in-depth for the sink-visibility feature (#8895), plus comprehensive integration tests. ## Runtime Verification At gateway startup, when a write-sink guard has `sink-visibility` configured, the gateway now verifies the actual repo visibility via `GET /repos/{owner}/{repo}`: - If the API reports the repo is **public** but config says private/internal → **overrides to "public"** with warning: ``` SINK VISIBILITY OVERRIDE: configured="private" but runtime check shows repo test-owner/test-repo is "public" — overriding to "public" to prevent potential data exfiltration ``` - Catches repos made public **after** workflow compilation (stale config) - Gracefully skipped when `GITHUB_REPOSITORY` or GitHub token unavailable - Falls back to configured value on API errors (non-fatal) - Never relaxes: if configured as "public" but repo is actually private, keeps "public" ## Integration Tests 7 test groups with 20+ subtests covering: | Test | What it verifies | |------|-----------------| | `ConfigAccepted` | Gateway starts with valid sink-visibility values (public, private, internal, omitted, case-insensitive) | | `InvalidValue` | Invalid values cause noop guard fallback | | `RuntimeOverride` | Override warning emitted when repo is more public than configured | | `RuntimeCheckSkippedWithoutRepo` | Graceful skip when GITHUB_REPOSITORY unset | | `RuntimeCheckSkippedWithoutToken` | Graceful skip when no token available | | `RuntimeCheckAPIFailure` | Graceful fallback on API 500 errors | | `WriteSinkGuardLogsSinkVisibility` | Effective visibility logged at startup | ## Files - `internal/githubhttp/visibility.go` — `FetchRepoVisibility` and `VerifySinkVisibility` functions - `internal/githubhttp/visibility_test.go` — Unit tests for the visibility API client - `internal/server/guard_init.go` — `verifySinkVisibilityAtRuntime` method wired into guard creation - `test/integration/sink_visibility_test.go` — Integration tests using mock HTTP backends + mock GitHub API - `docs/CONFIGURATION.md` — Added "Runtime Verification" documentation section ## Related - #8895 — Initial sink-visibility implementation - github/gh-aw#44153 — Compiler issue to emit sink-visibility at compile time
This was referenced Jul 8, 2026
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.
Summary
Implements the
sink-visibilityfield on the write-sink guard policy to prevent the GitLost vulnerability class — data exfiltration from private repos to public outputs via prompt injection.The Attack
The Fix
A new
sink-visibilityfield on write-sink guard policy:When
sink-visibilityis"public", the WriteSinkGuard sets resource secrecy to empty — the DIFC evaluator's write check (agentSecrecy ⊆ resourceSecrecy) then fails for any agent with non-empty secrecy, blocking the exfiltration.sink-visibility"public"[](empty)"private"acceptpatterns"internal"acceptpatternsaccept(incl."*")Changes
internal/config/guard_policy.go— AddSinkVisibilityfield toWriteSinkPolicystruct with full documentationinternal/config/guard_policy_validation.go— Validatesink-visibilityvalues (public/private/internal); case-insensitiveinternal/guard/write_sink.go—NewWriteSinkGuardWithVisibilityconstructor;LabelResourcereturns empty secrecy for public sinksinternal/server/guard_init.go— PassSinkVisibilitywhen constructing WriteSinkGuarddocs/CONFIGURATION.md— Full documentation of sink-visibility with examples and security rationaleconfig.example.toml— Updated examples showing sink-visibility usageCompiler Requirement
The gh-aw compiler MUST check the safe-outputs target repository visibility and set
sink-visibilityaccordingly. Without this, agents tricked into reading private data can exfiltrate it to public repos. The documentation makes this requirement explicit in multiple places.