Harden operator-set target headers (closes #233) (#242)
All checks were successful
check / check (push) Successful in 2m58s
All checks were successful
check / check (push) Successful in 2m58s
This commit was merged in pull request #242.
This commit is contained in:
47
README.md
47
README.md
@@ -1160,6 +1160,53 @@ events should be forwarded.
|
||||
The `config` field stores type-specific configuration as JSON (e.g.,
|
||||
destination URL, custom headers, timeout settings).
|
||||
|
||||
**`http` target configuration:**
|
||||
|
||||
| Key | Type | Description |
|
||||
| --------- | ------------- | ----------- |
|
||||
| `url` | string | Destination the event is POSTed to |
|
||||
| `headers` | object | Extra request headers, applied last so they win over the event's own forwarded headers |
|
||||
| `timeout` | integer (sec) | Per-target request timeout; unset (or 0) uses the shared 30-second client timeout |
|
||||
|
||||
`timeout` is capped at **300 seconds**, and the form rejects anything
|
||||
above it rather than substituting the cap. A delivery attempt holds one
|
||||
of the bounded pool's workers for its whole duration, so an unbounded
|
||||
timeout would let a single unresponsive destination stall the queue.
|
||||
|
||||
`headers` rejects the names the delivery path or `net/http` writes
|
||||
regardless of what is configured: `Host`, `Content-Length`,
|
||||
`Transfer-Encoding`, `Connection`, `Trailer` and `User-Agent`. These are
|
||||
refused at the form rather than accepted and ignored, because a stored
|
||||
header that provably never reaches the wire tells the operator their
|
||||
configuration took effect when it did not. `Content-Type` is _not_
|
||||
reserved: a configured one deliberately overrides the event's.
|
||||
|
||||
**Redirects.** A redirect from an `http` target's destination is
|
||||
followed, up to ten hops, and the delivery's recorded status and body
|
||||
come from the final hop. One rule governs every header the delivery
|
||||
carries for someone else — the configured `headers` and the inbound
|
||||
event headers forwarded from the sender alike: **a hop that leaves the
|
||||
origin the target names carries none of them.** Leaving the origin
|
||||
means a different host, a different port, or a step down from `https`
|
||||
to `http`. Both classes routinely carry a secret — a configured
|
||||
`X-Api-Key` or `PRIVATE-TOKEN`, an inbound `X-Hub-Signature` — and an
|
||||
open redirect at the destination would otherwise hand it to a host the
|
||||
operator never chose. `net/http` already does this for `Authorization`
|
||||
and `Cookie`. The delivery path's own headers (`Content-Type`,
|
||||
`User-Agent`) are not origin-scoped and always travel, so a body
|
||||
preserved across a `307` is still typed. A `301`, `302` or `303` is a
|
||||
different matter, and this is `net/http`'s behaviour rather than
|
||||
webhooker's: the POST becomes a GET and the event body and its
|
||||
`Content-Type` are dropped, so the destination the chain ends at
|
||||
receives no event at all — and the delivery is still recorded
|
||||
`Delivered` on that hop's `2xx`. Redirects within the target's own
|
||||
origin keep everything, so a destination that redirects its own paths
|
||||
is unaffected; the drop is per hop rather than permanent, so a chain
|
||||
that returns to the configured origin carries the headers again,
|
||||
exactly as `net/http` treats `Authorization`. Each hop is dialled
|
||||
through the same SSRF guard as the first, so a redirect aimed at a
|
||||
private or reserved address is refused at connect time.
|
||||
|
||||
#### APIKey
|
||||
|
||||
A programmatic access credential for API authentication.
|
||||
|
||||
Reference in New Issue
Block a user