Summary
Adversarial test sweep of the auth module found several confirmed security gaps where code behavior is currently correct but untested, and regressions would not be caught.
Census
- Auth
.mts files: 53 tests pass, 0 skip/fail
server/__tests__/gateway-user-key-apiaccess.test.ts: 10 pass, 0 skip/fail
- API core (
_api-key.js, _session.js, _user-api-key.js): 122 pass, 0 skip/fail
- MCP/OAuth surfaces: 144 pass, 1 suite skipped (
LIVE_API_CACHE_TESTS gate)
Confirmed gaps
High
- Resource exhaustion / DoS —
server/auth-session.ts:81-98
- Clerk plan fallback has no
AbortSignal/timeout.
- Temporary test with a valid no-plan JWT + never-settling Clerk fetch remained pending past 250ms.
- An authenticated user with a standard no-plan session can pin gateway invocations when Clerk stalls.
- State corruption / EoP —
server/_shared/user-api-key.ts:61-73
- Cache/Convex result is cast without runtime shape validation.
- A mocked validator returning truthy
{} produced HTTP 200 instead of expected 401.
- Malformed-key amplification —
server/_shared/user-api-key.ts:34-46
- Accepts any
wm_ prefix; wm_x reached SHA-256/cache/backend although the real contract is wm_ + 40 hex.
- MCP entitlement predicates individually unguarded —
api/mcp/auth.ts:315-319
- Enforces
tier>=1, mcpAccess===true, validUntil>=now.
- Tests use one fixture violating all three; removing any single predicate leaves 144/144 green.
- Live auth/cache suite never executes in CI —
tests/live-api-cache-auth-regression.test.mjs:77
- Whole describe skipped unless
LIVE_API_CACHE_TESTS=1; CI does not set it.
- Mutation proof: unconditional throw at top of skipped describe still exited 0.
- Authenticated MCP case at line 260 additionally requires
WM_LIVE_TEST_KEY.
Medium
- Empty cached
userId accepted — api/_user-api-key.js:215-218
- User-key request coalescing removal unguarded —
api/_user-api-key.js:118-129,203-210 (DoS amplification)
- Convex
AbortSignal timeout in user-key path not asserted — api/_user-api-key.js:174-190
- MCP authenticated per-minute limiter not exercised —
api/mcp/auth.ts:370-400
- MCP anonymous discovery limiter not exercised —
api/mcp/auth.ts:410-417
- Meta-test gap: secret-compare regex misses identifiers like
probeSecret !== expectedSecret — tests/no-non-timing-safe-secret-compare.test.mts:29-32,70-73
Design risk
server/__tests__/gateway-user-key-apiaccess.test.ts:210-218 deliberately enforces entitlement-null fail-open; a lapsed user who can induce or await that failure regains paid access.
Suggested fix
- Add timeouts/AbortSignal to external auth lookups.
- Validate
user-api-key cache/Convex result shape before trusting it.
- Enforce the
wm_[0-9a-f]{40} contract before hashing/backend calls.
- Split MCP entitlement fixtures so each predicate is individually tested.
- Decide whether the entitlement-null fail-open posture is acceptable and test/document the choice.
- Either provide CI secrets for the live auth/cache suite or replace it with recorded/mocked regression tests.
Summary
Adversarial test sweep of the auth module found several confirmed security gaps where code behavior is currently correct but untested, and regressions would not be caught.
Census
.mtsfiles: 53 tests pass, 0 skip/failserver/__tests__/gateway-user-key-apiaccess.test.ts: 10 pass, 0 skip/fail_api-key.js,_session.js,_user-api-key.js): 122 pass, 0 skip/failLIVE_API_CACHE_TESTSgate)Confirmed gaps
High
server/auth-session.ts:81-98AbortSignal/timeout.server/_shared/user-api-key.ts:61-73{}produced HTTP 200 instead of expected 401.server/_shared/user-api-key.ts:34-46wm_prefix;wm_xreached SHA-256/cache/backend although the real contract iswm_+ 40 hex.api/mcp/auth.ts:315-319tier>=1,mcpAccess===true,validUntil>=now.tests/live-api-cache-auth-regression.test.mjs:77LIVE_API_CACHE_TESTS=1; CI does not set it.WM_LIVE_TEST_KEY.Medium
userIdaccepted —api/_user-api-key.js:215-218api/_user-api-key.js:118-129,203-210(DoS amplification)AbortSignaltimeout in user-key path not asserted —api/_user-api-key.js:174-190api/mcp/auth.ts:370-400api/mcp/auth.ts:410-417probeSecret !== expectedSecret—tests/no-non-timing-safe-secret-compare.test.mts:29-32,70-73Design risk
server/__tests__/gateway-user-key-apiaccess.test.ts:210-218deliberately enforces entitlement-null fail-open; a lapsed user who can induce or await that failure regains paid access.Suggested fix
user-api-keycache/Convex result shape before trusting it.wm_[0-9a-f]{40}contract before hashing/backend calls.