web: Referrer-Policy same-origin; a password shown once emptied on pagehide
test / test (push) Canceled after 0s
test / test (push) Canceled after 0s
D-B3. Fetch Standard § 3.2 "append a request `Origin` header": under Referrer-Policy no-referrer a request that is not GET/HEAD and not CORS - a form POST, a navigation - gets Origin "null". originAllowed() refuses "null" whenever Sec-Fetch-Site is absent, and Fetch Metadata § 3 sends Sec-Fetch-Site only to a potentially trustworthy URL: every form, sign-in included, failed in Safari before 16.4 and in any browser on a plain-HTTP panel at a name. same-origin nulls Origin only for a request not same origin with its URL and still sends no referrer to another site. The comments of the origin check say so. D-B13. noStore keeps the page out of HTTP caches (RFC 9111 § 5.2.2.5); a history mechanism "might honor" it (§ 6), and Pragma in a response "was never specified" (§ 5.4) - it goes. CopyField.Secret marks the password of out-app-created data-secret, and panel.js empties such fields on pagehide (HTML § 7.5.9, "unload a Document", step 10.2: fired whether or not the document is kept for history traversal). Measured 2026-10-15 in Chrome 152 (the desktop app's browser), a local probe page with Cache-Control: no-store and a data-secret field: Back reloads it (pageshow persisted=false, a new load), so this browser keeps no-store pages out of its back/forward cache; the handler, fired on the same page, empties the field. Firefox and Safari not measured. Tests: the header value; the created page has the password data-secret and the login not, no Pragma. Stand (2026-10-15, make e2e, exit 0): new form_post_with_the_browsers_origin - Referrer-Policy: same-origin on a page; a POST carrying the page's own Origin and no Sec-Fetch-Site, what a browser sends now, passes; one carrying Origin: null, what it sent before, is 403. (A first run failed where the e2e client and a view test scraped the old input markup; both read data-secret now.) go vet and go test ./... pass on the server (24 packages). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -137,3 +138,41 @@ func writeCertWithoutItsKey(certPath string, notAfter time.Time) error {
|
||||
}
|
||||
return os.WriteFile(certPath, pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: der}), 0o644)
|
||||
}
|
||||
|
||||
// testFormPostWithTheBrowsersOrigin: a browser on a plain-HTTP panel at a
|
||||
// name sends no Sec-Fetch-Site (Fetch Metadata § 3: only for a potentially
|
||||
// trustworthy URL), and its form POST - a navigation - carries Origin by the
|
||||
// page's Referrer-Policy (Fetch Standard § 3.2): its own origin under the
|
||||
// panel's same-origin, which passes; "null" under no-referrer, which the
|
||||
// panel sent until 2.5.2 and which the origin check refuses (assumptions
|
||||
// D-B3). The client here is not a browser: it sends what one would.
|
||||
func testFormPostWithTheBrowsersOrigin(t *testing.T, sc *scenario) {
|
||||
resp, _, err := sc.panel.get("/server/health")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := resp.Header.Get("Referrer-Policy"); got != "same-origin" {
|
||||
t.Fatalf("Referrer-Policy %q, want same-origin", got)
|
||||
}
|
||||
post := func(origin string) int {
|
||||
t.Helper()
|
||||
req, err := http.NewRequest(http.MethodPost, panelBaseURL+"/server/health/recheck", strings.NewReader(""))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("Origin", origin)
|
||||
resp, err := sc.panel.http.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
return resp.StatusCode
|
||||
}
|
||||
if code := post(panelBaseURL); code != http.StatusOK {
|
||||
t.Fatalf("POST with the page's own Origin: status %d, want 200 after the redirect", code)
|
||||
}
|
||||
if code := post("null"); code != http.StatusForbidden {
|
||||
t.Fatalf("POST with Origin: null: status %d, want 403", code)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user