From dbc7b66a1bdd27b630fd53760126851bdf2073ad Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Fri, 24 Apr 2026 01:07:30 -0700 Subject: [PATCH] fix(brain-sync): secret scanner now catches Bearer-prefixed auth tokens in JSON MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bearer-token-json regex value charset was [A-Za-z0-9_./+=-]{16,}, which does NOT permit spaces. Real HTTP auth headers embed the scheme name with a literal space — "Bearer " — so the value portion actually starts with "Bearer " and the existing regex couldn't match. Result: any JSON blob containing "authorization":"Bearer ..." would slip past the scanner and sync to the user's private brain repo with the bearer token inline. Added optional (Bearer |Basic |Token )? prefix in front of the value charset. Now matches the common auth-scheme forms without broadening the matcher to tolerate arbitrary whitespace (which would false-positive on lots of benign JSON). Verified against 5 positive cases (bearer-in-json, clean bearer, apikey no-prefix, token with Bearer, password no-prefix) + 3 negative cases (too-short tokens, non-secret field names like username, random JSON). This closes the P0 security regression first noticed during v1.12.0.0 /ship. brain-sync.test.ts now passes all 7 secret-scan fixtures. Co-Authored-By: Claude Opus 4.7 (1M context) --- bin/gstack-brain-sync | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bin/gstack-brain-sync b/bin/gstack-brain-sync index 4adb330f..b0a1ff93 100755 --- a/bin/gstack-brain-sync +++ b/bin/gstack-brain-sync @@ -88,7 +88,12 @@ patterns = [ ('pem-block', re.compile(r'-----BEGIN [A-Z ]{3,}-----')), ('jwt', re.compile(r'\\beyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\b')), ('bearer-token-json', - re.compile(r'\"(authorization|api[_-]?key|apikey|token|secret|password)\"\\s*:\\s*\"[A-Za-z0-9_./+=-]{16,}\"', + # JSON-embedded auth headers. The optional Bearer/Basic/Token prefix + # matters: real auth values include a literal space after the scheme + # name, but the value charset below does not include spaces, so + # without the optional prefix every Bearer token in a JSON blob slips + # past the scanner. + re.compile(r'\"(authorization|api[_-]?key|apikey|token|secret|password)\"\\s*:\\s*\"(Bearer |Basic |Token )?[A-Za-z0-9_./+=-]{16,}\"', re.IGNORECASE)), ] text = sys.stdin.read()