6.9 KiB
Balanced Probe Summary: Kordant web/
Status: complete
Phase: L4 (Lite Probe)
Date: 2026-05-28
Commit: 26d9f8b050
Probe Execution
Scope
The L4 probe focused on the web/ directory of the Kordant monorepo — the primary web application built on SolidStart + tRPC + Drizzle ORM. The probe examined 16 tRPC routers, the Stripe webhook handler, WebSocket server, voiceprint audio pipeline, darkwatch external API scanner, report generator (Puppeteer), and middleware pipeline.
Knowledge Base Integration
The Phase 3 knowledge base was used to identify highest-impact attack surface slices:
- Stripe Webhook Processing (DFD-5, TB-3) — CRITICAL in KB, verified as MEDIUM in this probe
- tRPC → Drizzle ORM (DFD-1, TB-2) — CVE-2026-39356 in KB, verified as currently safe but with latent risks
- VoicePrint Audio Pipeline (DFD-2, TB-9) — CRITICAL in KB, verified as MEDIUM
- WebSocket (DFD-4, TB-5) — HIGH in KB, verified as MEDIUM
- Browser Extension (DFD-3, TB-6) — CRITICAL in KB, but KB correctly identified server does NOT use superjson
Files Analyzed
- 25+ source files read in full or partial
- 4 router files (admin, billing, extension, voiceprint)
- 3 service files (billing, voiceprint, darkwatch)
- 3 core infrastructure files (middleware, websocket, ratelimit)
- 6 schema files (billing, voiceprint, extension, darkwatch, reports, user)
- 1 generator file (reports/generator.ts)
- 1 JWT auth file
Hypothesis Generation
12 hypotheses were generated covering:
- Stripe webhook replay and type coercion
- Return URL open redirect
- VoicePrint resource exhaustion
- WebSocket JWT leakage
- Admin role unrestricted values
- Extension no-op endpoints
- SQL injection vectors (blog router
sql<>tags) - Rate limit bypass
- Puppeteer SSRF
- Watchlist item type injection
Hypothesis Verification
Each hypothesis was verified against actual code with file:line evidence. 7 findings were written as drafts; 5 were rejected as SAFE or LOW-IMPACT.
Findings Summary
| Draft ID | Title | Severity | Status |
|---|---|---|---|
| L4-001 | Stripe Webhook Replay → Partial Duplicate Subscription Protection | MEDIUM | VALIDATED |
| L4-002 | Return URL Open Redirect via Stripe Checkout | MEDIUM | VALIDATED |
| L4-003 | VoicePrint Resource Exhaustion via Unbounded Audio Upload | MEDIUM | VALIDATED |
| L4-004 | WebSocket JWT Leakage via Query Parameter | MEDIUM | VALIDATED |
| L4-005 | Webhook Type Coercion → Data Corruption | MEDIUM | VALIDATED |
| L4-006 | Admin userUpdateRole — Unrestricted Role Value |
LOW | VALIDATED |
| L4-007 | Public Extension Endpoints — No-Op and Unbounded Input | LOW | VALIDATED |
Rejected Hypotheses (SAFE or LOW-IMPACT)
- SQL injection via blog router
sql<>tag: SAFE — Drizzle parameterizes values insql<>template tags - Puppeteer SSRF via
page.setContent: LOW —setContentloads HTML as document, no external navigation;--no-sandboxweakens isolation but HTML is generated server-side - Admin role escalation via SQL injection: NOT FOUND — no SQL injection vector exists in admin procedures
- Rate limit bypass via path heuristic: NOT A VULNERABILITY — the heuristic is over-protective (flags legitimate sensitive paths)
- Watchlist item type injection: SAFE —
picklist()validates type, and scan engine usesencodeURIComponent
Coverage Summary
Entry Points Covered
| Entry Point | Covered? | Finding IDs |
|---|---|---|
Stripe webhook (/api/stripe/webhook) |
YES | L4-001, L4-005 |
| Billing tRPC procedures | YES | L4-002 |
| VoicePrint tRPC procedures | YES | L4-003 |
WebSocket (ws://:3001) |
YES | L4-004 |
| Extension public procedures | YES | L4-007 |
| Admin procedures | YES | L4-006 |
| Blog public procedures | YES (verified safe) | — |
| DarkWatch tRPC procedures | PARTIAL | — |
| Reports tRPC procedures | PARTIAL | — |
| User procedures | PARTIAL | — |
| Middleware (CORS, CSP, Clerk) | PARTIAL | — |
| Rate limiting | YES | — |
Trust Boundary Crossings Analyzed
| Boundary | File | Findings |
|---|---|---|
| TB-1: Internet → Web (tRPC) | middleware.ts, utils.ts |
L4-002, L4-006, L4-007 |
| TB-3: tRPC → Stripe | billing.service.ts |
L4-001, L4-005 |
| TB-5: WebSocket → ws | websocket.ts |
L4-004 |
| TB-9: tRPC → VoicePrint Storage | voiceprint.service.ts |
L4-003 |
Uncovered Areas
- DarkWatch scan engine: External API calls (HIBP, SecurityTrails, Censys, Shodan) were read but no vulnerabilities were found — all use
encodeURIComponentand circuit breakers - Report generation (Puppeteer):
page.setContentwas analyzed — HTML is server-generated, not user-controlled - Middleware pipeline: CORS and CSP were analyzed — CSP has
'unsafe-inline'and'unsafe-eval'which are known weaknesses but not exploitable without XSS - Drizzle ORM SQL injection: All
sql<>usages were verified as safe (Drizzle parameterizes values) - Clerk auth integration: Clerk handles auth — no vulnerabilities in the integration layer
Risk Assessment
Overall Risk: MEDIUM
The Kordant web application has a well-structured security model with Clerk-based authentication, tRPC procedure type enforcement, and rate limiting. However, several areas need attention:
High-priority fixes (MEDIUM severity):
- Add event ID deduplication to Stripe webhook handler
- Validate
returnUrlagainst an allowlist - Add maximum audio size limits to VoicePrint endpoints
- Move WebSocket JWT from query parameter to header
- Replace type coercion in webhook handler with proper type guards
Low-priority fixes (LOW severity):
- Add role validation to
userUpdateRole - Add length limits to extension public endpoints
- Implement or remove the no-op
reportPhishingendpoint
Dependencies with Known CVEs
- drizzle-orm 0.45.2: CVE-2026-39356 (SQL injection) — not currently exploitable in this codebase (all
sql<>tags use parameterized values) - ws 8.21.0: CVE-2026-45736, CVE-2024-37890 — WebSocket server uses
ws, but the vulnerabilities require specific attack conditions - valibot 0.29.0: CVE-2025-66020 (ReDoS) — emoji validation regex vulnerable, but no emoji-specific schemas found
- superjson 2.2.1 (browser extension): CVE-2022-23631 — prototype pollution, but server does NOT use superjson
Next Steps for Deeper Phases
- L5/L6: Test Stripe webhook replay with actual Stripe test API
- L5/L6: Verify WebSocket JWT leakage by checking actual log configurations
- L5/L6: Load test VoicePrint endpoints with large payloads
- L6: Audit CSP effectiveness —
'unsafe-inline'and'unsafe-eval'weaken XSS protection - L7: Supply chain analysis of npm dependencies
- L8: Native app security (iOS/Android) — separate codebases
- L9: Infrastructure and deployment security