mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 12:39:42 +02:00
docs(webview): record the lost-frame page as the third unauthenticated 200, and the inline-style limit
The lost-frame recovery page is answered ahead of the credential checks in both auth hooks, which makes it the third unauthenticated 200 beside the two hook routes, and the only one decided by request headers alone. CLAUDE.md's security table listed exactly two, and docs/web-tabs.md is not where anyone auditing that looks, so it now has a row in the table and a fourth property in docs/security-architecture.md section 10b, including the `/` carve-out and its credential-free condition. Both state the property that comes with it: a non-browser client can set those headers, so an unauthenticated caller can tell a registered route (401) from a non-route (200) and enumerate the route table, accepted because the routes are public in docs/api-reference.md. docs/web-tabs.md gains the landing-page case in layer 6 and a Known limits entry: masking trades away the Referer safety net, only HTML is rewritten server-side, and a root-absolute url() inside an inline <style> block has the masked document as its Referer, so it 404s where the Referer fallback used to rescue it. External stylesheets are unaffected. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
+14
-1
@@ -173,7 +173,10 @@ layers cooperate so a dashboard talking to its own backend just works:
|
||||
path it does not serve) and answers a static page that does nothing but tell
|
||||
the owning tab which path was lost; the tab remounts the frame inside the
|
||||
prefix at that path. It never counts as a failed login, so a dev server that
|
||||
reloads on every save cannot rate-limit its user out of Codeman.
|
||||
reloads on every save cannot rate-limit its user out of Codeman. The landing
|
||||
page is the one served path that gets the same answer: it masks to exactly
|
||||
`/`, and a reload there is admitted as long as the request carries no Codeman
|
||||
credentials, which a sandboxed frame never does.
|
||||
|
||||
On top of that, the proxy answers those requests with CORS headers. That sounds
|
||||
wrong for same-host requests, but a sandboxed iframe has an *opaque* origin, so the
|
||||
@@ -187,6 +190,16 @@ then every API call fails, which looks like the dashboard being broken.
|
||||
EventSource, normal markup, the DOM sinks a page uses to build markup at runtime,
|
||||
and `url()` inside stylesheets. Something that constructs requests by an unusual
|
||||
route can still slip through. Symptom: the page renders but a panel stays empty.
|
||||
- **A root-absolute `url()` inside an inline `<style>` is not rescued.** Masking the
|
||||
page's URL (layer 5) trades away the `Referer` safety net of layer 4 for
|
||||
requests the shim cannot see, and only HTML is rewritten server-side. An
|
||||
external stylesheet is fine: a `url()` it references is fetched with the
|
||||
stylesheet's own URL as `Referer`, which is still inside the prefix. A
|
||||
root-absolute `url(/img.png)` written directly into a `<style>` block in the
|
||||
document has the masked document as its `Referer`, so it 404s where the
|
||||
fallback used to rescue it. Symptom: one background image missing while
|
||||
everything else renders. Narrow, and a `url()` the page sets from script is
|
||||
still covered by layer 3.
|
||||
- **Root-absolute `location` navigation is recovered, not prevented.** `Location`
|
||||
is unforgeable, so `location.href = '/login'` or `location.reload()` really does
|
||||
leave the prefix; the frame comes back through the recovery hop in layer 6 above,
|
||||
|
||||
Reference in New Issue
Block a user