fix(server): inert proxy responses, API-call header, image-only uploads; origin check by host

From the final review: proxied archived HTML could run on our origin and read a
remembered token; /api/upload accepted any Wayback URL and GIF-prefixed bytes; the
origin check broke behind a TLS proxy; one unreadable snapshot could fail a run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Opus 5.5 committed 2026-10-15 01:49:52 +02:00
1 parent 5084f8c557
commit baa3476b73
16 files changed
+183 -26

No files matched your search

+18
View File
@@ -16,6 +16,24 @@ the repo every session — measurably slower and more tokens).
**Consequences:** Rule changes happen in one file; pointer files must stay thin. Plans are working
artefacts: kept after merge they go stale and contradict the code, so the spec is the record.
## 2026-10-15 — Harden the server proxy and uploads (final review)
**Status:** accepted (amends "Implementation details: server API" below)
**Context:** The whole-branch review found that `/api/fetch` passed the upstream content type through. Anyone can
archive an HTML page on Wayback and link a user to our `/api/fetch?url=…` for it: the script would run on our origin
and could read a MangaBaka token saved with "remember on this device". `/api/upload` also accepted any Wayback URL
and any bytes starting with `GIF`, so our domain could be used as a 30-day file drop and the store filled.
**Decision:**
- Proxied bodies are always `application/octet-stream` with `nosniff`, `Content-Security-Policy: sandbox;
default-src 'none'` and `Content-Disposition: attachment`. Nothing in our clients reads the content type.
- `/api/fetch` and `/api/upload` require the header `x-mbseed: 1`, which our page and userscript send and a link or
form cannot.
- `/api/upload` rehosts only from a source's image hosts (`Source.imageHosts`) or Wayback's copy of one, and only
images 1–10 000 px a side.
- The origin check compares hosts, so `https://host` passes behind a TLS proxy that Bun sees as `http://host`.
**Alternatives:** A session cookie or the password gate (deferred, spec §4.11); serving the page and the proxy on
different origins (more deployment work).
**Consequences:** A new source must list its image hosts. Clients other than ours must send `x-mbseed: 1`.
## 2026-10-14 — Implementation details: server API, Webtoons fetch forms
**Status:** accepted
**Context:** Decisions made while implementing plan 001 that the spec leaves open.