Skip to content

fix: patch multiple zero-day security vulnerabilities#1026

Open
ryokun6 wants to merge 1 commit intomainfrom
cursor/security-zero-day-fixes-8178
Open

fix: patch multiple zero-day security vulnerabilities#1026
ryokun6 wants to merge 1 commit intomainfrom
cursor/security-zero-day-fixes-8178

Conversation

@ryokun6
Copy link
Copy Markdown
Owner

@ryokun6 ryokun6 commented Mar 30, 2026

Security Audit & Fixes

Full security audit of the API surface uncovered 12 vulnerabilities across authentication, authorization, input validation, and network-layer protections. This PR fixes all of them.

Critical Fixes

Severity Vulnerability File(s) Fix
Critical Token verify cookie injection — attacker can set a cookie with a victim's username paired with their own token by sending only body.username without body.token, bypassing validation api/auth/token/verify.ts Always validate the username+token pair against Redis before setting the auth cookie
Critical Unauthenticated data destruction — clear-cached-data action on songs deletes translations/furigana/soramimi without any auth check api/songs/[id].ts Require authentication and canModifySong permission check
High Admin privilege squatting — username ryo (hardcoded admin) could be registered by any user on a fresh deployment api/auth/register.ts Reserve ryo, admin, system, moderator, mod from public registration
High Private room IDOR — handleGetRooms trusts unauthenticated ?username= query param to filter private rooms api/rooms/_helpers/_rooms.ts Use authenticated username instead of query parameter

Medium Fixes

Severity Vulnerability File(s) Fix
Medium Prototype pollution — client-supplied systemState spread with ... can inject __proto__/constructor keys api/chat.ts Filter dangerous keys before spreading
Medium Bulk messages missing access control — legacy handleGetBulkMessages skips private room membership check api/rooms/_helpers/_messages.ts Add room type + membership validation
Medium Password change with expired token — allowExpiredAuth: true lets stolen grace tokens set new passwords api/auth/password/set.ts Set allowExpiredAuth: false
Medium Unbounded applet content — no max size on shared applet content field enables Redis memory DoS api/share-applet.ts Cap at 512KB + field length limits
Medium Decompression bomb — gzip payloads in bulk song import have no output size limit api/songs/index.ts Add 5MB decompression limit
Medium Unbounded bulk import — no limit on songs array size api/songs/index.ts Cap at 500 items

Low / Hardening Fixes

Severity Vulnerability File(s) Fix
Low DNS rebinding TOCTOU — validate-then-fetch pattern allows DNS to change between check and connect api/_utils/_ssrf.ts Double-resolve and re-validate addresses before fetch
Low CORS wildcard + credentials footgun — API_ALLOWED_ORIGINS=* with credentials is insecure api/_utils/_cors.ts Add warning log; ensure reflect-origin mode (never literal *)
Low User enumeration via registration — distinct error for existing users api/auth/register.ts Unify error message
Low Missing member validation — private room member names not validated api/rooms/index.ts Validate with assertValidUsername

Testing

  • bun run build — clean compilation
  • bun run test:unit — all 130 tests pass (0 failures)
  • No behavioral changes to existing features; all fixes are defensive guards added to existing code paths
Open in Web Open in Cursor 

- Token verify: always validate username+token pair before setting cookie
  to prevent session confusion via mismatched credentials (CVE-class:
  broken authentication)

- Registration: reserve admin username 'ryo' and system names to prevent
  admin privilege squatting; improve error message to reduce user enumeration

- Songs clear-cached-data: require authentication and canModifySong check
  to prevent unauthenticated data destruction (CVE-class: broken access control)

- Chat systemState: strip __proto__/constructor/prototype keys from
  client-supplied objects to prevent prototype pollution

- Room listing (legacy handler): use authenticated username instead of
  unauthenticated query param for private room visibility (IDOR fix)

- Room creation: validate member usernames with assertValidUsername

- Bulk messages (legacy handler): add private room membership check

- Share applet: add max content size (512KB) and field length limits
  to prevent DoS via unbounded payloads

- Password set: disallow grace-period tokens for password changes

- CORS: add warning log for wildcard origin config; document that
  reflect-origin mode is used (never literal '*' with credentials)

- SSRF: add double-DNS-resolution defense against DNS rebinding attacks;
  re-validate resolved addresses before connecting

- Songs bulk import: cap array at 500 items; add 5MB decompression limit
  to prevent zip bomb DoS

Co-authored-by: Ryo Lu <me@ryo.lu>
@ryos-deploy
Copy link
Copy Markdown

ryos-deploy bot commented Mar 30, 2026

The preview deployment for ryos-dev is ready. 🟢

Open Preview | Open Build Logs | Open Application Logs

Last updated at: 2026-03-30 08:07:39 CET

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants