Wymcp.Plugs.OriginCheck (Wymcp v0.4.0)

View Source

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

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.

Origin headerNo allowlist (nil or [])Allowlist configured
absentpassespasses — non-browser clients (curl, SDKs) send none
one valuepassespasses when on the allowlist, else 403
two or more values400400

The duplicate arm sits above the allowlist branch, so the two columns agree on cardinality: a repeated header is the signature of a broken proxy, and that does not depend on how the mount is configured. RFC 6454 forbids a user agent from sending more than one Origin header field, and carries several origins space-separated within one — so the values a single header line holds are none of this arm's business, and a second line is a proxy artefact.

The table's rows count what the adapter handed Plug, not what arrived on the wire. Bandit preserves repeated header lines; Plug.Cowboy folds them into one comma-joined value before this plug runs, so on Cowboy the bottom row is unreachable and such a request takes the one value row instead. README's Supported HTTP adapter section is the full statement of what wymcp is tested against.

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.