Agreed with the owner, one question at a time; documents only, no code. - csrf-tokens -> origin-strict (agreed): no tokens, the origin check refuses a request with neither header. security.md's ADR records the decision and when tokens are built after all. - structured-logging, contributing: dropped, each with what brings it back (new roadmap section "Dropped, with the condition for return"). - template-data-typing: done by 2.0.0; its last map (healthChecks) is a step of the audit's stage 4. - preflight -> health-setup-checks (certificate name, Postfix's greeting, trusted proxy as lines on Health) and test-email, both agreed. The port check is dropped with its reason; plans/preflight.md removed. - password-reset: agreed; a reset link goes only to a confirmed e-mail, so the item builds confirmation first. - phone-desktop-mode: agreed, after stages 1 and 2 of the audit. - backup-reauth (agreed): the account password before a backup or a domain export, out of review-2026-08-followups. - from-header-binding, Not done: the Delivery log box is required on a refused message's page, with the line Postfix wrote, for all three kinds of refusal (audit stage 1); the Outbound log gets a filter by status and by day (audit stage 4). The audit's checklist is 48 lines (was 45). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+20
-6
@@ -165,7 +165,7 @@ assigned outbound domains and inbound domains **separately**, each list with
|
||||
(`originAllowed`, [internal/web/security.go](../internal/web/security.go)):
|
||||
`Sec-Fetch-Site` must be `same-origin`, or `Origin` must name the panel's own
|
||||
host; the session cookie is `SameSite` as well.
|
||||
- There are **no CSRF tokens yet**. The decision, its price and the conditions
|
||||
- There are **no CSRF tokens**. The decision, its price and the conditions
|
||||
for revisiting it are in the accepted risks and the ADR below.
|
||||
|
||||
### Errors shown to users
|
||||
@@ -306,7 +306,9 @@ deferred item from the roadmap.
|
||||
against, and a strict mode would not "protect" such a client, it would
|
||||
simply break the panel in it. Tightening is one line in `originAllowed`
|
||||
([internal/web/security.go](../internal/web/security.go)): return `false`
|
||||
instead of `true` in the "neither header present" branch.
|
||||
instead of `true` in the "neither header present" branch. That tightening
|
||||
is agreed (owner, 2026-10-13) as
|
||||
[origin-strict](roadmap.md#origin-strict); this bullet goes when it ships.
|
||||
- **Session-bound CSRF tokens are not implemented.** The origin check closes the
|
||||
neighbouring-subdomain case but depends on browser behaviour; a token does
|
||||
not. The price is a hidden field in roughly two dozen forms. The trigger to
|
||||
@@ -315,10 +317,12 @@ deferred item from the roadmap.
|
||||
(see the ADR below). A token would not save the panel from XSS inside it
|
||||
either: code executing in the panel's origin sends the request itself —
|
||||
against that, `html/template` auto-escaping and CSP do the work, which is why
|
||||
templates must contain no inline scripts and no inline styles. Tracked as
|
||||
[csrf-tokens](roadmap.md#csrf-tokens): implementing that item replaces this
|
||||
bullet and the ADR below, and dropping it leaves them as the single record of
|
||||
the decision. The two must not disagree.
|
||||
templates must contain no inline scripts and no inline styles. Decided by
|
||||
the owner on 2026-10-13: no tokens; the roadmap item that asked for them is
|
||||
dropped and the origin check is made strict instead
|
||||
([origin-strict](roadmap.md#origin-strict)). This bullet and the ADR below
|
||||
are the single record of the decision, and the ADR's **Revisit if** says
|
||||
when tokens are built after all.
|
||||
- **Destructive-action confirmation (`data-confirm`) is JavaScript-only.**
|
||||
Delete, regenerate-password, and clear-rate-limit forms carry a
|
||||
`data-confirm` prompt handled entirely in
|
||||
@@ -573,6 +577,16 @@ whose browsers/devices are not vetted) — at that point cross-role request
|
||||
forgery inside the panel would need its own analysis, separate from the
|
||||
external-site case this ADR covers.
|
||||
|
||||
**Decision of 2026-10-13 (owner).** Asked to choose between this ADR, tokens,
|
||||
and a strict origin check, the owner chose the ADR with the strict check
|
||||
([origin-strict](roadmap.md#origin-strict)) and no tokens. Session-bound tokens
|
||||
are the answer to return to - a hidden field in every state-changing form and
|
||||
htmx path, checked against the session, on top of the origin check - when
|
||||
either condition above comes true, and also when: a browser the panel must
|
||||
support is found to send neither header or to send them wrongly; the panel
|
||||
gains a state-changing request that a browser sends without these headers; or
|
||||
an outside review requires a defence that the server alone holds.
|
||||
|
||||
## How this list grows
|
||||
|
||||
The pre-release vulnerability review (history — CHANGELOG `[0.5.0]` Security)
|
||||
|
||||
Reference in New Issue
Block a user