Study/audit-results/UNVERIFIED_RISKS.md

4.7 KiB

Unverified Risks

Risks that could not be fully confirmed within audit constraints (need a browser, a container run, a live deployment, or timing-dependent reproduction). All are code-verified as plausible; the missing piece is runtime confirmation.

ID Title Why unverified Suggested verification
FIN-02 Hardcoded fallback SESSION_SECRET → session forgery Code path fully traced (seal/verify semantics verified in iron-session), but no live production deployment exists here to demonstrate an actual forged-cookie login Boot production build without SESSION_SECRET, forge a cookie with the fallback password (iron-webcrypto seal script), assert full access; then with a real secret assert rejection
FIN-06 No .dockerignore → win32 modules in Linux image Mechanics verified (PE32+ DLL present in local node_modules; Dockerfile COPY order), exact failure mode (build error vs ERR_DLOPEN_FAILED) not observed Run docker build . on this Windows host; inspect better_sqlite3.node/argon2 prebuilds in the image (must be ELF)
FIN-13 Progress PATCH-after-DELETE race Timing-dependent; needs throttled network DevTools throttling: submit final answer + Finish immediately; inspect StudyProgress after
FIN-14 Out-of-order progress PATCHes Timing-dependent DevTools throttling with rapid grading; reload and compare resume point/results
FIN-22 Entrypoint migrate crash loop / runner CLI install Requires container build + run on node:22-slim (docker CLI unavailable in audit environment) docker build + fresh-volume run (assert 200 + _prisma_migrations); corrupt-volume run (assert actionable failure, not silent loop)
FIN-24 Healthcheck/backup gaps Behavior observable only in a real container run Compose up with a corrupt volume; observe restart loop and absence of health status
FIN-32 Group-delete sortOrder duplicates Deterministic from code; visual impact needs a browser Delete a group in the app, inspect Uncategorized order + DB sortOrders
FIN-33 Keyboard cross-group moves impossible Deterministic from code (empty handleDragOver), needs manual keyboard test Tab to a drag handle, attempt keyboard cross-group move
FIN-34 Restart DELETE race Timing-dependent Throttled network: Restart, grade first card, inspect progress row
FIN-36 Previous-card animation race Timing-dependent (350 ms window) Grade then immediately click Previous; observe index jump
FIN-37 SRS page stale on focus Deterministic from code; browser needed to observe Two tabs: delete deck in one, focus the other
FIN-39 Proxy destroy cookie lost on redirect Deterministic from code; browser needed to observe Set-Cookie Stale-generation cookie → follow redirect → inspect response headers
FIN-40 Secure cookie flag off Deterministic from code (flag logic); deployment-dependent Inspect Set-Cookie in a production container
FIN-46 Cross-class fetch race Timing-dependent Throttled network + fast class switching
FIN-48 Empty slug / stale slug on rename Deterministic from code (slugify verified); UI behavior needs browser Create class named "!!!", try to navigate to it; rename a class, check old URL
FIN-49 Shared-viewer localStorage key collisions Code-verified key construction; symptom needs browser Open two share tokens for the same content, answer in one, reload the other
FIN-51 Collapsed-groups expand flash Cosmetic; browser-only Visit library with saved collapsed state

Items verified safe (hypotheses disproven — recorded for completeness)

  • SQLite relative-path split-brain between Prisma CLI and app (both cwd-relative → same dev.db; Docker uses absolute path) — verified safe.
  • Foreign-key enforcement (better-sqlite3 compiled with SQLITE_DEFAULT_FOREIGN_KEYS=1) — cascades/SetNull fire; verified safe.
  • Transactionality of deck/quiz/attempt/reorder writes — nested creates + $transaction; verified safe.
  • StudyProgress/ShareLink NULL-uniqueness — service-level guards prevent duplicates via app paths; only direct API misuse (FIN-41/FIN-21) can create junk rows.
  • Client/server boundary violations — none found (no client import of @/lib/db/services/prisma).
  • XSS via Markdown — react-markdown without rehype-raw; no dangerouslySetInnerHTML on user data; verified safe.
  • Password-reset nonce/token crypto (192-bit token, SHA-256 digest, timingSafeEqual, expiry) — sound; abuse vectors are FIN-10.
  • SRS optimistic concurrency (expectedStateVersion → 409, rollback via refetch) — correct.
  • Migrations are purely additive; no NOT NULL-without-default, no DROP — safe on populated migration-tracked DBs (except FIN-01 drift).