Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,6 @@ jobs:
with:
persist-credentials: false

# Keep source scanning in the required Gate job so a finding blocks merge.
# Scan docs and generated assets too; the container only sees runtime files.
- name: Scan repository for secrets
uses: aquasecurity/trivy-action@a9c7b0f06e461e9d4b4d1711f154ee024b8d7ab8 # v0.36.0
with:
scan-type: fs
scan-ref: .
version: v0.74.0
scanners: secret
exit-code: 1
format: table
cache: false

- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
Expand Down
49 changes: 49 additions & 0 deletions .github/workflows/leaks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Leaks

# Secrets, private AI session links and local workstation paths stay out of
# this public repository. The rules live in .gitleaks.toml.
on:
push:
branches: [main]
pull_request:
branches: [main]
types: [opened, edited, synchronize, reopened]

permissions:
contents: read

env:
GITLEAKS_VERSION: 8.30.1
GITLEAKS_SHA256: 551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb

jobs:
leaks:
name: Leaks
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false

- name: Install gitleaks
run: |
archive="$RUNNER_TEMP/gitleaks.tar.gz"
curl -fsSLo "$archive" "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
echo "${GITLEAKS_SHA256} $archive" | sha256sum -c -
tar -xzf "$archive" -C "$RUNNER_TEMP" gitleaks

- name: Scan files
run: '"$RUNNER_TEMP/gitleaks" dir . --redact --no-banner'

# Edits to the description rerun this job, so the text is checked as posted.
- name: Scan pull request text and commit messages
if: github.event_name == 'pull_request'
env:
TITLE: ${{ github.event.pull_request.title }}
BODY: ${{ github.event.pull_request.body }}
BASE: ${{ github.event.pull_request.base.sha }}
HEAD: ${{ github.event.pull_request.head.sha }}
run: |
{ printf '%s\n%s\n' "$TITLE" "$BODY"; git log --format=%B "$BASE..$HEAD"; } |
"$RUNNER_TEMP/gitleaks" stdin --redact --no-banner
21 changes: 17 additions & 4 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Default rules, plus known non-secrets: a fixed test-only auth code secret,
# a redaction fixture, a cache key name, and content hashes in fixtures.
# Default secret rules, plus links and paths this public repository must never
# publish, and known non-secrets: a fixed test-only auth code secret, a
# redaction fixture, a cache key name, and content hashes in fixtures.
# Lefthook and the Leaks workflow read this file; add a rule here to extend both.
[extend]
useDefault = true

Expand All @@ -12,9 +14,20 @@ regexes = [
]

[[allowlists]]
description = "content hashes in fixtures and the retired Atlas checksum file"
description = "content hashes in fixtures"
paths = [
'''^ui/host/e2e/data/mcp\.json$''',
'''^ui/host/tests/go-fragments/[^/]+\.json$''',
'''^internal/db/migrations/atlas\.sum$''',
]

[[rules]]
id = "private-ai-session-link"
description = "Private AI session link or session trailer"
regex = '''(?i)(claude\.ai/(code|chat|share|project)/|Claude-Session:|chatgpt\.com/(c|share|codex)/)'''
keywords = ["claude", "chatgpt"]

[[rules]]
id = "local-workstation-path"
description = "Local workstation home directory path"
regex = '''(/Users|/home)/[A-Za-z0-9_.-]+/'''
keywords = ["/users/", "/home/"]
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@

- Keep credentials, private telemetry, local workstation paths, and private AI
session links out of tracked files, commit messages, and pull request descriptions.
`.gitleaks.toml` holds the rules; lefthook and the Leaks workflow enforce them.
Squash merges take the pull request title and description.
- Keep local agent caches, indexes, evaluation records, and browser evidence out
of both Git and the Docker build context. Git ignores do not exclude Docker inputs.
- Design proposals live in `docs/proposals/NNNN-slug.md` and decision records
Expand Down
9 changes: 9 additions & 0 deletions lefthook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
pre-commit:
parallel: false
jobs:
# Secrets, private AI session links and local paths, by .gitleaks.toml.
- name: leaks
run: gitleaks git --pre-commit --staged --redact --no-banner

- name: merge-conflict
glob: "*"
# Minified single-file bundles legitimately contain long runs of `=`, so
Expand Down Expand Up @@ -39,6 +43,11 @@ pre-commit:
glob: "{ui/host/**/*.{ts,tsx},ui/panels/**/*.{ts,tsx},ui/*.ts}"
run: cd ui/host && bun run lint

commit-msg:
jobs:
- name: leaks
run: gitleaks stdin --redact --no-banner < {1}

pre-push:
jobs:
- name: check
Expand Down
Loading