Files
worldmonitor/todos/035-pending-p1-jwtverify-missing-algorithms-allowlist.md
Elie Habib 41d964265e fix(map): sanctions layer invisible on WebGL map (#2267)
* fix(health): extend EMPTY_DATA_OK_KEYS check to bootstrap loop

Greptile correctly identified the fix was a no-op: EMPTY_DATA_OK_KEYS was
only consulted in the STANDALONE_KEYS loop, not BOOTSTRAP_KEYS. All three
calendar keys are bootstrap keys, so critCount was still incremented.

Mirror the same seedStale branching already present in the standalone loop
into the bootstrap loop so EMPTY_DATA_OK members get OK/STALE_SEED instead
of EMPTY/EMPTY_DATA/critCount++.

* fix(map): implement sanctions choropleth layer in DeckGLMap

The sanctions layer toggle did nothing on the WebGL map — DeckGLMap had
no rendering logic, only a help text label. Only Map.ts (2D SVG) had the
updateCountryFills() implementation.

Add createSanctionsChoroplethLayer() as a GeoJsonLayer using
SANCTIONED_COUNTRIES_ALPHA2 (new export) since countriesGeoJsonData keys
by ISO3166-1-Alpha-2, not the numeric IDs used by Map.ts/TopoJSON.
Wire it into the layer pipeline after the CII choropleth.

Alpha values match Map.ts: severe=89, high=64, moderate=51 (0-255).

* Revert "fix(health): extend EMPTY_DATA_OK_KEYS check to bootstrap loop"

This reverts commit cc1405f495.
2026-03-26 08:52:48 +04:00

1.7 KiB

status, priority, issue_id, tags, dependencies
status priority issue_id tags dependencies
pending p1 035
code-review
security
auth
clerk
jwt

Problem Statement

jwtVerify() in server/auth-session.ts has no algorithms allowlist. jose defaults to accepting whatever algorithm the token header declares. An attacker could present a token using alg: none or an unexpected signing algorithm to bypass signature verification.

Findings

  • File: server/auth-session.ts:43-46
  • jwtVerify(token, jwks, { issuer, audience }) — no algorithms field
  • Clerk issues RS256 tokens. This should be enforced explicitly.
  • Without algorithms: ['RS256'], a token declaring alg: HS256 or alg: none could be accepted by some jose versions or future updates.
  • One-line fix.

Proposed Solutions

Option A: Add algorithms: ['RS256'] (Recommended)

const { payload } = await jwtVerify(token, jwks, {
  issuer: CLERK_JWT_ISSUER_DOMAIN,
  audience: 'convex',
  algorithms: ['RS256'],
});
  • Pros: Correct. Enforces Clerk's actual signing algorithm. Cheap to verify.
  • Cons: None.
  • Effort: Small (1 line)
  • Risk: None

Option B: Add both RS256 and ES256 to handle future Clerk key rotation

  • Pros: Forward-compatible if Clerk switches algorithms.
  • Cons: Slightly wider allowlist.
  • Effort: Small
  • Risk: Low

Acceptance Criteria

  • jwtVerify call includes explicit algorithms allowlist
  • Test: token with alg: HS256 or unexpected algorithm is rejected
  • Existing auth-session tests continue to pass

Work Log

  • 2026-03-26: Identified during PR #1812 security audit (security-sentinel agent). File: server/auth-session.ts:43.