diff --git a/.github/workflows/secret-scan.yml b/.github/workflows/secret-scan.yml new file mode 100644 index 0000000..e652404 --- /dev/null +++ b/.github/workflows/secret-scan.yml @@ -0,0 +1,38 @@ +# Secret-scan backstop. The allowlist export is the gate; this is the seatbelt. +# Uses the gitleaks BINARY (Apache-2.0, free) — NOT gitleaks-action, which +# requires a paid GITLEAKS_LICENSE for organization repos. Scans the current tree +# (--no-git) so it blocks NEW secrets/infra strings without re-flagging old history. +name: secret-scan +on: + push: + pull_request: + +jobs: + gitleaks: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: install gitleaks + run: | + curl -sSL -o /tmp/gl.tgz \ + https://github.com/gitleaks/gitleaks/releases/download/v8.30.1/gitleaks_8.30.1_linux_x64.tar.gz + tar -xzf /tmp/gl.tgz -C /tmp gitleaks + sudo install /tmp/gitleaks /usr/local/bin/gitleaks + - name: scan working tree + run: gitleaks detect --source . --no-git --config .gitleaks.toml --redact --verbose + + infra-strings: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: block infra / local-path leaks + run: | + set -e + patt='172\.(30|31)\.[0-9]+\.[0-9]+|/Users/[a-z0-9._-]+/|aipgcoregen|BEGIN (RSA |EC |OPENSSH |)PRIVATE KEY' + if git grep -nIE "$patt" -- . ':(exclude).gitleaks.toml' ':(exclude)**/secret-scan.yml'; then + echo "::error::infra/secret string found above — scrub before merge"; exit 1 + fi + if git ls-files | grep -iE 'security_audit|audit_report'; then + echo "::error::audit report file tracked — must not ship"; exit 1 + fi + echo "infra-string scan clean" diff --git a/.gitleaks.toml b/.gitleaks.toml new file mode 100644 index 0000000..7ef72ed --- /dev/null +++ b/.gitleaks.toml @@ -0,0 +1,62 @@ +# gitleaks config for AIPG OSS release scanning. +# Extends gitleaks' default ruleset (API keys, AWS, private keys, JWTs, ...) with +# AIPG-specific leaks that the defaults DON'T catch: internal infra, local dev +# paths, R2 buckets, on-chain addresses. Use with: +# gitleaks detect --source --config .gitleaks.toml --redact + +[extend] +useDefault = true + +[[rules]] +id = "aipg-internal-ip" +description = "Internal datacenter IP (Proxmox/LXC range)" +regex = '''\b(172\.(3[01])|10\.)\.\d{1,3}\.\d{1,3}\b''' +tags = ["aipg", "infra"] + +[[rules]] +id = "aipg-local-dev-path" +description = "Local developer absolute path (leaks username / machine layout)" +regex = '''/Users/[a-z0-9._-]+/''' +tags = ["aipg", "infra"] + +[[rules]] +id = "aipg-r2-bucket" +description = "Cloudflare R2 / internal bucket names" +regex = '''\b(aipgcoregen|aipg-transient|aipgcore[a-z0-9-]*)\b''' +tags = ["aipg", "infra"] + +[[rules]] +id = "aipg-eth-private-key" +description = "EVM private key (64 hex, optionally 0x)" +regex = '''\b(0x)?[a-fA-F0-9]{64}\b''' +tags = ["aipg", "wallet"] +# Hex-64 is also sha256 hashes / git oids → high false positives. Treated as a +# REVIEW signal, not an auto-block; the human triages contracts/worker output. +[rules.allowlist] +regexes = ['''[a-f0-9]{64}'''] # lowercase-only 64hex (hashes) are usually benign +paths = ['''(?i)(test|fixture|mock|\.lock|package-lock|yarn\.lock|poetry\.lock)'''] + +[[rules]] +id = "aipg-mnemonic" +description = "BIP-39 mnemonic / seed phrase markers" +regex = '''(?i)(mnemonic|seed[\s_-]?phrase)\s*[:=]\s*["']?(\w+\s+){11,}''' +tags = ["aipg", "wallet"] + +# Global allowlist: example/template/sample env + docs placeholders never block. +[allowlist] +description = "Non-secret placeholders, lockfiles, and the scanner's own config" +paths = [ + '''(?i)\.env\.(example|template|sample)$''', + '''(?i)(^|/)(examples?|samples?)/''', + '''(?i)\.(lock)$''', + '''(?i)(package-lock\.json|yarn\.lock|pnpm-lock\.yaml|poetry\.lock|Cargo\.lock)$''', + # The scanner's own files contain the patterns by definition — never self-flag. + '''(?i)\.gitleaks\.toml$''', + '''(?i)secret-scan\.ya?ml$''', +] +regexes = [ + '''(?i)(your[-_]?api[-_]?key|example|placeholder|changeme|xxxx+|<[a-z_]+>)''', + # EVM addresses (0x + 40 hex) are PUBLIC on-chain identifiers, never secrets — + # gitleaks' generic rule over-flags `ADDR = '0x...'` assignments. + '''0x[a-fA-F0-9]{40}\b''', +] diff --git a/AGENTS.md b/AGENTS.md index 24cc6fc..f40381d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -59,7 +59,7 @@ which is intentionally NOT published. ## Local Contracts -- **Inherit org engineering standards:** `/Users/j/fix-axios-vuln/aipg-documentation/engineering-standards/` +- **Inherit org engineering standards:** `aipg-documentation/engineering-standards/` (core + `git.md` + the matching language file). The rules below are docs-repo specializations. - **Only `pages/` is published.** Anything that must NOT ship to the public site (standards, research, internal notes) lives outside `pages/`. Adding a routable page = adding to `pages/`. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..0c445e5 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,21 @@ +# Security Policy + +## Reporting a vulnerability + +Email **security@aipowergrid.io** (or open a private GitHub security advisory). +Please do **not** open public issues for security reports. + +- We acknowledge within 72 hours and aim to triage within 7 days. +- Coordinated disclosure: give us a reasonable window to ship a fix before public + disclosure. We credit reporters who follow this process. + +## Scope + +In scope: this repository's code, smart contracts, and protocol handling. +Out of scope: third-party dependencies (report upstream), social engineering, +volumetric DoS. + +## Smart contracts + +On-chain code on Base is verified and public. Findings affecting funds, access +control, or settlement are highest priority.