Postmortem: Why Hardening One Code Path Does Not Harden All Code Paths
TLDR: A structured audit against 27 auth requirements found 7 real issues. None were catastrophic. Six of them shared one root cause: the primary implementation of each pattern had been hardened; the secondary, backup, or shared-component implementations of the same pattern had not. Auditing one path is not the same as auditing all paths.
The Assumption That Seemed Reasonable
When a security-sensitive code path is hardened, the hardening is applied to the primary implementation. The primary implementation is the one that was reviewed, tested, and fixed. Other implementations of the same pattern, such as backup proxies, shared components, and older copies, were written at a different time. They do not automatically inherit the fix.
This assumption is obvious when stated. It is not obvious while writing the code, because each fix feels complete when the primary path passes the check.
What the Audit Found
Finding 1: Polling secret in URL query parameter.
The primary poll proxy passed the authentication secret via Authorization: Bearer <secret> header. A secondary backup proxy, copied from an earlier draft, passed the same secret as ?secret=Y in the URL query string. URL query parameters appear in server access logs, CDN logs, and browser history. The secret was live in every poll request for the duration of each VS Code sign-in session.
The primary proxy was correct. The backup was not. The hardening of the primary did not update the backup.
Finding 2: Logout did not clear the server-side session cookie.
The sign-out function called the identity provider's sign-out and cleared localStorage. It did not call the server endpoint that sets Max-Age=0 on the HttpOnly session cookie. The cookie remained valid for up to one hour after the user clicked Sign Out.
HttpOnly cookies are invisible to JavaScript by design. That invisibility also means you cannot rely on client-side cleanup to expire them. The oversight: the client-side cleanup felt complete because localStorage was empty.
Finding 3: postMessage with wildcard target on 9 call sites.
Nine places in the codebase used window.parent.postMessage(payload, ''). None of the payloads contained credentials. The issue is that '' allows any cross-origin parent frame to receive the message. The primary shell-to-tool communication paths used window.location.origin. The gate scripts, bridge scripts, and fallback paths used '*'. Fix: replace all 9 with window.location.origin.
Finding 4: Session endpoint with no rate limiting.
The endpoint that sets the HttpOnly cookie from a provided access token had no per-IP protection. Added a KV-backed counter (10 requests per IP per minute).
Finding 5: HSTS header missing from session endpoint responses.
The Strict-Transport-Security header was present on HTML page responses but not on the edge function responses from the session endpoint.
Finding 6: Account enumeration via raw error messages.
Two auth surfaces rendered error.message from the identity provider directly. The provider returns different messages for "wrong password" versus "email not confirmed" versus "user not found." Normalize all sign-in errors to one message.
Finding 7: OAuth prompt parameter missing in the shared web component.
The primary modal and the standalone login page both had prompt: 'select_account' (Google) and prompt: 'login' (GitHub) on all OAuth calls. The shared web component version of the auth modal was written before the prompt fix and never updated. Three surfaces: two correct, one not.
What Was Actually Wrong
All seven findings shared the same structure: the primary implementation was correct; a secondary implementation, whether a backup, shared component, or older copy, was not.
The root cause is not carelessness. It is that security fixes applied to one implementation create a false sense of completeness. The fix is documented, the PR is merged, the review is done. The backup proxy file that was copied from an older draft still exists. The shared component that predates the fix still ships.
What Survived
PKCE on all OAuth flows, HttpOnly cookie pattern, OS keychain storage in the extension, AES-GCM token encryption for the VS Code handshake, redirect URI validation, BroadcastChannel cross-tab sync: all held up. The architecture was correct. The gaps were in the secondary implementations.
The Lesson
When you harden a security-sensitive pattern, grep the codebase for every implementation of that pattern before closing the task. "We fixed the main path" is not the same as "we fixed all paths." The audit found things that code review had not, because code review checked each file against itself, not each file against the checklist.