fix(api): Origin-Guard — Browser erreichen nur POST /speak von gelisteten Origins
CORS allein verhindert nur das Lesen der Antwort, nicht die Wirkung: Ein POST mit text/plain-Body oder ein Formular-POST geht ohne Preflight raus, und talkd hat den Body trotzdem als JSON gelesen bzw. /mute, /cancel und /mcp ohne Body ausgeführt. Jede Webseite konnte so sprechen, muten und abbrechen. Neue Middleware vor dem Router: Anfragen mit Origin-Header kommen nur als OPTIONS /speak (Preflight, ohne Wirkung) oder POST /speak von gelisteter Origin durch; alles andere ist 403, bevor ein Body gelesen wird. CLI, curl und MCP-Clients senden keinen Origin und sind nicht betroffen. Prozesstests angepasst (ungelistete Origin auf /speak → 403, Steuer- Endpunkte aus dem Browser → 403) und TestBrowserKannNichtSteuern ergänzt, der den Angriff mit simple requests durchspielt und prüft, dass weder Provider noch Mute-State berührt werden. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
8909f37802
commit
46bd507fd8
4 files changed
+132
-20
No files matched your search
@@ -126,8 +126,17 @@ allowed_origins = ["https://chat.az-gruppe.com"] # Env TALK_ALLOWED_ORIGINS
|
||||
`Access-Control-Allow-Origin` (die Origin bzw. `*`), `-Methods: POST,
|
||||
OPTIONS`, `-Headers: Content-Type`, `Max-Age: 600`.
|
||||
- Echter `POST /speak` mit gelisteter `Origin` trägt denselben ACAO-Header.
|
||||
- Ungelistete Origins bekommen saubere `204`/`202` **ohne** CORS-Header —
|
||||
die Blockade macht der Browser.
|
||||
- **Die Tür ist serverseitig zu, nicht nur browserseitig.** CORS allein
|
||||
verhindert nur das *Lesen* der Antwort; einen POST mit `text/plain`-Body
|
||||
oder einen Formular-POST schickt jede Webseite ohne Preflight ab. Deshalb
|
||||
lehnt talkd jede Anfrage mit fremdem `Origin`-Header mit `403` ab, die
|
||||
nicht POST /speak von einer gelisteten Origin ist — also ungelistete
|
||||
Origins auf /speak, jeden Browser-Zugriff auf `/status`, `/mute`,
|
||||
`/unmute`, `/cancel` und `/mcp`, auch von gelisteten Origins. Nur der
|
||||
Preflight `OPTIONS /speak` bleibt für ungelistete Origins ein `204` ohne
|
||||
CORS-Header (ohne Wirkung; der Browser verwirft den geplanten POST).
|
||||
CLI, curl und MCP-Clients senden keinen `Origin`-Header und sind nicht
|
||||
betroffen.
|
||||
|
||||
**MCP** (`POST /mcp`, Streamable HTTP): schlanke eigene Implementierung
|
||||
des JSON-RPC-Subsets ohne SDK — `initialize` (angefragte
|
||||
|
||||
Reference in new issue
Block a user