Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions .github/audit/hosted.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ unreachable, report those two checks as `UNVERIFIABLE`.

Read `docs/specs/hosted.md`, `docs/specs/one-time.md` (its "Wire contract",
"Hosted rendezvous", and "Phone page"), `docs/specs/relay.md` (its "HTTP API",
"Setup tokens and the pairing QR", and "WebAuthn without a WebAuthn library",
whose semantics the Hosted Relay keeps), `hosted/server/`, `hosted/src/`,
"Setup tokens and the pairing QR", "WebAuthn without a WebAuthn library", and
"Routing", whose semantics the Hosted Relay keeps), `hosted/server/`, `hosted/src/`,
`hosted/scripts/`, `hosted/wrangler.jsonc`, `hosted/wrangler.relay.jsonc`,
`hosted/wrangler.voice.jsonc`,
`remote-lib-common/src/remote/one-time-wire.ts`,
Expand Down Expand Up @@ -130,6 +130,20 @@ Be adversarial, and go past the `FAIL IF` list. Ask specifically:
Relay must read no cookie, and the rendezvous authorizes nothing. Pocket and
`/connect/` share the relay origin; check what each page's policy lets it
reach of the other.
- **Can one account's relay socket reach another's?** Trace an upgrade
through `relaySocketRoutes` (`hosted/server/relay-sockets.ts`) into
`RelayRoom` (`hosted/server/relay-room.ts`): the object must be named only
from the account a token resolved to, refuse any request or RPC naming
another, and receive no header or token of the caller's; a web page must not
open a Burrow socket, nor another origin a Client socket. Look for routing
state kept in memory that a hibernated object would lose, a socket torn down
twice or routed after its close began, a frame parsed before its length is
bounded or bounded in characters rather than bytes, a `ct` read, decoded,
logged, or stored outside the shared frame layer's field copy, a Client cap
one socket can evict past, a session that outlives its alarm, a ping that
wakes the object, a Burrow socket accepted on a row removed after the token
check, and a removed or de-entitled Burrow whose socket outlives the hourly
sweep.
- **Can the rendezvous become more than a handshake pipe?** Trace a frame
through `OneTimeRoom`: nothing may read, keep, or log it, and the length,
type, and count bounds must close both ends before a byte past them is
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ Six sibling lints run in `pnpm test`. Five enforce one invariant a spec states i
| `scripts/loopback-lint.mjs` (`pnpm lint:loopback`) | `docs/specs/security-local.md` -> "Loopback Listeners": a loopback bind is not an access control — a new listener references a guard module or is allowlisted with a reason. |
| `scripts/deploy-lint.mjs` (`pnpm lint:deploy`) | `docs/specs/security-remote.md` -> "Credentials at rest" and "Network posture (self-hosted)": the installer controls binding all three of `deploy/local/install-{macos,windows,linux}`. |
| `scripts/ps1-cmdlet-lint.mjs` (`pnpm lint:deploy`) | Every `Verb-Noun` call in `deploy/local/install-windows.ps1` uses an approved verb and a noun that is not this project's vocabulary. No job has a PowerShell, so this is the Windows installer's only syntax gate. |
| `scripts/e2e-lint.mjs` (`pnpm lint:e2e`) | The structural half of `docs/specs/security-remote.md` -> "Remote Control": one Noise suite with no selector, no JavaScript curve, no legacy relay discriminant, no Relay-side protocol-v1 type, no one-time reader in the Relay or `BurrowRuntime`, no store in the one-time phone, no checked-in service worker, no optional field on a ciphertext or transcript; and `docs/specs/security-hosted.md` -> "Rendezvous boundary": no frame read in Hosted's one-time room. |
| `scripts/e2e-lint.mjs` (`pnpm lint:e2e`) | The structural half of `docs/specs/security-remote.md` -> "Remote Control": one Noise suite with no selector, no JavaScript curve, no legacy relay discriminant, no Relay-side protocol-v1 type, no one-time reader in the Relay or `BurrowRuntime`, no store in the one-time phone, no checked-in service worker, no optional field on a ciphertext or transcript; and `docs/specs/security-hosted.md`: no frame read in Hosted's one-time room, or decoded or kept in its `RelayRoom`. |

`scripts/spec-lint-selftest.mjs` plants one defect per finding check in the spec lint. The `deploy`, `e2e`, and `loopback` lints carry self-tests that mutate each rule in whichever direction it points: a present-control rule has its control deleted (and, for exact-count rules, a copy added), a `forbidden` rule has the banned text appended. `scripts/e2e-lint-selftest.mjs` is mostly the second kind; `scripts/deploy-lint-selftest.mjs` mostly the first. Either way the lint must go red. **A rule added to one of these lints without its self-test case is not enforced** — it is a claim that something is checked. They share plumbing, and only that, through `scripts/lint-kit.mjs`. `scripts/installer-verify-test.mjs` (also `pnpm lint:deploy`) runs the installer shell helpers lint can only read, extracted from the shipped files; `scripts/ps1-cmdlet-lint-selftest.mjs` carries the `ps1-cmdlet` lint's mutations. `pnpm test` also runs `scripts/clamp-issue-body-selftest.mjs`, the test for `scripts/clamp-issue-body.mjs` (the helper the audit workflows use to keep an issue body postable); it lives at the repo root because its callers do.

Expand Down
Loading
Loading