capsite/toybox: routing carries no secrets
The ingress no longer reads labels from a Toybox-Labels header. A header was no place for the webkey pattern: browsers can't set one on a WebSocket, and the pattern puts the secret in-band anyway. A page keeps it in its fragment, reaches the vat by public labels, and sends it in the body of a call, which the vat checks like a swissnum. A request still reaches a vat only by naming every label of its mount. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
28b1c3c9d3
commit
193a126d1c
5 files changed
+28
-24
No files matched your search
+10
-9
@@ -320,21 +320,22 @@ export class Directory extends DurableObject {
|
||||
}
|
||||
|
||||
/**
|
||||
* A request's labels: its query parameters, plus a `Toybox-Labels` header
|
||||
* (JSON) for labels too secret for a URL, which ends up in logs and
|
||||
* `Referer`s. A webkey page keeps such a secret in its fragment and sends
|
||||
* it in the header.
|
||||
* A request's labels: its query parameters.
|
||||
*
|
||||
* Routing carries no secrets: a URL ends up in logs and `Referer`s. A
|
||||
* secret travels in-band instead, as on a webkey page: the page keeps it
|
||||
* in its fragment, reaches the vat by public labels, and sends it in the
|
||||
* body of a call, which the vat checks like a swissnum.
|
||||
*
|
||||
* @param {Request} request
|
||||
*/
|
||||
const requestLabels = (request) => {
|
||||
const query = {};
|
||||
const labels = {};
|
||||
for (const [k, v] of new URL(request.url).searchParams) {
|
||||
if (k in query) throw new Error(`label ${k} given twice`);
|
||||
query[k] = v;
|
||||
if (k in labels) throw new Error(`label ${k} given twice`);
|
||||
labels[k] = v;
|
||||
}
|
||||
const header = request.headers.get("Toybox-Labels");
|
||||
return mergeLabels(query, header ? JSON.parse(header) : {});
|
||||
return Object.freeze(labels);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user