diff --git a/packages/cli/package.json b/packages/cli/package.json index d7b76af09..83b77c769 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@openrouter/spawn", - "version": "1.0.36", + "version": "1.0.37", "type": "module", "bin": { "spawn": "cli.js" diff --git a/packages/cli/src/__tests__/export.test.ts b/packages/cli/src/__tests__/export.test.ts index 6a4510655..e5497eeea 100644 --- a/packages/cli/src/__tests__/export.test.ts +++ b/packages/cli/src/__tests__/export.test.ts @@ -194,13 +194,16 @@ describe("buildExportScript", () => { const s = buildExportScript(opts); expect(s).toContain("SECRET_REGEX="); // Verify a representative pattern from each provider family is present - expect(s).toContain("sk-or-v1-"); // OpenRouter + expect(s).toContain("sk-or-[a-zA-Z0-9_-]"); // OpenRouter (v1, v2+) expect(s).toContain("sk-ant-api"); // Anthropic expect(s).toContain("sk-proj-"); // OpenAI expect(s).toContain("gh[ops]_"); // GitHub PAT/OAuth/server expect(s).toContain("AKIA"); // AWS access key expect(s).toContain("hcloud_"); // Hetzner expect(s).toContain("dop_v1_"); // DigitalOcean + expect(s).toContain("xox[abp]-"); // Slack bot/user/app tokens + expect(s).toContain("sk_live_"); // Stripe live keys + expect(s).toContain("service_account"); // Google service account JSON expect(s).toContain("BEGIN ([A-Z]+ )?PRIVATE KEY"); // PEM }); diff --git a/packages/cli/src/commands/export.ts b/packages/cli/src/commands/export.ts index 76ef6f55c..3baa51137 100644 --- a/packages/cli/src/commands/export.ts +++ b/packages/cli/src/commands/export.ts @@ -323,7 +323,20 @@ export function buildExportScript(opts: { "# 9. SECRETS SCAN — first pass just detects and stops if hits exist so the", "# host can confirm before pushing. Second pass (ALLOW_REDACT=1) redacts", "# in-place and continues to commit/push.", - "SECRET_REGEX='(sk-or-v1-[a-f0-9]{20,})|(sk-ant-api[0-9-]+_[A-Za-z0-9_-]{20,})|(sk-proj-[A-Za-z0-9_-]{20,})|(gh[ops]_[A-Za-z0-9]{36})|(AKIA[0-9A-Z]{16})|(hcloud_[a-zA-Z0-9_-]{20,})|(dop_v1_[a-f0-9]{32,})|(-----BEGIN ([A-Z]+ )?PRIVATE KEY-----)'", + "# Secret patterns grouped by provider family:", + "# - OpenRouter: sk-or- prefix (v1, v2+, non-hex chars)", + "# - Anthropic: sk-ant-api prefix", + "# - OpenAI: sk-proj- prefix", + "# - GitHub: gho/ghp/ghs tokens", + "# - AWS: AKIA access key IDs", + "# - Hetzner: hcloud_ tokens", + "# - DigitalOcean: dop_v1_ tokens", + "# - Slack: xoxb/xoxp/xoxa bot/user/app tokens", + "# - Stripe: sk_live_ secret keys", + "# - Discord: bot tokens (base64-encoded user ID.timestamp.HMAC)", + "# - Google: service account JSON blocks", + "# - PEM: private key blocks", + 'SECRET_REGEX=\'(sk-or-[a-zA-Z0-9_-]{20,})|(sk-ant-api[0-9-]+_[A-Za-z0-9_-]{20,})|(sk-proj-[A-Za-z0-9_-]{20,})|(gh[ops]_[A-Za-z0-9]{36})|(AKIA[0-9A-Z]{16})|(hcloud_[a-zA-Z0-9_-]{20,})|(dop_v1_[a-f0-9]{32,})|(xox[abp]-[0-9A-Za-z-]{10,})|(sk_live_[A-Za-z0-9]{24,})|([A-Za-z0-9_-]{24}\\.[A-Za-z0-9_-]{6}\\.[A-Za-z0-9_-]{27,})|("type":\\s*"service_account")|(-----BEGIN ([A-Z]+ )?PRIVATE KEY-----)\'', "REDACT_PLACEHOLDER='***REDACTED-BY-SPAWN-EXPORT***'", 'SECRET_HITS="$(git ls-files -z | xargs -0 grep -lEa "$SECRET_REGEX" 2>/dev/null || true)"', 'REDACTED_JSON="[]"',