Wymcp.Plugs.OriginCheck (Wymcp v0.1.1)

View Source

The origin check (docs/glossary.md, wire check): DNS-rebinding protection for browser-based clients. Reads the router's :origin allowlist and rejects a request whose Origin header is not on it.

This is the first of the three wire checks on every non-fallthrough route — the ordering is Wymcp.Router's wire-check invariant. It runs before anything has validated Origin, which is exactly why this plug carries its own duplicate arm instead of leaving cardinality to Wymcp.Plugs.SingletonHeaders.

With an allowlist configured:

Origin headerAnswer
absentpasses — non-browser clients (curl, SDKs) send none
one value, on the allowlistpasses
one value, not on the allowlist403
two or more values400

With no allowlist (nil or []) the plug returns immediately, so a duplicated Origin is not rejected at all. Origin is therefore the one singleton header whose cardinality goes unenforced in the default configuration — acceptable because nothing downstream reads it, and with no allowlist there is no rebinding protection to weaken.

The rejection speaks the route's error dialect, taken from the :error_dialect init option: the JSON-RPC dialect on POST, the plain-JSON dialect on GET and DELETE. Its envelope id is always nil, and structurally so — this plug runs ahead of both body parsing and Wymcp.Plugs.Classify, so Wymcp.Response.rejection_id/1 has no message kind to read even when the body does carry an id. The nil is not a judgement about the message kind.