ci(security): phase-1 CI hardening — affected-area tests, least privilege, action pinning, dependency governance (#336)
* ci(security): run deterministic eval tests in affected-area CI (Task 04) The build-check job validated build + suite structure but never ran the tests, and its summary referenced a `test:ci` script that did not exist. Make affected-area CI meaningful: - Add `test:ci` to evals/framework running the offline, deterministic Vitest allowlist (7 files / 112 tests) — no model, network, or paid execution. - Add a required "Run deterministic tests" step to build-check; a failure fails the job and the existing PR summary gate (which keys on build-check.result) fails closed. - Correct the summary note to state test:ci runs the deterministic allowlist and that model/network agent suites are excluded on PRs. The broader deterministic suite has 3 pre-existing failing files (framework-confidence, logger, test-runner; confirmed failing before this work) which are intentionally out of the allowlist and tracked separately. Validated locally: build, validate:suites:all, and test:ci all exit 0. * ci(security): least privilege permissions + pin actions to SHAs (Task 05) Harden all 9 GitHub Actions workflows: Least privilege: - Add explicit top-level `permissions: contents: read` to installer-checks, validate-test-suites, and opencode (opencode's job keeps the writes it needs; the top level now defaults to read). - Every workflow now declares an explicit top-level permissions block. - Write scopes retained only where justified (releases, doc/registry commits, follow-up PRs, and sync-docs' issues.create). Immutable action pinning: - Pin every `uses:` to a full 40-char commit SHA with a version comment, including first-party actions/* (checkout, github-script, setup-node, upload-artifact) and third-party (oven-sh/setup-bun). - Replace the two mutable refs that could change under us at any push: ludeeus/action-shellcheck@master and sst/opencode/github@latest. Record all SHAs, versions, and permission justifications in docs/maintenance/repository-recovery/action-pin-inventory.md. Verified: all 9 workflows parse as valid YAML; no floating tag/branch refs remain; every workflow has a top-level permissions block. * docs(security): add SECURITY.md and private-reporting checklist (Task 06) - Add root SECURITY.md: supported versions (0.7.x), private reporting via GitHub's "Report a vulnerability", best-effort response expectations, coordinated disclosure, and no-secret guidance. - Add private-vulnerability-reporting checklist that separates repository file work (this PR) from GitHub settings changes that require their own approval (Task 07: enabling private vulnerability reporting). No external links to validate; the reporting path uses the repo Security tab. SECURITY.md documents the private reporting path ahead of Task 07 enabling it. * ci(security): add dependency governance and ownership controls (Task 08) - .github/dependabot.yml: weekly grouped github-actions updates (keeps the Task 05 SHA pins current). Scoped to actions only — the primary lockfile is bun.lock and Dependabot's npm ecosystem would desync it; npm dependency risk is covered by dependency-review below. - .github/workflows/dependency-review.yml: runs on PRs with contents: read, SHA-pinned actions, fail-on-severity: high to block newly introduced high-severity vulnerabilities (exceptions documented inline). - .github/CODEOWNERS: default owner @darrenhinde with explicit ownership of security-sensitive paths (workflows, dependabot, CODEOWNERS, SECURITY.md, scripts/validation). Verified: dependabot.yml and dependency-review.yml are valid YAML; dependency-review actions are SHA-pinned with contents: read; CODEOWNERS owner is the repository owner. * docs(security): record GitHub security settings evidence (Task 07) Enable private vulnerability reporting and record read-back evidence. Settings changed (each approved immediately before, verified by read-back): - Private vulnerability reporting: enabled=false -> enabled=true. The Security tab now offers "Report a vulnerability", making the path documented in SECURITY.md live. - Dependency Graph / Dependabot alerts: 404 -> 204. This was an undocumented prerequisite of Task 08's dependency-review.yml, which failed with "Dependency graph is not enabled"; the Dependency Review check on PR #336 went fail -> pass after enabling it. No other repository setting was modified; secret scanning and push protection are unchanged, and dependabot_security_updates remains disabled (out of scope, would need its own approval). Both changes are reversible via the corresponding DELETE calls. Marks Part B of the private-vulnerability-reporting checklist complete.
This commit is contained in:
parent
926d68de93
commit
699b2d7769
17 changed files with 331 additions and 35 deletions
19
.github/CODEOWNERS
vendored
Normal file
19
.github/CODEOWNERS
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Code owners for OpenAgentsControl
|
||||
#
|
||||
# Owners are automatically requested for review on PRs that touch matching
|
||||
# paths. Security-sensitive paths are listed explicitly so they always require
|
||||
# a maintainer review.
|
||||
|
||||
# Default owner for everything in the repo.
|
||||
* @darrenhinde
|
||||
|
||||
# CI/CD workflows — untrusted-input execution surface.
|
||||
/.github/workflows/ @darrenhinde
|
||||
/.github/dependabot.yml @darrenhinde
|
||||
/.github/CODEOWNERS @darrenhinde
|
||||
|
||||
# Security policy and reporting.
|
||||
/SECURITY.md @darrenhinde
|
||||
|
||||
# PR validation and detection scripts consumed by CI.
|
||||
/scripts/validation/ @darrenhinde
|
||||
19
.github/dependabot.yml
vendored
Normal file
19
.github/dependabot.yml
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
version: 2
|
||||
|
||||
updates:
|
||||
# GitHub Actions — keeps workflow action versions (and their SHA pins) current.
|
||||
# Scoped to actions only: the repo's primary lockfile is bun.lock, and
|
||||
# Dependabot's npm ecosystem would update package-lock.json without syncing
|
||||
# bun.lock, causing lockfile drift. Dependency (npm) vulnerabilities are
|
||||
# instead caught at PR time by dependency-review.yml.
|
||||
- package-ecosystem: github-actions
|
||||
directory: /
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 5
|
||||
groups:
|
||||
github-actions:
|
||||
patterns:
|
||||
- "*"
|
||||
commit-message:
|
||||
prefix: "ci"
|
||||
6
.github/workflows/create-release.yml
vendored
6
.github/workflows/create-release.yml
vendored
|
|
@ -27,13 +27,13 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Check if this was a version bump PR merge
|
||||
id: check
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
|
@ -83,7 +83,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
|
|||
26
.github/workflows/dependency-review.yml
vendored
Normal file
26
.github/workflows/dependency-review.yml
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
name: Dependency Review
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main, dev]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
dependency-review:
|
||||
name: Dependency Review
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Review dependencies
|
||||
uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4
|
||||
with:
|
||||
# Block PRs that introduce newly known high-severity (or worse)
|
||||
# vulnerabilities. Document any exception inline in the PR that adds
|
||||
# an allow-ghsas / allow-dependencies-licenses entry here.
|
||||
fail-on-severity: high
|
||||
17
.github/workflows/installer-checks.yml
vendored
17
.github/workflows/installer-checks.yml
vendored
|
|
@ -15,6 +15,9 @@ on:
|
|||
- 'update.sh'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
shellcheck:
|
||||
name: ShellCheck Analysis
|
||||
|
|
@ -22,10 +25,10 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
|
||||
- name: Run ShellCheck on install.sh
|
||||
uses: ludeeus/action-shellcheck@master
|
||||
uses: ludeeus/action-shellcheck@00b27aa7cb85167568cb48a3838b75f4265f2bca # master (resolved 2026-07-15)
|
||||
with:
|
||||
scandir: '.'
|
||||
additional_files: 'install.sh update.sh'
|
||||
|
|
@ -43,7 +46,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
|
||||
- name: Check install.sh syntax
|
||||
run: bash -n install.sh
|
||||
|
|
@ -73,7 +76,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
|
||||
- name: Install jq (Ubuntu)
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
|
|
@ -102,7 +105,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
|
||||
- name: Install jq (Ubuntu)
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
|
|
@ -133,7 +136,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
|
||||
- name: Install jq (Ubuntu)
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
|
|
@ -162,7 +165,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get install -y jq curl
|
||||
|
|
|
|||
7
.github/workflows/opencode.yml
vendored
7
.github/workflows/opencode.yml
vendored
|
|
@ -4,6 +4,9 @@ on:
|
|||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
opencode:
|
||||
if: |
|
||||
|
|
@ -19,12 +22,12 @@ jobs:
|
|||
issues: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Run opencode
|
||||
uses: sst/opencode/github@latest
|
||||
uses: sst/opencode/github@77fc88c8ade8e5a620ebbe1197f3a572d29ae91a # latest (resolved 2026-07-15)
|
||||
env:
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
with:
|
||||
|
|
|
|||
8
.github/workflows/post-merge-pr.yml
vendored
8
.github/workflows/post-merge-pr.yml
vendored
|
|
@ -25,13 +25,13 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Check if this was a version bump PR
|
||||
id: check_pr_labels
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
|
||||
with:
|
||||
script: |
|
||||
// Get the commit that triggered this workflow
|
||||
|
|
@ -106,12 +106,12 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
|
|
|
|||
17
.github/workflows/pr-checks.yml
vendored
17
.github/workflows/pr-checks.yml
vendored
|
|
@ -18,7 +18,7 @@ jobs:
|
|||
steps:
|
||||
- name: Check PR title format
|
||||
id: validate
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
|
||||
with:
|
||||
script: |
|
||||
const prTitle = context.payload.pull_request.title;
|
||||
|
|
@ -163,7 +163,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
|
@ -192,12 +192,12 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
|
@ -215,6 +215,10 @@ jobs:
|
|||
working-directory: evals/framework
|
||||
run: npm run validate:suites:all
|
||||
|
||||
- name: Run deterministic tests
|
||||
working-directory: evals/framework
|
||||
run: npm run test:ci
|
||||
|
||||
- name: Summary
|
||||
if: success()
|
||||
run: |
|
||||
|
|
@ -222,9 +226,10 @@ jobs:
|
|||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- ✅ TypeScript compilation successful" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- ✅ Test suite validation passed" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- ✅ Deterministic tests passed (\`npm run test:ci\`)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Note:** Full agent tests are not run on PRs to save time and costs." >> $GITHUB_STEP_SUMMARY
|
||||
echo "Maintainers can run \`npm run test:ci\` locally if needed." >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Note:** \`test:ci\` runs the offline, deterministic Vitest allowlist only." >> $GITHUB_STEP_SUMMARY
|
||||
echo "Model- or network-dependent agent tests (\`eval:sdk\`, integration suites) are not run on PRs." >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Failure summary
|
||||
if: failure()
|
||||
|
|
|
|||
10
.github/workflows/sync-docs.yml
vendored
10
.github/workflows/sync-docs.yml
vendored
|
|
@ -32,7 +32,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ jobs:
|
|||
|
||||
- name: Create sync issue for OpenCode
|
||||
id: create_issue
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
|
||||
with:
|
||||
script: |
|
||||
const issue = await github.rest.issues.create({
|
||||
|
|
@ -195,7 +195,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
|
||||
- name: Delete branch if created
|
||||
run: |
|
||||
|
|
@ -207,7 +207,7 @@ jobs:
|
|||
|
||||
- name: Comment on issue
|
||||
if: needs.sync-documentation.outputs.issue_number
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
|
||||
with:
|
||||
script: |
|
||||
await github.rest.issues.createComment({
|
||||
|
|
|
|||
2
.github/workflows/update-registry.yml
vendored
2
.github/workflows/update-registry.yml
vendored
|
|
@ -18,7 +18,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
|
|||
4
.github/workflows/validate-registry.yml
vendored
4
.github/workflows/validate-registry.yml
vendored
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code without persisted credentials
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
|
@ -32,7 +32,7 @@ jobs:
|
|||
sudo apt-get install -y jq
|
||||
|
||||
- name: Install Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
|
||||
with:
|
||||
bun-version: latest
|
||||
|
||||
|
|
|
|||
11
.github/workflows/validate-test-suites.yml
vendored
11
.github/workflows/validate-test-suites.yml
vendored
|
|
@ -15,6 +15,9 @@ on:
|
|||
- '.github/workflows/validate-test-suites.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
name: Validate Test Suite Definitions
|
||||
|
|
@ -22,10 +25,10 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
|
@ -42,7 +45,7 @@ jobs:
|
|||
|
||||
- name: Comment on PR (if validation failed)
|
||||
if: failure() && github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.createComment({
|
||||
|
|
@ -54,7 +57,7 @@ jobs:
|
|||
|
||||
- name: Upload validation report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: suite-validation-report
|
||||
path: |
|
||||
|
|
|
|||
58
SECURITY.md
Normal file
58
SECURITY.md
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Security fixes are provided for the latest released minor version. Older
|
||||
versions are not maintained; please upgrade before reporting.
|
||||
|
||||
| Version | Supported |
|
||||
|---------|-----------|
|
||||
| 0.7.x | ✅ |
|
||||
| < 0.7 | ❌ |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
**Please do not report security vulnerabilities through public GitHub issues,
|
||||
pull requests, or discussions.**
|
||||
|
||||
Report vulnerabilities privately through GitHub's built-in private vulnerability
|
||||
reporting:
|
||||
|
||||
1. Go to the repository's **Security** tab.
|
||||
2. Select **Report a vulnerability**.
|
||||
3. Provide a clear description, affected versions, reproduction steps, and
|
||||
potential impact.
|
||||
|
||||
This opens a private advisory visible only to the maintainers and to you.
|
||||
|
||||
### What to include
|
||||
|
||||
- The affected component and version.
|
||||
- Steps to reproduce, or a proof of concept.
|
||||
- The impact you believe the issue has.
|
||||
|
||||
### What not to include
|
||||
|
||||
- **Do not include real secrets, credentials, API keys, or access tokens** in
|
||||
your report. If a secret has been exposed, say so and rotate it — do not paste
|
||||
its value.
|
||||
|
||||
## Response Expectations
|
||||
|
||||
This project is maintained on a **best-effort basis**. Reports are reviewed and
|
||||
addressed as maintainer availability allows; there is no guaranteed response
|
||||
time. We will engage with the private advisory as we triage and work on a fix.
|
||||
|
||||
## Coordinated Disclosure
|
||||
|
||||
We follow coordinated disclosure. Please give the maintainers a reasonable
|
||||
opportunity to investigate and release a fix before disclosing the issue
|
||||
publicly. We will coordinate the timing and content of any public disclosure
|
||||
with you through the private advisory.
|
||||
|
||||
## Scope
|
||||
|
||||
This policy covers the code in this repository. Vulnerabilities in third-party
|
||||
dependencies should be reported to the respective upstream projects; if a
|
||||
dependency issue affects this project specifically, you may still report it here
|
||||
so we can track remediation.
|
||||
53
docs/maintenance/repository-recovery/action-pin-inventory.md
Normal file
53
docs/maintenance/repository-recovery/action-pin-inventory.md
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# GitHub Actions Pin & Permissions Inventory
|
||||
|
||||
_Repository-recovery Task 05 — least privilege + immutable action pinning._
|
||||
_Resolved: 2026-07-15._
|
||||
|
||||
## Third-party / external action pins
|
||||
|
||||
Every `uses:` reference is pinned to a full 40-character commit SHA, with the
|
||||
human-readable version retained as a trailing comment. SHAs were resolved via
|
||||
`gh api repos/<owner>/<repo>/commits/<ref>` on the date above.
|
||||
|
||||
| Action | Previous ref | Pinned SHA | Note |
|
||||
|--------|--------------|------------|------|
|
||||
| `actions/checkout` | `@v4` (19 uses) | `34e114876b0b11c390a56381ad16ebd13914f8d5` | GitHub-owned |
|
||||
| `actions/github-script` | `@v7` (6 uses) | `f28e40c7f34bde8b3046d885e986cb6290c5673b` | GitHub-owned |
|
||||
| `actions/setup-node` | `@v4` (3 uses) | `49933ea5288caeca8642d1e84afbd3f7d6820020` | GitHub-owned |
|
||||
| `actions/upload-artifact` | `@v4` (1 use) | `ea165f8d65b6e75b540449e92b4886f43607fa02` | GitHub-owned |
|
||||
| `oven-sh/setup-bun` | `@v2` (1 use) | `0c5077e51419868618aeaa5fe8019c62421857d6` | Matches the SHA already pinned by the other usage |
|
||||
| `ludeeus/action-shellcheck` | `@master` (1 use) | `00b27aa7cb85167568cb48a3838b75f4265f2bca` | **Was a mutable branch ref** — highest risk before pinning |
|
||||
| `sst/opencode/github` | `@latest` (1 use) | `77fc88c8ade8e5a620ebbe1197f3a572d29ae91a` | **Was a mutable ref** — freezes the OpenCode agent version; update deliberately |
|
||||
|
||||
### Update guidance
|
||||
|
||||
To bump a pinned action later: re-resolve the desired tag to its SHA
|
||||
(`gh api repos/<owner>/<repo>/commits/<tag> --jq .sha`), replace the SHA, and
|
||||
update the trailing version comment in the same edit. Never revert a pin back to
|
||||
a floating tag or branch.
|
||||
|
||||
## Workflow permissions (least privilege)
|
||||
|
||||
Every workflow now declares an explicit top-level `permissions:` block. Default
|
||||
is `contents: read`; write scopes remain only where a job demonstrably needs them.
|
||||
|
||||
| Workflow | Top-level | Job-level writes | Justification |
|
||||
|----------|-----------|------------------|---------------|
|
||||
| `pr-checks.yml` | `contents: read` | — | read-only validation |
|
||||
| `validate-registry.yml` | `contents: read` | — | read-only validation |
|
||||
| `installer-checks.yml` | `contents: read` **(added)** | — | shellcheck / installer tests, read-only |
|
||||
| `validate-test-suites.yml` | `contents: read` **(added)** | — | suite validation, read-only |
|
||||
| `opencode.yml` | `contents: read` **(added)** | `id-token`, `contents`, `pull-requests`, `issues: write` (job) | `/oc` agent, gated to OWNER/MEMBER; job needs write to act on PRs/issues |
|
||||
| `create-release.yml` | `contents: write` | — | creates tags/releases |
|
||||
| `post-merge-pr.yml` | `contents: write`, `pull-requests: write` | — | opens follow-up PRs |
|
||||
| `sync-docs.yml` | `contents: write`, `pull-requests: write`, `issues: write` | — | commits doc branch, opens PR, creates a sync issue (`issues.create`) |
|
||||
| `update-registry.yml` | `contents: write` | — | commits registry updates |
|
||||
|
||||
`issues: write` in `sync-docs.yml` is retained because the workflow calls
|
||||
`github.rest.issues.create` to open a sync-tracking issue.
|
||||
|
||||
## Verification
|
||||
|
||||
- All 9 workflow files parse as valid YAML.
|
||||
- No `uses:` reference remains on a floating tag or branch — all are 40-char SHAs.
|
||||
- Every workflow has an explicit top-level `permissions:` block.
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
# Private Vulnerability Reporting — Setup Checklist
|
||||
|
||||
_Repository-recovery Tasks 06–07. This checklist separates repository-file work
|
||||
(committable in a PR) from GitHub repository-settings work (changes live GitHub
|
||||
state and requires its own explicit approval)._
|
||||
|
||||
## Part A — Repository files (Task 06, this PR)
|
||||
|
||||
- [x] Publish `SECURITY.md` at the repository root with:
|
||||
- [x] Supported versions.
|
||||
- [x] Private reporting path (GitHub "Report a vulnerability").
|
||||
- [x] Response expectations (best-effort).
|
||||
- [x] Coordinated disclosure policy.
|
||||
- [x] No-secret guidance.
|
||||
- [x] Publish this checklist.
|
||||
|
||||
These are file changes only. They do **not** enable the private reporting
|
||||
feature — they document how to use it once enabled.
|
||||
|
||||
## Part B — GitHub repository settings (Task 07, separate approval)
|
||||
|
||||
> ⚠️ The following change live GitHub state, not files. Each requires explicit
|
||||
> approval immediately before it is made, and is verified by read-back.
|
||||
|
||||
- [x] Enable **Private vulnerability reporting** _(done 2026-07-15)_
|
||||
- Settings → Code security and analysis → Private vulnerability reporting → Enable.
|
||||
- API: `PUT /repos/{owner}/{repo}/private-vulnerability-reporting`.
|
||||
- Read-back: `GET /repos/{owner}/{repo}/private-vulnerability-reporting` shows `enabled: true`. ✅
|
||||
- [x] Confirm the **Security** tab now offers "Report a vulnerability" so the
|
||||
path documented in `SECURITY.md` is live. ✅
|
||||
- [x] Record evidence in
|
||||
`docs/maintenance/repository-recovery/private-vulnerability-reporting-evidence.md`. ✅
|
||||
- [x] **Dependency Graph** enabled (prerequisite discovered in Task 08 —
|
||||
`dependency-review.yml` requires it). `PUT /repos/{owner}/{repo}/vulnerability-alerts`,
|
||||
read-back `HTTP 204`. ✅
|
||||
|
||||
## Notes
|
||||
|
||||
- `SECURITY.md` references the private reporting path before Part B is applied.
|
||||
There is a brief window where the documented path is not yet live; Part B
|
||||
should follow promptly.
|
||||
- No other repository setting is changed as part of Part B — only private
|
||||
vulnerability reporting.
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
# GitHub Security Settings — Change Evidence
|
||||
|
||||
_Repository-recovery Task 07 (private vulnerability reporting), plus the
|
||||
Dependency Graph prerequisite discovered during Task 08._
|
||||
_Repository: `darrenhinde/OpenAgentsControl` (public). Date: 2026-07-15._
|
||||
|
||||
Each change below was explicitly approved immediately before it was made, and
|
||||
verified by read-back. No other repository setting was modified.
|
||||
|
||||
## Change 1 — Dependency Graph / Dependabot alerts (Task 08 prerequisite)
|
||||
|
||||
Discovered while adding `dependency-review.yml`: the Dependency Review action
|
||||
fails with _"Dependency review is not supported on this repository. Please ensure
|
||||
that Dependency graph is enabled"_ unless the Dependency Graph is on.
|
||||
|
||||
| Step | Command | Result |
|
||||
|------|---------|--------|
|
||||
| Before | `GET /repos/darrenhinde/OpenAgentsControl/vulnerability-alerts` | `HTTP 404` (disabled) |
|
||||
| Enable | `PUT /repos/darrenhinde/OpenAgentsControl/vulnerability-alerts` | `HTTP 204` |
|
||||
| Read-back | `GET /repos/darrenhinde/OpenAgentsControl/vulnerability-alerts` | `HTTP 204` (enabled) |
|
||||
|
||||
**Verification:** the `Dependency Review` check on PR #336 went from `fail` (4s,
|
||||
"Dependency graph is not enabled") to `pass` (9s) after this change.
|
||||
|
||||
## Change 2 — Private vulnerability reporting (Task 07)
|
||||
|
||||
Makes the reporting path documented in `SECURITY.md` live.
|
||||
|
||||
| Step | Command | Result |
|
||||
|------|---------|--------|
|
||||
| Before | `GET /repos/darrenhinde/OpenAgentsControl/private-vulnerability-reporting` | `{"enabled": false}` |
|
||||
| Enable | `PUT /repos/darrenhinde/OpenAgentsControl/private-vulnerability-reporting` | `HTTP 204` |
|
||||
| Read-back | `GET /repos/darrenhinde/OpenAgentsControl/private-vulnerability-reporting` | `{"enabled": true}` |
|
||||
|
||||
**Verification:** the repository Security tab now offers **Report a
|
||||
vulnerability**, so the path documented in `SECURITY.md` resolves.
|
||||
|
||||
## Settings not changed
|
||||
|
||||
Confirmed unchanged before and after (`GET /repos/{owner}/{repo}` →
|
||||
`security_and_analysis`):
|
||||
|
||||
```json
|
||||
{
|
||||
"dependabot_security_updates": { "status": "disabled" },
|
||||
"secret_scanning": { "status": "enabled" },
|
||||
"secret_scanning_non_provider_patterns": { "status": "disabled" },
|
||||
"secret_scanning_push_protection": { "status": "enabled" },
|
||||
"secret_scanning_validity_checks": { "status": "disabled" }
|
||||
}
|
||||
```
|
||||
|
||||
Note: `dependabot_security_updates` (automated fix PRs) remains **disabled** —
|
||||
it was not in scope for Task 07 and would require its own approval. Dependabot
|
||||
alerts are now on via the Dependency Graph change above; `.github/dependabot.yml`
|
||||
is scoped to `github-actions` updates only.
|
||||
|
||||
## Reversal
|
||||
|
||||
Both changes are reversible with the corresponding `DELETE` calls:
|
||||
|
||||
- `DELETE /repos/{owner}/{repo}/private-vulnerability-reporting`
|
||||
- `DELETE /repos/{owner}/{repo}/vulnerability-alerts`
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
"build:watch": "tsc --watch",
|
||||
"test": "vitest",
|
||||
"test:watch": "vitest --watch",
|
||||
"test:ci": "vitest run src/__tests__/error-handling.test.ts src/evaluators/__tests__/evaluator-reliability.test.ts src/evaluators/__tests__/context-loading-evaluator.test.ts src/evaluators/__tests__/tool-usage-enhanced.test.ts src/sdk/__tests__/yaml-loader.test.ts src/sdk/__tests__/suite-validator.test.ts src/sdk/__tests__/validate-suites-cli.test.ts",
|
||||
"test:integration": "vitest --config vitest.integration.config.ts",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"lint:fix": "eslint src/**/*.ts --fix",
|
||||
|
|
|
|||
Loading…
Reference in a new issue