Skip to content

fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes - #3386

Open
la14-1 wants to merge 1 commit into
mainfrom
fix/broaden-secret-regex
Open

fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes#3386
la14-1 wants to merge 1 commit into
mainfrom
fix/broaden-secret-regex

Conversation

@la14-1

Copy link
Copy Markdown
Collaborator

Why: Closes known gaps in the SECRET_REGEX that would allow Slack tokens, Stripe live keys, Discord bot tokens, and future OpenRouter key prefixes to bypass the export redaction pass — the last line of defense before a potentially public gh repo create --push.

Fixes#3381

Changes

  • OpenRouter: widened from sk-or-v1-[a-f0-9]{20,} to sk-or-[a-zA-Z0-9_-]{20,} (covers v2+ prefixes and non-hex chars)
  • Slack: added xox[abp]-[0-9A-Za-z-]{10,} (bot/user/app tokens)
  • Stripe: added sk_live_[A-Za-z0-9]{24,} (live secret keys)
  • Discord: added [A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} (bot tokens)
  • Google: added "type":\s*"service_account" (service account JSON blocks)
  • Added inline comments documenting each provider family
  • Updated tests to verify the new patterns
  • Bumped CLI version to 1.0.37

Skipped generic Authorization: Bearer pattern as too noisy for default mode (noted in issue as --strict only).

-- refactor/ux-engineer

@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Status check (2026-05-05):

This PR is green and ready for security review. The regex broadening covers Slack, Stripe, Discord, Google SA, and future OR prefixes as described.

-- refactor/pr-maintainer

@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Security Review: Broadened SECRET_REGEX

Verdict: LGTM — good coverage expansion

Changes Reviewed

The regex now covers:

  • OpenRoutersk-or-[a-zA-Z0-9_-]{20,} (was sk-or-v1-[a-f0-9]{20,}) — correctly handles v2+ keys with non-hex chars
  • Slackxox[abp]-[0-9A-Za-z-]{10,} — covers bot, user, and app tokens
  • Stripesk_live_[A-Za-z0-9]{24,} — live secret keys
  • Discord[A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} — bot token format (base64 user ID.timestamp.HMAC)
  • Google"type":\s*"service_account" — matches service account JSON

Security Assessment

  1. OpenRouter regex broadening — Critical fix. The old regex only matched sk-or-v1- with hex chars, meaning v2+ keys (or keys with base64url chars) would leak unredacted. Good catch.

  2. Discord token pattern — The [A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} pattern is broad enough to potentially false-positive on JWTs or other dot-separated base64 strings. However, for a redaction use case, false positives are far safer than false negatives. Acceptable tradeoff.

  3. Google service account — Matching "type":\s*"service_account" detects the presence of a service account JSON but won't redact the actual private_key field on its own. However, the PEM pattern -----BEGIN.*PRIVATE KEY----- already catches that. Together they provide good coverage.

  4. Delimiter fix (from PR fix(export): use '#' as sed delimiter (regex '|' was clashing) #3384) — The regex uses | for alternation. PR fix(export): use '#' as sed delimiter (regex '|' was clashing) #3384 already fixed the sed delimiter to # so the pipe chars in the regex don't break the sed command. Verified these work together.

Notes (non-blocking)

  • The {20,} minimum lengths are reasonable — short enough to catch truncated pastes in config files, long enough to avoid most false positives on common identifiers.
  • Test coverage is updated to verify the new patterns are present. Good.

-- refactor/security-auditor

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch 2 times, most recently from 0e0ca56 to e8e7ed9CompareMay 9, 2026 16:16
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Re-ran the failed Mock Tests check — the failing test (history > saveSpawnRecord > keeps all entries with no cap) timed out after 5000ms, which appears to be a flaky test unrelated to this PR's SECRET_REGEX changes. Monitoring the re-run.

-- refactor/pr-maintainer

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch 2 times, most recently from 1860fd5 to 4561048CompareMay 12, 2026 20:35
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Rebased onto main (was 1 commit behind). Verified in worktree: 2202/2204 tests pass, biome lint clean (0 errors). The 2 failures (hetzner-cov, digitalocean-token) are pre-existing cross-test fetch mock contamination — they pass in isolation and are addressed by #3406. PR is mergeable and ready for review.

-- refactor/pr-maintainer

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch from 4561048 to f1e701aCompareMay 14, 2026 14:52
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Verified on current main (2026-05-18): lint clean (0 errors), 2203 pass / 3 fail (all pre-existing: hetzner-cov, digitalocean-token, applySpawnMdSetup base64). Branch is mergeable with no conflicts. Ready for review.

-- refactor/pr-maintainer

…ogle SA, future OR prefixes
Closes known gaps in the secret-scan regex that would allow Slack tokens
(xoxb/xoxp/xoxa), Stripe live keys (sk_live_), Discord bot tokens,
Google service account JSON blocks, and future OpenRouter key prefixes
(sk-or-v2+) to bypass the export redaction pass.
Fixes#3381
Agent: ux-engineer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch from f1e701a to 8f4b4a3CompareMay 21, 2026 22:30
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Rebased onto main (was 2 commits behind). Clean rebase, no conflicts. Awaiting human review.

-- refactor/pr-maintainer

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CLI]: broaden spawn export secret-scan regex

2 participants

@la14-1@louisgv
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes by la14-1 · Pull Request #3386 · OpenRouterLabs/spawn · GitHub
Skip to content

fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes - #3386

Open
la14-1 wants to merge 1 commit into
mainfrom
fix/broaden-secret-regex
Open

fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes#3386
la14-1 wants to merge 1 commit into
mainfrom
fix/broaden-secret-regex

Conversation

@la14-1

Copy link
Copy Markdown
Collaborator

Why: Closes known gaps in the SECRET_REGEX that would allow Slack tokens, Stripe live keys, Discord bot tokens, and future OpenRouter key prefixes to bypass the export redaction pass — the last line of defense before a potentially public gh repo create --push.

Fixes#3381

Changes

  • OpenRouter: widened from sk-or-v1-[a-f0-9]{20,} to sk-or-[a-zA-Z0-9_-]{20,} (covers v2+ prefixes and non-hex chars)
  • Slack: added xox[abp]-[0-9A-Za-z-]{10,} (bot/user/app tokens)
  • Stripe: added sk_live_[A-Za-z0-9]{24,} (live secret keys)
  • Discord: added [A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} (bot tokens)
  • Google: added "type":\s*"service_account" (service account JSON blocks)
  • Added inline comments documenting each provider family
  • Updated tests to verify the new patterns
  • Bumped CLI version to 1.0.37

Skipped generic Authorization: Bearer pattern as too noisy for default mode (noted in issue as --strict only).

-- refactor/ux-engineer

@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Status check (2026-05-05):

This PR is green and ready for security review. The regex broadening covers Slack, Stripe, Discord, Google SA, and future OR prefixes as described.

-- refactor/pr-maintainer

@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Security Review: Broadened SECRET_REGEX

Verdict: LGTM — good coverage expansion

Changes Reviewed

The regex now covers:

  • OpenRoutersk-or-[a-zA-Z0-9_-]{20,} (was sk-or-v1-[a-f0-9]{20,}) — correctly handles v2+ keys with non-hex chars
  • Slackxox[abp]-[0-9A-Za-z-]{10,} — covers bot, user, and app tokens
  • Stripesk_live_[A-Za-z0-9]{24,} — live secret keys
  • Discord[A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} — bot token format (base64 user ID.timestamp.HMAC)
  • Google"type":\s*"service_account" — matches service account JSON

Security Assessment

  1. OpenRouter regex broadening — Critical fix. The old regex only matched sk-or-v1- with hex chars, meaning v2+ keys (or keys with base64url chars) would leak unredacted. Good catch.

  2. Discord token pattern — The [A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} pattern is broad enough to potentially false-positive on JWTs or other dot-separated base64 strings. However, for a redaction use case, false positives are far safer than false negatives. Acceptable tradeoff.

  3. Google service account — Matching "type":\s*"service_account" detects the presence of a service account JSON but won't redact the actual private_key field on its own. However, the PEM pattern -----BEGIN.*PRIVATE KEY----- already catches that. Together they provide good coverage.

  4. Delimiter fix (from PR fix(export): use '#' as sed delimiter (regex '|' was clashing) #3384) — The regex uses | for alternation. PR fix(export): use '#' as sed delimiter (regex '|' was clashing) #3384 already fixed the sed delimiter to # so the pipe chars in the regex don't break the sed command. Verified these work together.

Notes (non-blocking)

  • The {20,} minimum lengths are reasonable — short enough to catch truncated pastes in config files, long enough to avoid most false positives on common identifiers.
  • Test coverage is updated to verify the new patterns are present. Good.

-- refactor/security-auditor

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch 2 times, most recently from 0e0ca56 to e8e7ed9CompareMay 9, 2026 16:16
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Re-ran the failed Mock Tests check — the failing test (history > saveSpawnRecord > keeps all entries with no cap) timed out after 5000ms, which appears to be a flaky test unrelated to this PR's SECRET_REGEX changes. Monitoring the re-run.

-- refactor/pr-maintainer

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch 2 times, most recently from 1860fd5 to 4561048CompareMay 12, 2026 20:35
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Rebased onto main (was 1 commit behind). Verified in worktree: 2202/2204 tests pass, biome lint clean (0 errors). The 2 failures (hetzner-cov, digitalocean-token) are pre-existing cross-test fetch mock contamination — they pass in isolation and are addressed by #3406. PR is mergeable and ready for review.

-- refactor/pr-maintainer

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch from 4561048 to f1e701aCompareMay 14, 2026 14:52
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Verified on current main (2026-05-18): lint clean (0 errors), 2203 pass / 3 fail (all pre-existing: hetzner-cov, digitalocean-token, applySpawnMdSetup base64). Branch is mergeable with no conflicts. Ready for review.

-- refactor/pr-maintainer

…ogle SA, future OR prefixes
Closes known gaps in the secret-scan regex that would allow Slack tokens
(xoxb/xoxp/xoxa), Stripe live keys (sk_live_), Discord bot tokens,
Google service account JSON blocks, and future OpenRouter key prefixes
(sk-or-v2+) to bypass the export redaction pass.
Fixes#3381
Agent: ux-engineer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch from f1e701a to 8f4b4a3CompareMay 21, 2026 22:30
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Rebased onto main (was 2 commits behind). Clean rebase, no conflicts. Awaiting human review.

-- refactor/pr-maintainer

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CLI]: broaden spawn export secret-scan regex

2 participants

@la14-1@louisgv
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes by la14-1 · Pull Request #3386 · OpenRouterLabs/spawn · GitHub
Skip to content

fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes - #3386

Open
la14-1 wants to merge 1 commit into
mainfrom
fix/broaden-secret-regex
Open

fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes#3386
la14-1 wants to merge 1 commit into
mainfrom
fix/broaden-secret-regex

Conversation

@la14-1

Copy link
Copy Markdown
Collaborator

Why: Closes known gaps in the SECRET_REGEX that would allow Slack tokens, Stripe live keys, Discord bot tokens, and future OpenRouter key prefixes to bypass the export redaction pass — the last line of defense before a potentially public gh repo create --push.

Fixes#3381

Changes

  • OpenRouter: widened from sk-or-v1-[a-f0-9]{20,} to sk-or-[a-zA-Z0-9_-]{20,} (covers v2+ prefixes and non-hex chars)
  • Slack: added xox[abp]-[0-9A-Za-z-]{10,} (bot/user/app tokens)
  • Stripe: added sk_live_[A-Za-z0-9]{24,} (live secret keys)
  • Discord: added [A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} (bot tokens)
  • Google: added "type":\s*"service_account" (service account JSON blocks)
  • Added inline comments documenting each provider family
  • Updated tests to verify the new patterns
  • Bumped CLI version to 1.0.37

Skipped generic Authorization: Bearer pattern as too noisy for default mode (noted in issue as --strict only).

-- refactor/ux-engineer

@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Status check (2026-05-05):

This PR is green and ready for security review. The regex broadening covers Slack, Stripe, Discord, Google SA, and future OR prefixes as described.

-- refactor/pr-maintainer

@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Security Review: Broadened SECRET_REGEX

Verdict: LGTM — good coverage expansion

Changes Reviewed

The regex now covers:

  • OpenRoutersk-or-[a-zA-Z0-9_-]{20,} (was sk-or-v1-[a-f0-9]{20,}) — correctly handles v2+ keys with non-hex chars
  • Slackxox[abp]-[0-9A-Za-z-]{10,} — covers bot, user, and app tokens
  • Stripesk_live_[A-Za-z0-9]{24,} — live secret keys
  • Discord[A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} — bot token format (base64 user ID.timestamp.HMAC)
  • Google"type":\s*"service_account" — matches service account JSON

Security Assessment

  1. OpenRouter regex broadening — Critical fix. The old regex only matched sk-or-v1- with hex chars, meaning v2+ keys (or keys with base64url chars) would leak unredacted. Good catch.

  2. Discord token pattern — The [A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} pattern is broad enough to potentially false-positive on JWTs or other dot-separated base64 strings. However, for a redaction use case, false positives are far safer than false negatives. Acceptable tradeoff.

  3. Google service account — Matching "type":\s*"service_account" detects the presence of a service account JSON but won't redact the actual private_key field on its own. However, the PEM pattern -----BEGIN.*PRIVATE KEY----- already catches that. Together they provide good coverage.

  4. Delimiter fix (from PR fix(export): use '#' as sed delimiter (regex '|' was clashing) #3384) — The regex uses | for alternation. PR fix(export): use '#' as sed delimiter (regex '|' was clashing) #3384 already fixed the sed delimiter to # so the pipe chars in the regex don't break the sed command. Verified these work together.

Notes (non-blocking)

  • The {20,} minimum lengths are reasonable — short enough to catch truncated pastes in config files, long enough to avoid most false positives on common identifiers.
  • Test coverage is updated to verify the new patterns are present. Good.

-- refactor/security-auditor

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch 2 times, most recently from 0e0ca56 to e8e7ed9CompareMay 9, 2026 16:16
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Re-ran the failed Mock Tests check — the failing test (history > saveSpawnRecord > keeps all entries with no cap) timed out after 5000ms, which appears to be a flaky test unrelated to this PR's SECRET_REGEX changes. Monitoring the re-run.

-- refactor/pr-maintainer

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch 2 times, most recently from 1860fd5 to 4561048CompareMay 12, 2026 20:35
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Rebased onto main (was 1 commit behind). Verified in worktree: 2202/2204 tests pass, biome lint clean (0 errors). The 2 failures (hetzner-cov, digitalocean-token) are pre-existing cross-test fetch mock contamination — they pass in isolation and are addressed by #3406. PR is mergeable and ready for review.

-- refactor/pr-maintainer

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch from 4561048 to f1e701aCompareMay 14, 2026 14:52
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Verified on current main (2026-05-18): lint clean (0 errors), 2203 pass / 3 fail (all pre-existing: hetzner-cov, digitalocean-token, applySpawnMdSetup base64). Branch is mergeable with no conflicts. Ready for review.

-- refactor/pr-maintainer

…ogle SA, future OR prefixes
Closes known gaps in the secret-scan regex that would allow Slack tokens
(xoxb/xoxp/xoxa), Stripe live keys (sk_live_), Discord bot tokens,
Google service account JSON blocks, and future OpenRouter key prefixes
(sk-or-v2+) to bypass the export redaction pass.
Fixes#3381
Agent: ux-engineer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch from f1e701a to 8f4b4a3CompareMay 21, 2026 22:30
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Rebased onto main (was 2 commits behind). Clean rebase, no conflicts. Awaiting human review.

-- refactor/pr-maintainer

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CLI]: broaden spawn export secret-scan regex

2 participants

@la14-1@louisgv
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes by la14-1 · Pull Request #3386 · OpenRouterLabs/spawn · GitHub
Skip to content

fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes - #3386

Open
la14-1 wants to merge 1 commit into
mainfrom
fix/broaden-secret-regex
Open

fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes#3386
la14-1 wants to merge 1 commit into
mainfrom
fix/broaden-secret-regex

Conversation

@la14-1

Copy link
Copy Markdown
Collaborator

Why: Closes known gaps in the SECRET_REGEX that would allow Slack tokens, Stripe live keys, Discord bot tokens, and future OpenRouter key prefixes to bypass the export redaction pass — the last line of defense before a potentially public gh repo create --push.

Fixes#3381

Changes

  • OpenRouter: widened from sk-or-v1-[a-f0-9]{20,} to sk-or-[a-zA-Z0-9_-]{20,} (covers v2+ prefixes and non-hex chars)
  • Slack: added xox[abp]-[0-9A-Za-z-]{10,} (bot/user/app tokens)
  • Stripe: added sk_live_[A-Za-z0-9]{24,} (live secret keys)
  • Discord: added [A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} (bot tokens)
  • Google: added "type":\s*"service_account" (service account JSON blocks)
  • Added inline comments documenting each provider family
  • Updated tests to verify the new patterns
  • Bumped CLI version to 1.0.37

Skipped generic Authorization: Bearer pattern as too noisy for default mode (noted in issue as --strict only).

-- refactor/ux-engineer

@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Status check (2026-05-05):

This PR is green and ready for security review. The regex broadening covers Slack, Stripe, Discord, Google SA, and future OR prefixes as described.

-- refactor/pr-maintainer

@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Security Review: Broadened SECRET_REGEX

Verdict: LGTM — good coverage expansion

Changes Reviewed

The regex now covers:

  • OpenRoutersk-or-[a-zA-Z0-9_-]{20,} (was sk-or-v1-[a-f0-9]{20,}) — correctly handles v2+ keys with non-hex chars
  • Slackxox[abp]-[0-9A-Za-z-]{10,} — covers bot, user, and app tokens
  • Stripesk_live_[A-Za-z0-9]{24,} — live secret keys
  • Discord[A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} — bot token format (base64 user ID.timestamp.HMAC)
  • Google"type":\s*"service_account" — matches service account JSON

Security Assessment

  1. OpenRouter regex broadening — Critical fix. The old regex only matched sk-or-v1- with hex chars, meaning v2+ keys (or keys with base64url chars) would leak unredacted. Good catch.

  2. Discord token pattern — The [A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} pattern is broad enough to potentially false-positive on JWTs or other dot-separated base64 strings. However, for a redaction use case, false positives are far safer than false negatives. Acceptable tradeoff.

  3. Google service account — Matching "type":\s*"service_account" detects the presence of a service account JSON but won't redact the actual private_key field on its own. However, the PEM pattern -----BEGIN.*PRIVATE KEY----- already catches that. Together they provide good coverage.

  4. Delimiter fix (from PR fix(export): use '#' as sed delimiter (regex '|' was clashing) #3384) — The regex uses | for alternation. PR fix(export): use '#' as sed delimiter (regex '|' was clashing) #3384 already fixed the sed delimiter to # so the pipe chars in the regex don't break the sed command. Verified these work together.

Notes (non-blocking)

  • The {20,} minimum lengths are reasonable — short enough to catch truncated pastes in config files, long enough to avoid most false positives on common identifiers.
  • Test coverage is updated to verify the new patterns are present. Good.

-- refactor/security-auditor

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch 2 times, most recently from 0e0ca56 to e8e7ed9CompareMay 9, 2026 16:16
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Re-ran the failed Mock Tests check — the failing test (history > saveSpawnRecord > keeps all entries with no cap) timed out after 5000ms, which appears to be a flaky test unrelated to this PR's SECRET_REGEX changes. Monitoring the re-run.

-- refactor/pr-maintainer

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch 2 times, most recently from 1860fd5 to 4561048CompareMay 12, 2026 20:35
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Rebased onto main (was 1 commit behind). Verified in worktree: 2202/2204 tests pass, biome lint clean (0 errors). The 2 failures (hetzner-cov, digitalocean-token) are pre-existing cross-test fetch mock contamination — they pass in isolation and are addressed by #3406. PR is mergeable and ready for review.

-- refactor/pr-maintainer

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch from 4561048 to f1e701aCompareMay 14, 2026 14:52
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Verified on current main (2026-05-18): lint clean (0 errors), 2203 pass / 3 fail (all pre-existing: hetzner-cov, digitalocean-token, applySpawnMdSetup base64). Branch is mergeable with no conflicts. Ready for review.

-- refactor/pr-maintainer

…ogle SA, future OR prefixes
Closes known gaps in the secret-scan regex that would allow Slack tokens
(xoxb/xoxp/xoxa), Stripe live keys (sk_live_), Discord bot tokens,
Google service account JSON blocks, and future OpenRouter key prefixes
(sk-or-v2+) to bypass the export redaction pass.
Fixes#3381
Agent: ux-engineer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch from f1e701a to 8f4b4a3CompareMay 21, 2026 22:30
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Rebased onto main (was 2 commits behind). Clean rebase, no conflicts. Awaiting human review.

-- refactor/pr-maintainer

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CLI]: broaden spawn export secret-scan regex

2 participants

@la14-1@louisgv
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes by la14-1 · Pull Request #3386 · OpenRouterLabs/spawn · GitHub
Skip to content

fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes - #3386

Open
la14-1 wants to merge 1 commit into
mainfrom
fix/broaden-secret-regex
Open

fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes#3386
la14-1 wants to merge 1 commit into
mainfrom
fix/broaden-secret-regex

Conversation

@la14-1

Copy link
Copy Markdown
Collaborator

Why: Closes known gaps in the SECRET_REGEX that would allow Slack tokens, Stripe live keys, Discord bot tokens, and future OpenRouter key prefixes to bypass the export redaction pass — the last line of defense before a potentially public gh repo create --push.

Fixes#3381

Changes

  • OpenRouter: widened from sk-or-v1-[a-f0-9]{20,} to sk-or-[a-zA-Z0-9_-]{20,} (covers v2+ prefixes and non-hex chars)
  • Slack: added xox[abp]-[0-9A-Za-z-]{10,} (bot/user/app tokens)
  • Stripe: added sk_live_[A-Za-z0-9]{24,} (live secret keys)
  • Discord: added [A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} (bot tokens)
  • Google: added "type":\s*"service_account" (service account JSON blocks)
  • Added inline comments documenting each provider family
  • Updated tests to verify the new patterns
  • Bumped CLI version to 1.0.37

Skipped generic Authorization: Bearer pattern as too noisy for default mode (noted in issue as --strict only).

-- refactor/ux-engineer

@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Status check (2026-05-05):

This PR is green and ready for security review. The regex broadening covers Slack, Stripe, Discord, Google SA, and future OR prefixes as described.

-- refactor/pr-maintainer

@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Security Review: Broadened SECRET_REGEX

Verdict: LGTM — good coverage expansion

Changes Reviewed

The regex now covers:

  • OpenRoutersk-or-[a-zA-Z0-9_-]{20,} (was sk-or-v1-[a-f0-9]{20,}) — correctly handles v2+ keys with non-hex chars
  • Slackxox[abp]-[0-9A-Za-z-]{10,} — covers bot, user, and app tokens
  • Stripesk_live_[A-Za-z0-9]{24,} — live secret keys
  • Discord[A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} — bot token format (base64 user ID.timestamp.HMAC)
  • Google"type":\s*"service_account" — matches service account JSON

Security Assessment

  1. OpenRouter regex broadening — Critical fix. The old regex only matched sk-or-v1- with hex chars, meaning v2+ keys (or keys with base64url chars) would leak unredacted. Good catch.

  2. Discord token pattern — The [A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} pattern is broad enough to potentially false-positive on JWTs or other dot-separated base64 strings. However, for a redaction use case, false positives are far safer than false negatives. Acceptable tradeoff.

  3. Google service account — Matching "type":\s*"service_account" detects the presence of a service account JSON but won't redact the actual private_key field on its own. However, the PEM pattern -----BEGIN.*PRIVATE KEY----- already catches that. Together they provide good coverage.

  4. Delimiter fix (from PR fix(export): use '#' as sed delimiter (regex '|' was clashing) #3384) — The regex uses | for alternation. PR fix(export): use '#' as sed delimiter (regex '|' was clashing) #3384 already fixed the sed delimiter to # so the pipe chars in the regex don't break the sed command. Verified these work together.

Notes (non-blocking)

  • The {20,} minimum lengths are reasonable — short enough to catch truncated pastes in config files, long enough to avoid most false positives on common identifiers.
  • Test coverage is updated to verify the new patterns are present. Good.

-- refactor/security-auditor

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch 2 times, most recently from 0e0ca56 to e8e7ed9CompareMay 9, 2026 16:16
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Re-ran the failed Mock Tests check — the failing test (history > saveSpawnRecord > keeps all entries with no cap) timed out after 5000ms, which appears to be a flaky test unrelated to this PR's SECRET_REGEX changes. Monitoring the re-run.

-- refactor/pr-maintainer

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch 2 times, most recently from 1860fd5 to 4561048CompareMay 12, 2026 20:35
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Rebased onto main (was 1 commit behind). Verified in worktree: 2202/2204 tests pass, biome lint clean (0 errors). The 2 failures (hetzner-cov, digitalocean-token) are pre-existing cross-test fetch mock contamination — they pass in isolation and are addressed by #3406. PR is mergeable and ready for review.

-- refactor/pr-maintainer

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch from 4561048 to f1e701aCompareMay 14, 2026 14:52
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Verified on current main (2026-05-18): lint clean (0 errors), 2203 pass / 3 fail (all pre-existing: hetzner-cov, digitalocean-token, applySpawnMdSetup base64). Branch is mergeable with no conflicts. Ready for review.

-- refactor/pr-maintainer

…ogle SA, future OR prefixes
Closes known gaps in the secret-scan regex that would allow Slack tokens
(xoxb/xoxp/xoxa), Stripe live keys (sk_live_), Discord bot tokens,
Google service account JSON blocks, and future OpenRouter key prefixes
(sk-or-v2+) to bypass the export redaction pass.
Fixes#3381
Agent: ux-engineer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch from f1e701a to 8f4b4a3CompareMay 21, 2026 22:30
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Rebased onto main (was 2 commits behind). Clean rebase, no conflicts. Awaiting human review.

-- refactor/pr-maintainer

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CLI]: broaden spawn export secret-scan regex

2 participants

@la14-1@louisgv
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes by la14-1 · Pull Request #3386 · OpenRouterLabs/spawn · GitHub
Skip to content

fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes - #3386

Open
la14-1 wants to merge 1 commit into
mainfrom
fix/broaden-secret-regex
Open

fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes#3386
la14-1 wants to merge 1 commit into
mainfrom
fix/broaden-secret-regex

Conversation

@la14-1

Copy link
Copy Markdown
Collaborator

Why: Closes known gaps in the SECRET_REGEX that would allow Slack tokens, Stripe live keys, Discord bot tokens, and future OpenRouter key prefixes to bypass the export redaction pass — the last line of defense before a potentially public gh repo create --push.

Fixes#3381

Changes

  • OpenRouter: widened from sk-or-v1-[a-f0-9]{20,} to sk-or-[a-zA-Z0-9_-]{20,} (covers v2+ prefixes and non-hex chars)
  • Slack: added xox[abp]-[0-9A-Za-z-]{10,} (bot/user/app tokens)
  • Stripe: added sk_live_[A-Za-z0-9]{24,} (live secret keys)
  • Discord: added [A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} (bot tokens)
  • Google: added "type":\s*"service_account" (service account JSON blocks)
  • Added inline comments documenting each provider family
  • Updated tests to verify the new patterns
  • Bumped CLI version to 1.0.37

Skipped generic Authorization: Bearer pattern as too noisy for default mode (noted in issue as --strict only).

-- refactor/ux-engineer

@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Status check (2026-05-05):

This PR is green and ready for security review. The regex broadening covers Slack, Stripe, Discord, Google SA, and future OR prefixes as described.

-- refactor/pr-maintainer

@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Security Review: Broadened SECRET_REGEX

Verdict: LGTM — good coverage expansion

Changes Reviewed

The regex now covers:

  • OpenRoutersk-or-[a-zA-Z0-9_-]{20,} (was sk-or-v1-[a-f0-9]{20,}) — correctly handles v2+ keys with non-hex chars
  • Slackxox[abp]-[0-9A-Za-z-]{10,} — covers bot, user, and app tokens
  • Stripesk_live_[A-Za-z0-9]{24,} — live secret keys
  • Discord[A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} — bot token format (base64 user ID.timestamp.HMAC)
  • Google"type":\s*"service_account" — matches service account JSON

Security Assessment

  1. OpenRouter regex broadening — Critical fix. The old regex only matched sk-or-v1- with hex chars, meaning v2+ keys (or keys with base64url chars) would leak unredacted. Good catch.

  2. Discord token pattern — The [A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} pattern is broad enough to potentially false-positive on JWTs or other dot-separated base64 strings. However, for a redaction use case, false positives are far safer than false negatives. Acceptable tradeoff.

  3. Google service account — Matching "type":\s*"service_account" detects the presence of a service account JSON but won't redact the actual private_key field on its own. However, the PEM pattern -----BEGIN.*PRIVATE KEY----- already catches that. Together they provide good coverage.

  4. Delimiter fix (from PR fix(export): use '#' as sed delimiter (regex '|' was clashing) #3384) — The regex uses | for alternation. PR fix(export): use '#' as sed delimiter (regex '|' was clashing) #3384 already fixed the sed delimiter to # so the pipe chars in the regex don't break the sed command. Verified these work together.

Notes (non-blocking)

  • The {20,} minimum lengths are reasonable — short enough to catch truncated pastes in config files, long enough to avoid most false positives on common identifiers.
  • Test coverage is updated to verify the new patterns are present. Good.

-- refactor/security-auditor

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch 2 times, most recently from 0e0ca56 to e8e7ed9CompareMay 9, 2026 16:16
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Re-ran the failed Mock Tests check — the failing test (history > saveSpawnRecord > keeps all entries with no cap) timed out after 5000ms, which appears to be a flaky test unrelated to this PR's SECRET_REGEX changes. Monitoring the re-run.

-- refactor/pr-maintainer

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch 2 times, most recently from 1860fd5 to 4561048CompareMay 12, 2026 20:35
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Rebased onto main (was 1 commit behind). Verified in worktree: 2202/2204 tests pass, biome lint clean (0 errors). The 2 failures (hetzner-cov, digitalocean-token) are pre-existing cross-test fetch mock contamination — they pass in isolation and are addressed by #3406. PR is mergeable and ready for review.

-- refactor/pr-maintainer

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch from 4561048 to f1e701aCompareMay 14, 2026 14:52
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Verified on current main (2026-05-18): lint clean (0 errors), 2203 pass / 3 fail (all pre-existing: hetzner-cov, digitalocean-token, applySpawnMdSetup base64). Branch is mergeable with no conflicts. Ready for review.

-- refactor/pr-maintainer

…ogle SA, future OR prefixes
Closes known gaps in the secret-scan regex that would allow Slack tokens
(xoxb/xoxp/xoxa), Stripe live keys (sk_live_), Discord bot tokens,
Google service account JSON blocks, and future OpenRouter key prefixes
(sk-or-v2+) to bypass the export redaction pass.
Fixes#3381
Agent: ux-engineer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch from f1e701a to 8f4b4a3CompareMay 21, 2026 22:30
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Rebased onto main (was 2 commits behind). Clean rebase, no conflicts. Awaiting human review.

-- refactor/pr-maintainer

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CLI]: broaden spawn export secret-scan regex

2 participants

@la14-1@louisgv
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes by la14-1 · Pull Request #3386 · OpenRouterLabs/spawn · GitHub
Skip to content

fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes - #3386

Open
la14-1 wants to merge 1 commit into
mainfrom
fix/broaden-secret-regex
Open

fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes#3386
la14-1 wants to merge 1 commit into
mainfrom
fix/broaden-secret-regex

Conversation

@la14-1

Copy link
Copy Markdown
Collaborator

Why: Closes known gaps in the SECRET_REGEX that would allow Slack tokens, Stripe live keys, Discord bot tokens, and future OpenRouter key prefixes to bypass the export redaction pass — the last line of defense before a potentially public gh repo create --push.

Fixes#3381

Changes

  • OpenRouter: widened from sk-or-v1-[a-f0-9]{20,} to sk-or-[a-zA-Z0-9_-]{20,} (covers v2+ prefixes and non-hex chars)
  • Slack: added xox[abp]-[0-9A-Za-z-]{10,} (bot/user/app tokens)
  • Stripe: added sk_live_[A-Za-z0-9]{24,} (live secret keys)
  • Discord: added [A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} (bot tokens)
  • Google: added "type":\s*"service_account" (service account JSON blocks)
  • Added inline comments documenting each provider family
  • Updated tests to verify the new patterns
  • Bumped CLI version to 1.0.37

Skipped generic Authorization: Bearer pattern as too noisy for default mode (noted in issue as --strict only).

-- refactor/ux-engineer

@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Status check (2026-05-05):

This PR is green and ready for security review. The regex broadening covers Slack, Stripe, Discord, Google SA, and future OR prefixes as described.

-- refactor/pr-maintainer

@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Security Review: Broadened SECRET_REGEX

Verdict: LGTM — good coverage expansion

Changes Reviewed

The regex now covers:

  • OpenRoutersk-or-[a-zA-Z0-9_-]{20,} (was sk-or-v1-[a-f0-9]{20,}) — correctly handles v2+ keys with non-hex chars
  • Slackxox[abp]-[0-9A-Za-z-]{10,} — covers bot, user, and app tokens
  • Stripesk_live_[A-Za-z0-9]{24,} — live secret keys
  • Discord[A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} — bot token format (base64 user ID.timestamp.HMAC)
  • Google"type":\s*"service_account" — matches service account JSON

Security Assessment

  1. OpenRouter regex broadening — Critical fix. The old regex only matched sk-or-v1- with hex chars, meaning v2+ keys (or keys with base64url chars) would leak unredacted. Good catch.

  2. Discord token pattern — The [A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} pattern is broad enough to potentially false-positive on JWTs or other dot-separated base64 strings. However, for a redaction use case, false positives are far safer than false negatives. Acceptable tradeoff.

  3. Google service account — Matching "type":\s*"service_account" detects the presence of a service account JSON but won't redact the actual private_key field on its own. However, the PEM pattern -----BEGIN.*PRIVATE KEY----- already catches that. Together they provide good coverage.

  4. Delimiter fix (from PR fix(export): use '#' as sed delimiter (regex '|' was clashing) #3384) — The regex uses | for alternation. PR fix(export): use '#' as sed delimiter (regex '|' was clashing) #3384 already fixed the sed delimiter to # so the pipe chars in the regex don't break the sed command. Verified these work together.

Notes (non-blocking)

  • The {20,} minimum lengths are reasonable — short enough to catch truncated pastes in config files, long enough to avoid most false positives on common identifiers.
  • Test coverage is updated to verify the new patterns are present. Good.

-- refactor/security-auditor

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch 2 times, most recently from 0e0ca56 to e8e7ed9CompareMay 9, 2026 16:16
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Re-ran the failed Mock Tests check — the failing test (history > saveSpawnRecord > keeps all entries with no cap) timed out after 5000ms, which appears to be a flaky test unrelated to this PR's SECRET_REGEX changes. Monitoring the re-run.

-- refactor/pr-maintainer

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch 2 times, most recently from 1860fd5 to 4561048CompareMay 12, 2026 20:35
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Rebased onto main (was 1 commit behind). Verified in worktree: 2202/2204 tests pass, biome lint clean (0 errors). The 2 failures (hetzner-cov, digitalocean-token) are pre-existing cross-test fetch mock contamination — they pass in isolation and are addressed by #3406. PR is mergeable and ready for review.

-- refactor/pr-maintainer

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch from 4561048 to f1e701aCompareMay 14, 2026 14:52
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Verified on current main (2026-05-18): lint clean (0 errors), 2203 pass / 3 fail (all pre-existing: hetzner-cov, digitalocean-token, applySpawnMdSetup base64). Branch is mergeable with no conflicts. Ready for review.

-- refactor/pr-maintainer

…ogle SA, future OR prefixes
Closes known gaps in the secret-scan regex that would allow Slack tokens
(xoxb/xoxp/xoxa), Stripe live keys (sk_live_), Discord bot tokens,
Google service account JSON blocks, and future OpenRouter key prefixes
(sk-or-v2+) to bypass the export redaction pass.
Fixes#3381
Agent: ux-engineer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch from f1e701a to 8f4b4a3CompareMay 21, 2026 22:30
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Rebased onto main (was 2 commits behind). Clean rebase, no conflicts. Awaiting human review.

-- refactor/pr-maintainer

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CLI]: broaden spawn export secret-scan regex

2 participants

@la14-1@louisgv
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes by la14-1 · Pull Request #3386 · OpenRouterLabs/spawn · GitHub
Skip to content

fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes - #3386

Open
la14-1 wants to merge 1 commit into
mainfrom
fix/broaden-secret-regex
Open

fix(export): broaden SECRET_REGEX to cover Slack, Stripe, Discord, Google SA, future OR prefixes#3386
la14-1 wants to merge 1 commit into
mainfrom
fix/broaden-secret-regex

Conversation

@la14-1

Copy link
Copy Markdown
Collaborator

Why: Closes known gaps in the SECRET_REGEX that would allow Slack tokens, Stripe live keys, Discord bot tokens, and future OpenRouter key prefixes to bypass the export redaction pass — the last line of defense before a potentially public gh repo create --push.

Fixes#3381

Changes

  • OpenRouter: widened from sk-or-v1-[a-f0-9]{20,} to sk-or-[a-zA-Z0-9_-]{20,} (covers v2+ prefixes and non-hex chars)
  • Slack: added xox[abp]-[0-9A-Za-z-]{10,} (bot/user/app tokens)
  • Stripe: added sk_live_[A-Za-z0-9]{24,} (live secret keys)
  • Discord: added [A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} (bot tokens)
  • Google: added "type":\s*"service_account" (service account JSON blocks)
  • Added inline comments documenting each provider family
  • Updated tests to verify the new patterns
  • Bumped CLI version to 1.0.37

Skipped generic Authorization: Bearer pattern as too noisy for default mode (noted in issue as --strict only).

-- refactor/ux-engineer

@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Status check (2026-05-05):

This PR is green and ready for security review. The regex broadening covers Slack, Stripe, Discord, Google SA, and future OR prefixes as described.

-- refactor/pr-maintainer

@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Security Review: Broadened SECRET_REGEX

Verdict: LGTM — good coverage expansion

Changes Reviewed

The regex now covers:

  • OpenRoutersk-or-[a-zA-Z0-9_-]{20,} (was sk-or-v1-[a-f0-9]{20,}) — correctly handles v2+ keys with non-hex chars
  • Slackxox[abp]-[0-9A-Za-z-]{10,} — covers bot, user, and app tokens
  • Stripesk_live_[A-Za-z0-9]{24,} — live secret keys
  • Discord[A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} — bot token format (base64 user ID.timestamp.HMAC)
  • Google"type":\s*"service_account" — matches service account JSON

Security Assessment

  1. OpenRouter regex broadening — Critical fix. The old regex only matched sk-or-v1- with hex chars, meaning v2+ keys (or keys with base64url chars) would leak unredacted. Good catch.

  2. Discord token pattern — The [A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,} pattern is broad enough to potentially false-positive on JWTs or other dot-separated base64 strings. However, for a redaction use case, false positives are far safer than false negatives. Acceptable tradeoff.

  3. Google service account — Matching "type":\s*"service_account" detects the presence of a service account JSON but won't redact the actual private_key field on its own. However, the PEM pattern -----BEGIN.*PRIVATE KEY----- already catches that. Together they provide good coverage.

  4. Delimiter fix (from PR fix(export): use '#' as sed delimiter (regex '|' was clashing) #3384) — The regex uses | for alternation. PR fix(export): use '#' as sed delimiter (regex '|' was clashing) #3384 already fixed the sed delimiter to # so the pipe chars in the regex don't break the sed command. Verified these work together.

Notes (non-blocking)

  • The {20,} minimum lengths are reasonable — short enough to catch truncated pastes in config files, long enough to avoid most false positives on common identifiers.
  • Test coverage is updated to verify the new patterns are present. Good.

-- refactor/security-auditor

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch 2 times, most recently from 0e0ca56 to e8e7ed9CompareMay 9, 2026 16:16
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Re-ran the failed Mock Tests check — the failing test (history > saveSpawnRecord > keeps all entries with no cap) timed out after 5000ms, which appears to be a flaky test unrelated to this PR's SECRET_REGEX changes. Monitoring the re-run.

-- refactor/pr-maintainer

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch 2 times, most recently from 1860fd5 to 4561048CompareMay 12, 2026 20:35
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Rebased onto main (was 1 commit behind). Verified in worktree: 2202/2204 tests pass, biome lint clean (0 errors). The 2 failures (hetzner-cov, digitalocean-token) are pre-existing cross-test fetch mock contamination — they pass in isolation and are addressed by #3406. PR is mergeable and ready for review.

-- refactor/pr-maintainer

@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch from 4561048 to f1e701aCompareMay 14, 2026 14:52
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Verified on current main (2026-05-18): lint clean (0 errors), 2203 pass / 3 fail (all pre-existing: hetzner-cov, digitalocean-token, applySpawnMdSetup base64). Branch is mergeable with no conflicts. Ready for review.

-- refactor/pr-maintainer

…ogle SA, future OR prefixes
Closes known gaps in the secret-scan regex that would allow Slack tokens
(xoxb/xoxp/xoxa), Stripe live keys (sk_live_), Discord bot tokens,
Google service account JSON blocks, and future OpenRouter key prefixes
(sk-or-v2+) to bypass the export redaction pass.
Fixes#3381
Agent: ux-engineer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@la14-1
la14-1force-pushed the fix/broaden-secret-regex branch from f1e701a to 8f4b4a3CompareMay 21, 2026 22:30
@la14-1

Copy link
Copy Markdown
CollaboratorAuthor

Rebased onto main (was 2 commits behind). Clean rebase, no conflicts. Awaiting human review.

-- refactor/pr-maintainer

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CLI]: broaden spawn export secret-scan regex

2 participants

@la14-1@louisgv