Files
Kordant/piolium/attack-surface/balanced-chamber-summary.md
2026-05-29 09:03:47 -04:00

7.2 KiB

Balanced Chamber Summary — Kordant Security Audit

Phase: L5 (Single Review Chamber + FP Check)
Date: 2026-05-28
Target: Kordant monorepo (SolidStart + tRPC + Drizzle ORM + Stripe + WebSocket + Browser Extension)
Status: CLOSED


Executive Summary

19 draft findings were evaluated (12 from p4 SAST phase, 7 from l4 probe phase). After ideological challenge, false-positive elimination, and duplicate consolidation:

  • Valid findings promoted to p8: 11
  • Rejected (false positive): 1
  • Rejected (low severity): 3
  • Rejected (duplicate): 4

The 11 surviving findings cover XSS, SSRF, open redirect, rate limit bypass, CORS misconfiguration, webhook type safety, webhook replay, WebSocket authentication weaknesses, resource exhaustion, and vulnerable dependency usage.


Finding Verdict Table

# Source ID Slug Verdict Severity p8 Draft
1 p4-004 xss-in-innerhtml VALID HIGH p8-001-xss-in-innerhtml.md
2 p4-002 puppeteer-ssrf VALID MEDIUM p8-002-puppeteer-ssrf.md
3 p4-010 open-redirect-return-url VALID MEDIUM p8-003-open-redirect-return-url.md
4 p4-009 rate-limit-substring-bypass VALID MEDIUM p8-004-rate-limit-substring-bypass.md
5 p4-003 cors-origin-env-var VALID MEDIUM p8-005-cors-origin-env-var.md
6 p4-006 webhook-type-coercion VALID MEDIUM p8-006-webhook-type-coercion.md
7 l4-001 webhook-replay VALID MEDIUM p8-007-webhook-replay.md
8 p4-007 websocket-jwt-query-param VALID MEDIUM p8-008-websocket-jwt-query-param.md
9 p4-011 websocket-no-origin-validation VALID MEDIUM p8-009-websocket-no-origin-validation.md
10 l4-003 voiceprint-resource-exhaustion VALID MEDIUM p8-010-voiceprint-resource-exhaustion.md
11 p4-008 superjson-vulnerable-version VALID MEDIUM p8-011-superjson-vulnerable-version.md

Rejected Findings

False Positive (1)

Source ID Slug Reason
p4-005 path-traversal-audio-storage userId comes from ctx.user.id (authenticated session), NOT user input — no path traversal vector exists

Low Severity (3)

Source ID Slug Reason
p4-001 unvalidated-role-mutation No current privilege escalation path; role check only looks for "admin"; setting role to non-admin strings grants no privileges
p4-012 admin-sql-pattern Latent risk only; current sql<> usage is safe (wraps count() aggregate); no active exploitation
l4-007 extension-noop-endpoints Rate-limited at 5/min; no data corruption or privilege escalation; resource waste only

Duplicate (4)

Source ID Slug Duplicate Of
l4-002 return-url-open-redirect-stripe p4-010 (open-redirect-return-url)
l4-004 websocket-jwt-leakage-query-param p4-007 (websocket-jwt-query-param)
l4-005 webhook-type-coercion-data-corruption p4-006 (webhook-type-coercion)
l4-006 admin-role-unrestricted-value p4-001 (unvalidated-role-mutation)

Severity Distribution

Severity Count Findings
HIGH 1 XSS via unsanitized innerHTML
MEDIUM 10 Puppeteer SSRF, Open redirect, Rate limit bypass, CORS origin, Webhook type coercion, Webhook replay, WebSocket JWT leak, WebSocket origin, VoicePrint exhaustion, Superjson CVE
LOW 0

Threat Cluster Coverage

DFD/CFD Slice Findings Notes
DFD-1: tRPC → Drizzle ORM 0 CVE-2026-39356 surface noted; no active injection found
DFD-2: VoicePrint Pipeline 2 p8-010 (resource exhaustion), p4-005 (FP)
DFD-3: Browser Ext → tRPC 1 p8-011 (superjson CVE)
DFD-4: WebSocket Alerts 2 p8-008 (JWT leak), p8-009 (no origin)
DFD-5: Stripe Webhook 2 p8-006 (type coercion), p8-007 (replay)
CFD-1: Auth Flow 2 p8-008 (JWT leak), p8-009 (no origin)
CFD-2: Authz Flow 0 p4-001 rejected (low severity)
CFD-3: Rate Limiting 1 p8-004 (bypass)
DFD-6: Puppeteer Reports 1 p8-002 (SSRF)
CFD-1 (CORS) 1 p8-005 (env var trust)

Attack Pattern Registry Updates

New Patterns Identified

Pattern ID Root Cause Detection Signature Severity
AP-001 Stored XSS via innerHTML + unsanitized markdown Grep: innerHTML=.*contentHtml + contentToHtml with raw concatenation HIGH
AP-002 Puppeteer SSRF via --no-sandbox + page.setContent() Grep: puppeteer.launch.*--no-sandbox + page.setContent MEDIUM
AP-003 Open redirect via unvalidated return URL Grep: return_url.*returnUrl + url() validator only MEDIUM
AP-004 Rate limit bypass via incomplete sensitive path list Grep: path.includes.*sensitivePaths MEDIUM
AP-005 CORS origin from unvalidated env var Grep: process.env.APP_URL.*allowedOrigins MEDIUM
AP-006 Webhook type coercion via chained as unknown as Grep: as unknown as Record<string, unknown> in billing MEDIUM
AP-007 Webhook replay via missing event ID deduplication Grep: handleWebhookEvent without event.id check MEDIUM
AP-008 JWT in WebSocket query parameter Grep: searchParams.get.*token in websocket handler MEDIUM
AP-009 WebSocket no Origin validation Grep: verifyClient missing in WebSocketServer config MEDIUM
AP-010 Unbounded input → resource exhaustion Grep: minLength(1) without maxLength in audio schemas MEDIUM
AP-011 Vulnerable dependency version (superjson) Grep: superjson.*\^2.2.1 in package.json MEDIUM

Variant Candidates (Not Promoted)

Candidate Reason
p4-005 (path traversal audio) FALSE POSITIVE — userId from ctx.user.id
p4-001 (unvalidated role) LOW severity — no current exploit
p4-012 (admin SQL pattern) LOW severity — latent risk only

Key Observations

  1. No remotely triggerable CRITICAL findings — All valid findings require some precondition (auth, admin access, log access, or env var injection). The highest severity is HIGH (stored XSS), which requires admin access for payload creation.

  2. WebSocket authentication is the weakest link — Two findings (p8-008, p8-009) show that the WebSocket server lacks both Origin validation and uses JWT in query parameters. Together, these create a complete authentication bypass chain.

  3. Stripe webhook handler has two independent issues — Type coercion (p8-006) and missing idempotency (p8-007) create a combined risk: a replayed forged webhook event can corrupt subscription data.

  4. Input validation gaps are systematic — Multiple findings (p8-004, p8-009, p8-010) point to a pattern of missing maximum-length constraints and incomplete validation in valibot schemas.

  5. No active SQL injection found — Despite the CVE-2026-39356 surface, no actively exploitable SQL injection was found in the current codebase. The sql<> tag usage in admin.ts is safe.


Chamber Closure

Findings written: 11
Patterns added to registry: 11
Variant candidates: 3

Chamber closed: 2026-05-28T13:00:00Z