← back to Codex Review 2026 04 30

consensus/trademarks-copyright.md

50 lines

# Consensus — trademarks-copyright
Generated 2026-04-30T23:48:03-07:00. Source: codex review/fix/rereview/round-2 artifacts (round-3 was quota-blocked).

## Codex pass-1 review (top risks)
## Top Risks (P0 — fix this week)
- `package.json:18`, `src/middleware.ts:14`: Next `15.0.3` is vulnerable to middleware auth bypass; admin auth relies on middleware. Upgrade to `15.2.3+` or block `x-middleware-subrequest` at the edge. citeturn0search4
- `src/app/api/drops/send/route.ts:15`, `src/app/api/drops/compose/route.ts:8`, `src/app/api/score/route.ts:9`, `src/app/api/brands/hunt/route.ts:12`: public mutation routes can send newsletters, compose drops, rescore DB, and run crawler/LLM jobs. Put all operational routes behind server-side auth, not only middleware path matching.
- `src/app/api/drops/drop-items/[id]/route.ts:8`: public PATCH edits newsletter content/CTA URLs. Move under `/api/drops/admin/*` or enforce auth inside the handler.
- `src/app/api/drops/checkout/route.ts:23`: if Stripe is unset, any caller can set any subscriber email to paid tier at lines `24-30`. Remove dev fallback outside `NODE_ENV !== "production"` and require subscriber token/session.
- `.env.local:30`, `.env.local:47-48`: plaintext admin token and Basic auth credential, including raw password comment, sit in project dir. Rotate both; store outside repo/workspace backups.
- `src/app/api/drops/cron/route.ts:15`: cron route is open if `CRON_TOKEN` is unset; `.env.local:25` uses `change-me-before-public`. Fail closed when missing and rotate token.


## Round-1 applied
## Applied
- src/app/api/drops/cron/route.ts:14 — require `CRON_TOKEN` to be configured before accepting cron requests — prevents the reviewed fail-open cron path when the env secret is missing.
- src/app/api/drops/checkout/route.ts:7 — return 400 when the parsed JSON body is `null` or non-object — prevents malformed JSON values from becoming handler errors.
- src/app/api/drops/send/route.ts:17 — return 400 when the parsed JSON body is `null` or non-object — prevents malformed JSON values from becoming handler errors.
- src/app/api/drops/compose/route.ts:10 — return 400 when the parsed JSON body is `null` or non-object — prevents malformed JSON values from becoming handler errors.
- src/app/api/brands/hunt/route.ts:14 — return 400 when the parsed JSON body is `null` or non-object — prevents malformed JSON values from becoming handler errors.
- src/app/api/drops/drop-items/[id]/route.ts:17 — return 400 when the parsed JSON body is `null` or non-object — prevents malformed JSON values from becoming handler errors.
- src/app/api/drops/admin/subscribers/[id]/route.ts:13 — return 400 when the parsed JSON body is `null` or non-object — prevents malformed JSON values from becoming handler errors.


## Codex re-review verdict: FIX BEFORE SHIP

## New issues introduced
none observed.


## Round-2 applied
## Round 2 Applied
- src/app/api/swot/route.ts:10 — added a non-null object/array guard before reading `body.itemId` and `body.force` — fixes CODEX_REREVIEW.md missed call-site for JSON `null` reaching `body.itemId`.
- src/app/api/drops/signup/route.ts:10 — added a non-null object/array guard before reading `body.email`, `body.name`, and `body.ref` — fixes CODEX_REREVIEW.md missed call-site for JSON `null` reaching `body.email`.


## Still deferred for Steve
- P0 — package.json:18, src/middleware.ts:14 — vulnerable Next middleware auth bypass — deferred because package upgrades/edge blocking were outside the safe fix list.
- P0 — src/app/api/drops/send/route.ts:15, src/app/api/drops/compose/route.ts:8, src/app/api/score/route.ts:9, src/app/api/brands/hunt/route.ts:12 — public operational mutation routes — deferred because route auth design is broader than a surgical safe fix.
- P0 — src/app/api/drops/drop-items/[id]/route.ts:8 — public PATCH can edit newsletter content — deferred because moving/enforcing admin auth changes route structure and access policy.
- P0 — src/app/api/drops/checkout/route.ts:23 — Stripe-disabled checkout can directly upgrade subscribers — deferred because billing fallback/session policy needs owner decision.
- P0 — .env.local:30, .env.local:47-48 — plaintext admin/basic credentials — deferred because real secret rotation must be done by Steve; `.env.local` was left untouched.
- P0 — .env.local:25 — placeholder cron token — deferred because rotation of the real token must be done by Steve.
- P1 — src/app/api/drops/send/route.ts:43, src/app/api/drops/send/route.ts:85, src/lib/drops.ts:381 — transient email failures mark deliveries bounced — deferred because retry semantics/data handling are not in the safe list.
- P1 — src/lib/drops.ts:197, src/lib/drops.ts:233 — compose race without transaction/lock — deferred because transaction/locking behavior is beyond the approved safe fixes.
- P1 — src/app/api/drops/admin/subscribers/[id]/route.ts:18 — subscriber values are not enum/range validated — deferred because validation rules need owner-approved state constraints.
- P1 — src/lib/brandHunter.ts:283, src/app/api/brands/hunt/route.ts:18 — caller controls seeds/cap — deferred because auth/resource policy changes are broader than the safe body guard applied.
- P1 — src/lib/email.ts:96 — file email fallback writes recipient HTML under `/tmp/drops` — deferred because production email-backend policy needs Steve.