Intentionally vulnerable testbed. Not for production use.
This repository is a controlled Go fixture for demonstrating REACHABLE code exploitability analysis and risk posture reduction in GitHub Actions.
For the public guide and provider map, see CI auto-remediation on sthenosec.com.
This repo is the GitHub Go/public-clone remediation proof demo. It is not the GitHub Marketplace action listing.
| Repo | Role |
|---|---|
REACHABLE Risk Exposure Reduction |
GitHub Marketplace action for customer installation, including optional copilot-github remediation. |
reachable GitLab Catalog component |
GitLab Catalog component for customer installation. |
reach-testbed-github-marketplace |
GitHub Marketplace distribution repo plus the configurable root action. |
reach-ci-github |
Reusable GitHub Actions toolkit for production remediation workflows. |
reach-testbed-github-go |
Public GitHub demo repo for full remediation proof and scan-only runs with remediation disabled. |
Copilot campaign proof lives in this demo repo, while customer installs should use the Marketplace action. Do not use this repo itself as the Marketplace listing; use it to prove scan, dispatch, PR verification, parity, and the no-auto-merge kill switch for the same behavior exposed to customer installs.
Contact Sthenos Security for custom CI/CD integration.
Do not deploy, fork as an application template, or reuse this code in a production service. The vulnerabilities are deliberate synthetic fixtures for scanner validation and controlled demos only.
The diagram above is the release-gate flow. GitHub exposes explicit demo workflows so the provider lane is obvious in the Actions UI:
- GitHub Actions → Run Demo (Codex)
- GitHub Actions → Run Demo (Claude)
- GitHub Actions → Run Demo (Copilot Dispatch)
- GitHub Actions → Run Demo (Copilot E2E)
- GitHub Actions → Run Demo (Copilot Alpha Candidate)
- GitHub Actions → Run Demo (Copilot Bundle Replay)
- GitHub Actions → Dispatch Copilot PR Verification
- GitHub Actions → Agent Parity Check
This repo is also the public scan-only sample surface. There is no separate
public legacy scan repo in the supported contract; use the same toolkit-backed
workflow here with remediate=false.
| Action shown in GitHub | Meaning | Run manually? |
|---|---|---|
Run Demo (Codex) |
Scan the vulnerable release candidate, create a fix branch, test it, rescan it, open or prepare a PR, and publish the verdict status page with the Codex/OpenAI lane. | Yes |
Run Demo (Claude) |
Run the same remediation demo with the Claude/Anthropic lane so GitHub clearly shows support for both providers. | Yes |
Run Demo (Copilot Dispatch) |
Scan the vulnerable release candidate and dispatch bounded GitHub Copilot cloud-agent issues/tasks from DB-backed evidence. This can create multiple Copilot PRs: one PR per REACHABLE shard. Copilot PRs require later REACHABLE verification before they are considered ready. | Yes |
Run Demo (Copilot E2E) |
Run the proof-gated Copilot demo from this Go repo and fail unless the published artifact contains at least one dispatched Copilot task with a GitHub issue/task identifier. | Yes |
Run Demo (Copilot Alpha Candidate) |
Install a non-published reach-core Test Release candidate dist directly and prove Copilot dispatch from this Go repo before any Marketplace rollout. Like the normal Copilot dispatch lane, this can create multiple PRs for one remediation campaign. | Yes |
Run Demo (Copilot Bundle Replay) |
Re-dispatch Copilot from a saved bundle and pre-dispatch DB artifact so prompt/task changes can be tested without another full Reachable scan. | Yes |
Dispatch Copilot PR Verification |
Trusted scheduled/manual workflow that finds open Copilot PRs and dispatches Verify Copilot PR from main, avoiding PR-event approval gates for bot-authored PRs. |
Yes |
Agent Parity Check |
Compare Codex, Claude, and Copilot proof artifacts by verified security outcome instead of diff text. | Yes |
Reset Demo |
Delete old reachable-remediate-* demo branches before a fresh run. |
Optional |
pages-build-deployment |
Publish Verdict Status Page. This is GitHub Pages plumbing created automatically after Run Demo publishes results. |
No |
Click Run workflow on either provider lane and leave the defaults selected.
The defaults run the full release-gate demo: scan main, create a remediation
branch, run the agent, run project tests, rescan after each bounded batch, stop
when the DB proof is clean, open a PR, and publish the verdict page.
| Control | Demo value | Release-manager meaning |
|---|---|---|
| Branch | main |
Start from the intentionally vulnerable release candidate. |
remediate |
true |
Let CI create a fix branch and apply a bounded patch. |
rescan_only |
false |
Run the full release-gate loop: scan baseline, patch branch, rescan proof, publish evidence. |
target_branch |
main |
The branch being evaluated as the release candidate. |
ai_mode |
workflow-specific | Run Demo (Codex) uses openai-codex with OPENAI_API_KEY. Run Demo (Claude) uses anthropic-claude with ANTHROPIC_API_KEY. Run Demo (Copilot Dispatch) uses copilot-github with REACHABLE_COPILOT_USER_TOKEN. |
prompt_profile |
balanced |
Keeps fixes scoped: enough context to repair the issue queue without turning the run into an open-ended refactor. |
signal_types |
all |
Covers all demo blocker classes: CVE, CWE, secret, DLP, and AI findings. |
max_batches |
1 |
Upper bound for serialized fix batches in this smoke-style public demo. The workflow stops after one bounded pass and proves the result from the database. |
rescan_strategy |
each_batch |
Rescan after each bounded patch batch so CI can stop once release blockers are gone. |
require_ai |
true |
Fail fast if the selected AI key is missing, instead of producing a confusing partial run. |
fresh_scan |
true |
Start from an empty Reachable cache for a clean public demo evidence run. |
create_pr |
true |
Open a remediation PR from the pushed reachable-remediate-* branch after the DB proof passes. Set false to use branch-only/manual PR mode. |
Expected result: the workflow creates a reachable-remediate-* branch, runs
the selected coding agent with instructions to run appropriate local Go
validation when available, rescans that branch, publishes the proof page, and
opens a pull request for review. The proof page displays the remediation branch
name, commit, scan IDs, and PR link when GitHub accepts automatic PR creation.
The repository's normal CI and any manual release harness checks remain the
enforcement point for language-specific tests such as go test ./....
Automatic PR creation is controlled by CI permissions, not by Reachable scanner
tokens. Branch push, artifact upload, Pages publishing, and SARIF upload use the
built-in GITHUB_TOKEN. If GitHub rejects automatic PR creation, the workflow
keeps the pushed remediation branch and publishes the manual PR URL/path instead
of hiding the auth failure in a green log. Branch protection and review policy
still decide whether anything can merge.
MCP_GITHUB_TOKEN is the optional read-only source token for higher-quality
GitHub package context. Create it as a fine-grained PAT at
https://github.com/settings/personal-access-tokens/new, choose the GitHub
Resource owner that owns the source repos Reachable may inspect, and grant
Repository permissions -> Contents: Read-only. GitHub adds Metadata:
Read-only automatically. Use Only select repositories for a fixed set, or
All repositories when the demo must read any current/future repo for that
owner; Public repositories is enough only for public source repos. The token
is used for MCP GitHub cloning and git clone fallback when MCP cannot fetch a
package directly. It is not used to push branches or open PRs.
Use this only if create_pr=false, or if GitHub blocks automatic PR creation
after the workflow publishes a clean proof page and pushes the
reachable-remediate-<run_id> branch.
- Open the repository Branches page.
- Find the latest
reachable-remediate-<run_id>branch from the successfulRun Demolog or verdict page. - Click New pull request for that branch.
- Confirm
base: mainandcompare: reachable-remediate-<run_id>. - Create the PR and review the code diff together with the DB-backed proof page.
The manual PR is only a review wrapper around the already-published evidence: the workflow has already pushed the remediation branch, run the project test gate, rescanned the branch, and published the proof artifacts.
Use this when you want to show detection and reporting without allowing CI to write a fix branch.
| Control | Demo value | Release-manager meaning |
|---|---|---|
| Branch | main |
Scan the intentionally vulnerable release candidate. |
remediate |
false |
Do not invoke the coding agent or change code. |
rescan_only |
false |
Run only the baseline scan and evidence publication. |
target_branch |
main |
Branch being evaluated. |
require_ai |
true |
Fail early if AI enrichment cannot run. |
fresh_scan |
true |
Start from an empty Reachable cache so the public demo run proves a clean install and scan path. |
Expected result: the workflow publishes baseline evidence and blocker counts, but no remediation branch or PR is created.
Use this after a remediation branch already exists and you only want proof that the branch is clean.
| Control | Demo value | Release-manager meaning |
|---|---|---|
| Branch | main |
The workflow definition still runs from main. |
remediate |
false |
Do not invoke the coding agent. |
rescan_only |
true |
Only scan and prove the selected branch. |
target_branch |
reachable-remediate-* |
Existing fix branch to verify. |
require_ai |
true |
Keep AI-backed reachability/enrichment enabled. |
Expected result: the workflow scans the selected branch, gates on zero release blockers, and publishes proof for that branch.
| Evidence | Release-manager meaning |
|---|---|
| Baseline scan | The release candidate contains the expected blocker queue. |
| Fix branch | CI produced a reachable-remediate-* branch instead of changing main directly. |
| Project tests | The patch still passes the application test command. |
| Proof scan | Reachable rescanned the fix branch from the database source of truth. |
| Pull request | The fix is ready for normal review and merge policy. |
| Public verdict status page | Sanitized evidence shows baseline findings, fixed findings, branch, commit, scan IDs, timestamps, runtime, AI cost, and artifact links. |
| Workflow | Purpose |
|---|---|
Run Demo (Codex) |
Main GitHub Codex demo workflow. |
Run Demo (Claude) |
Main GitHub Claude demo workflow. |
Run Demo (Copilot Dispatch) |
Async GitHub Copilot cloud-agent dispatch workflow. It scans and creates Copilot tasks; a later verification pass decides whether Copilot PRs are ready. |
Run Demo (Copilot E2E) |
Proof-gated Copilot dispatch workflow. It consumes the GitHub toolkit from this demo repo and verifies the artifact contains non-empty Copilot dispatch proof. |
Run Demo (Copilot Alpha Candidate) |
Proof-gated Copilot dispatch workflow against a two-wheel, non-published reach-core alpha candidate artifact. |
Dispatch Copilot PR Verification |
Finds open app/copilot-swe-agent PRs from trusted main context and dispatches Verify Copilot PR; skips already verified PRs from verification artifacts. |
Agent Parity Check |
Downloads Codex, Claude, and Copilot proof artifacts from supplied run IDs and fails unless all three lanes reach the same verified security outcome. |
Reset Demo |
Deletes old reachable-remediate-* branches when resetting the demo. Use dry_run=true first if you want to preview. |
pages-build-deployment |
Publish Verdict Status Page. This is GitHub Pages plumbing. Do not run it manually; it appears after Run Demo publishes results. |
The workflow code is .github/workflows/reachable-remediate.yml for Codex and .github/workflows/reachable-remediate-claude.yml for Claude. Copilot dispatch lives in .github/workflows/reachable-remediate-copilot.yml, the proof-gated toolkit-backed Copilot workflow is .github/workflows/reachable-remediate-copilot-e2e.yml, and the non-published alpha-candidate Copilot workflow is .github/workflows/reachable-copilot-alpha-candidate.yml. Trusted Copilot PR verification dispatch is handled by .github/workflows/reachable-copilot-verification-dispatcher.yml and DB-backed verification is recorded by .github/workflows/reachable-copilot-pr-verify.yml. Cross-agent parity comparison is tracked in docs/copilot-parity-test-plan.md and executed by .github/workflows/reachable-agent-parity.yml with ci/check-agent-parity.py. The first product-cut Copilot model is documented in docs/copilot-remediation-campaign.md: REACHABLE dispatches one bounded task per shard, Copilot opens one PR per task, REACHABLE verifies each PR, and parity is proven at the campaign level. Multiple Copilot PRs are therefore expected behavior, not a duplicate-dispatch bug, when a scan contains findings that REACHABLE separates by priority, dependency affinity, file affinity, or remediation risk. These helper scripts keep the release-gate logic auditable and testable outside GitHub Actions:
| Script | Used for | Release-gate purpose |
|---|---|---|
| ci/smoke-db-remediation-proof.py | Preflight smoke test | Verifies the DB proof/verdict helper can run before the expensive scan begins. |
| ci/reachable-cache-evidence.py | Cache telemetry | Records whether the Reachable cache was restored, reused, or created fresh. |
| ci/collect-reachable-report.sh | Artifact collection | Collects the latest Reachable scan outputs into .reachable/ci-artifacts. |
| ci/check-db-release-blockers.py | Baseline gate | Reads the scan database and checks that the vulnerable branch matches the expected release-blocker contract. |
| ci/write-remediation-ledger.py | Remediation audit | Writes a sanitized remediation ledger without publishing prompts, rules, transcripts, or raw databases. |
| ci/write-agent-audit-log.py | Agent parity audit | Writes sanitized Copilot PR and cross-agent parity audit artifacts with selected signals, changed files, test evidence, and post-fix blocker counts. |
| ci/run-agent.sh | Agent execution | Invokes the selected coding agent against the bounded remediation task. |
| ci/check-db-remediation-proof.py | Proof gate | Reads the proof scan database and fails unless release blockers are gone. |
| ci/sanitize-sarif-for-upload.py | Platform export hygiene | Sanitizes the SARIF compatibility export before upload; SARIF is not the source of truth. |
| ci/build-pages-summary.py | Public evidence page | Builds the sanitized Pages report from DB-backed evidence and workflow metadata. |
| ci/smoke-pages-summary.py | Page smoke test | Verifies the public summary/page artifacts have the expected structure. |
| Question | Answer |
|---|---|
| What is this repo? | A controlled vulnerable Go application used to demonstrate Reachable CI scanning, autonomous remediation, and DB-backed proof that a remediation branch is clean. |
| What do I configure? | Add one AI key as a repository secret: OPENAI_API_KEY for openai-codex / Codex (OpenAI), or ANTHROPIC_API_KEY for anthropic-claude / Claude Code (Anthropic). Add MCP_GITHUB_TOKEN when you want read-only GitHub source access, MCP GitHub cloning, and package git clone fallback. Optional workflow inputs are listed below. |
| How does the PR open? | The demo default is automatic PR creation with the workflow GITHUB_TOKEN. Set create_pr=false to publish proof and open the PR manually from the reachable-remediate-* branch. Branch protection and reviews still control merge. |
| How does Copilot remediation merge? | Copilot can open multiple PRs for one remediation campaign: one PR per REACHABLE shard. Maintainers merge verified Copilot PRs after Verify Copilot PR and Agent Parity Check pass. Auto-merge is not a default. Agent Parity Check has an auto_merge kill-switch input that defaults to false and currently refuses true; merge automation is an opt-in roadmap feature for customers that grant a trusted REACHABLE workflow or GitHub App merge permission. |
| Where is the CI pipeline? | .github/workflows/reachable-remediate.yml for Codex and .github/workflows/reachable-remediate-claude.yml for Claude. Both scan, optionally remediate, rescan, verify the DB proof, and publish sanitized evidence. |
| Where do I run it? | GitHub Actions → Run Demo (Codex) or Run Demo (Claude). |
| Where are the verdict and artifacts? | Public verdict status page and published artifacts. |
| What is the expected vulnerable contract? | EXPECTED.md and expected/baseline.json. |
The public demo page is the release-facing proof view for the last published successful proof:
https://sthenos-security.github.io/reach-testbed-github-go/
That page is built from Reachable scan evidence. It shows the branch, commit, scan ID, and CI run it came from. The GitHub Actions workflow list remains the authority for the latest run status. It shows:
| Evidence | What the viewer should understand |
|---|---|
| Vulnerable baseline | The known vulnerable main branch was scanned and matched the expected issue contract. |
| Remediation branch | CI created a reviewable remediation branch and applied the agent fixes there. |
| Proof scan | Reachable rescanned the remediated branch and compared the result to the expected contract. |
| Final verdict | The demo passes only when the proof database has zero release blockers. |
| Audit metadata | Branch, commit, scan number, timestamp, runtime, AI token count, and estimated AI cost are displayed for traceability. |
| Sanitized artifacts | Convenience exports are linked for review; private prompts, rules, agent transcripts, raw witnesses, and local databases are not published. |
The scan database is the source of truth for the demo verdict. SARIF may be generated for platform compatibility, but it is only an export report. It is not the authority for the pass/fail claim.
The workflow in .github/workflows/reachable-remediate.yml is the implementation. At a high level, each demo run follows this sequence:
- CI checks out the vulnerable baseline branch.
- Reachable installs or updates, records cache evidence, and scans the
baseline into
repo.db. - The baseline database is compared with expected/baseline.json. A mismatch fails the run because the testbed contract is no longer intact.
- Reachable synthesizes a bounded remediation request from the database.
- The selected coding agent edits a dedicated
reachable-remediate-*branch. - The project test command runs to catch ordinary build or behavior breaks.
- Reachable rescans the remediation branch into a new proof database.
- If the proof database still has release blockers, CI generates another
bounded batch from the updated database state, up to
max_batches. - The proof database is compared with the expected contract. The pass condition is zero remaining release blockers. Rescan-only verification uses the same database release-blocker gate; SARIF is never the pass/fail source.
- CI publishes a sanitized Pages report and support artifacts with the exact scan IDs, branch names, commits, timestamps, runtime, cache state, and AI cost telemetry.
This is branch-first by design. The tool fixes code on a remediation branch so a release manager can inspect the diff, verify the proof, and merge only after normal review.
The expected vulnerable contract is documented in EXPECTED.md and enforced by expected/baseline.json.
Current golden baseline:
| Result | Expected |
|---|---|
| Raw DB signals | 28 |
| Release blockers before remediation | 18 |
| DB evidence rows used in public proof | 21 |
| Families | CVE, CWE, secret, DLP, AI |
| Grouped expected findings | 17 grouped findings covering 28 raw DB signals. |
| Release blockers after remediation | 0 non-deferred blockers |
| Deferred demo case | GO-CWE-01 / CWE/78 at internal/handlers/cwe.go:12; kept in the scanner contract, skipped from autonomous-remediation proof until the agent prompt is tightened. |
| Residual post-fix findings | Only filtered NON_PROD or NOT_REACHABLE fixture markers may remain in the database. |
The testbed itself is the contract. Do not edit the vulnerable fixture or the expected manifest just to make a scan pass; scanner logic must conform to the golden behavior.
The Pages report links a small set of public artifacts. These are review aids, not private execution material.
| Artifact | Purpose |
|---|---|
| summary.json | Compact DB-backed run summary for the public page. |
| db-remediation-verdict.json | Machine-readable baseline/proof comparison and final verdict. |
| reachable.sarif | Compatibility export for GitHub Code Scanning; not the demo verdict source. |
| remediation-ledger.json | Sanitized remediation summary with rule IDs and outcomes, not prompt text. |
| compliance.json | DB-backed compliance evidence extract. |
| compliance-narrative.json | Evidence-cited narrative draft for review, not a legal attestation. |
| expected-results.html | Branded expected issue contract and baseline proof criteria. |
The workflow must not publish raw remediation bundles, prompt text, generated
rule packs, skills databases, fuzz or pentest prompts, agent transcripts, raw
witness payloads, or local repo.db files.
The demo supports two synchronous coding-agent lanes plus one async Copilot dispatch lane:
| Lane | Secret | Agent |
|---|---|---|
openai-codex |
OPENAI_API_KEY |
Codex (OpenAI) |
anthropic-claude |
ANTHROPIC_API_KEY |
Claude Code (Anthropic) |
copilot-github |
REACHABLE_COPILOT_USER_TOKEN |
GitHub Copilot cloud-agent dispatch; PR readiness still requires later REACHABLE verification |
The workflow inputs are the operational guardrails. They define whether the run only scans, creates a remediation branch, verifies an existing branch, or publishes fresh evidence.
| Input | Default | Purpose |
|---|---|---|
remediate |
true |
Main kill switch. When false, CI scans and publishes evidence without changing code. |
rescan_only |
false |
Verifies target_branch as an existing branch; does not invoke an agent or create edits. |
target_branch |
main |
Baseline branch for normal runs, or the branch to verify when rescan_only=true. |
ai_mode |
openai-codex |
Selects the agent lane and matching provider secret. |
prompt_profile |
balanced |
Controls how aggressively Reachable bundles remediation work. |
signal_types |
all |
Limits remediation to selected signal families, or leaves all families eligible. |
max_batches |
1 |
Bounds the public demo to one serialized remediation batch so the run stays short and auditable. |
rescan_strategy |
each_batch |
Runs proof scans after each batch so the workflow can stop as soon as the branch is clean. |
scan_extra_flags |
empty | Optional extra scan flags for advanced test runs. |
require_ai |
true |
Fails early unless the selected provider key is configured. |
fresh_scan |
true |
Starts from an empty ~/.reachable cache for a clean evidence run. |
create_pr |
true |
Opens a remediation pull request when code changes are successfully produced. |
| The public report should make the selected branch, commit, scan number, final | ||
| proof state, cache state, and artifact links obvious without requiring the | ||
| viewer to know these inputs. |
| Path | Purpose |
|---|---|
| cmd/server/ | HTTP entrypoint and route registration. |
| internal/handlers/ | Vulnerable, defended, and assessed signal cases. |
| internal/safety/ | Guard helpers used by defended cases. |
| config/ | Synthetic insecure configuration cases. |
| deploy/ | Synthetic IaC cases. |
| testdata/dlp/ | Synthetic DLP corpus. |
| expected/baseline.json | Machine-readable expected scanner contract. |
| ci/ | DB proof, page summary, and CI helper scripts. |
| docs/ | Public demo page assets and sanitized reports. |
| .github/workflows/ | Demo scan/remediation/proof publishing workflow and branch cleanup workflow. |
For this demo, “fixed” means:
- The vulnerable baseline database contained the expected issue.
- The remediation branch proof database no longer contains that production actionable issue.
- The proof gate reports zero remaining release blockers.
- The public report displays the branch, commit, scan ID, timestamp, and artifact links that produced the verdict.