diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..ad174a5 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,37 @@ +name: CodeQL + +# Consumes the SHA-pinned reusable CodeQL template published by +# BicameralAI/bicameral-integrations for the wider Bicameral ecosystem. +# Pin: b1b52b5d (integrations main HEAD, 2026-06-08). Bump deliberately. +# See docs/research-brief-557-ci-security-gates-2026-06-08.md (#557). + +on: + push: + branches: ["main"] + pull_request: + branches: ["main", "dev"] + paths-ignore: + - "**/*.md" + - "docs/**" + schedule: + - cron: "30 6 * * 1" + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + codeql: + # Write scopes are re-declared at the caller job so the top-level token + # stays read-only; the reusable's effective token is the intersection of + # this job's grant and the reusable's own job permissions. + permissions: + contents: read + security-events: write + actions: read + uses: BicameralAI/bicameral-integrations/.github/workflows/_reusable-codeql.yml@b1b52b5d1c37c8cfdd5f916a9558cbf019b66a6e + with: + languages: python diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000..cb2cc9a --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,24 @@ +name: Dependency Review + +# Consumes the SHA-pinned reusable dependency-review template from +# BicameralAI/bicameral-integrations. Pin: b1b52b5d (integrations main, 2026-06-08). +# Starts ADVISORY (never fails the build) because it requires the repo's +# Dependency Graph to be enabled; flip advisory:false + fail-on-severity once +# Dependency Graph is confirmed on. See docs/research-brief-557-ci-security-gates-2026-06-08.md (#557). + +on: + pull_request: + branches: ["main", "dev"] + +permissions: + contents: read + +jobs: + dependency-review: + permissions: + contents: read + pull-requests: write + uses: BicameralAI/bicameral-integrations/.github/workflows/_reusable-dependency-review.yml@b1b52b5d1c37c8cfdd5f916a9558cbf019b66a6e + with: + advisory: true + fail-on-severity: moderate diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 0000000..c8cf467 --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,24 @@ +name: OpenSSF Scorecard + +# Consumes the SHA-pinned reusable Scorecard template from +# BicameralAI/bicameral-integrations. Pin: b1b52b5d (integrations main, 2026-06-08). +# NOTE: the reusable runs publish_results=false (org OIDC-publish policy), so +# there is NO public scorecard.dev badge — results upload to GitHub code-scanning +# as SARIF. See docs/research-brief-557-ci-security-gates-2026-06-08.md (#557). + +on: + push: + branches: ["main"] + schedule: + - cron: "30 6 * * 1" + +permissions: + contents: read + +jobs: + scorecard: + permissions: + contents: read + security-events: write + actions: read + uses: BicameralAI/bicameral-integrations/.github/workflows/_reusable-scorecard.yml@b1b52b5d1c37c8cfdd5f916a9558cbf019b66a6e diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml new file mode 100644 index 0000000..2845686 --- /dev/null +++ b/.github/workflows/security-scan.yml @@ -0,0 +1,56 @@ +name: Security Scan + +# Bandit SAST (advisory until the first full-tree backlog is cleared) + pip-audit (advisory). Vendored rather than consumed: +# bicameral-integrations has no reusable for these, and the scan targets differ +# for mcp's flat package layout. Actions SHA-pinned per #544. +# See docs/research-brief-557-ci-security-gates-2026-06-08.md (#557). + +on: + pull_request: + branches: ["main", "dev"] + push: + branches: ["main"] + +permissions: + contents: read + +jobs: + bandit: + # ADVISORY for now: #562 closed the caller-controlled MCP query-safety P0, + # but the first full-tree Bandit pass still surfaces separate Medium/High + # findings in CLI/operator paths, code-locator storage, schema migration, + # URL fetches, and checksum helpers. Keep producing evidence without + # blocking unrelated work until that backlog is triaged. + name: Bandit SAST (advisory) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: "3.13" + - run: python -m pip install --upgrade pip bandit==1.8.6 + - name: Bandit (package source — Medium+ severity/confidence) + # Recurse the repo; in CI only tracked source is present. Exclude tests, + # the JS dashboard, docs, retired mocks, and .claude tooling hooks. B101 + # (assert_used) skipped. Medium+ thresholds focus on actionable findings. + # `|| true` keeps this advisory while the initial full-tree backlog is triaged. + run: bandit -r . --exclude './tests,./dashboard,./docs,./mocks,./.claude' --skip B101 --severity-level medium --confidence-level medium || true + + pip-audit: + name: pip-audit (advisory) + runs-on: ubuntu-latest + continue-on-error: true + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: "3.13" + - run: python -m pip install --upgrade pip pip-audit==2.9.0 + - name: Install project runtime deps so pip-audit sees them + run: python -m pip install -e . + - name: Audit installed dependencies for known CVEs + run: pip-audit diff --git a/README.md b/README.md index 4faea94..795e2fd 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ [![CI](https://img.shields.io/github/actions/workflow/status/BicameralAI/bicameral-mcp/test-mcp-regression.yml?branch=main&label=tests)](https://github.com/BicameralAI/bicameral-mcp/actions) [![Lint + Types](https://img.shields.io/github/actions/workflow/status/BicameralAI/bicameral-mcp/lint-and-typecheck.yml?branch=main&label=lint%2Btypes)](https://github.com/BicameralAI/bicameral-mcp/actions/workflows/lint-and-typecheck.yml) [![Secret scan](https://img.shields.io/github/actions/workflow/status/BicameralAI/bicameral-mcp/secret-scan.yml?branch=main&label=secret-scan)](https://github.com/BicameralAI/bicameral-mcp/actions/workflows/secret-scan.yml) +[![CodeQL](https://img.shields.io/github/actions/workflow/status/BicameralAI/bicameral-mcp/codeql.yml?branch=main&label=CodeQL)](https://github.com/BicameralAI/bicameral-mcp/actions/workflows/codeql.yml) +[![Security Scan](https://img.shields.io/github/actions/workflow/status/BicameralAI/bicameral-mcp/security-scan.yml?branch=main&label=security-scan)](https://github.com/BicameralAI/bicameral-mcp/actions/workflows/security-scan.yml) AI agents ship code fast. They forget what your team agreed — and requirement gaps surfaced mid-implementation are buried under thousands of lines of code. @@ -218,4 +220,3 @@ MIT `bicameral-mcp` is the agent-facing tool surface. It exposes local Bicameral actions to coding agents: ingest, preflight, bind, review-command emission, and local run loops. It is not the source-specific integration repo, the local bot runtime, or the hosted code graph. See `docs/adr/0001-mcp-repository-boundary.md`. -