the notify sidecar stops trusting whoever reaches it
to send one message to four accounts an hour ago i found the sidecar's ephemeral port and POSTed to it directly, once per user, with no authentication of any kind. that worked, which was the problem: the same door was open to anything else on the machine, including a commander with a shell. two changes. POST /api/notify/broadcast, owner only via `ownerOnly` on the permission — the supported way to say one thing to everyone. teams will narrow it later; today the choice is everyone or one person. and the sidecar now requires a secret on everything under /_officer/. it is generated per boot, held in memory, announced to the platform over the registration socket beside the port, and never written to disk. X-Officer-User could not carry this on its own, and my first attempt got that wrong: it says WHO is asking, and a caller on loopback can write it itself. only the secret says the PLATFORM is asking. so the check covers the whole /_officer/ surface rather than just the send route — /_officer/ devices takes the same header to decide whose phones are listed and deleted. what it bounds, honestly: a MEMBER's commander runs as its own Linux user and cannot read this process, so for every account but the owner's this is kernel-enforced. the owner's own commander runs as the owner, same as the platform, and is not bounded by this and cannot be — the same reason `execution` permissions are never grantable. the owner's decision, and this is a real improvement rather than a boundary. `bun run notify:test` posts to that port and will now be refused. it is a developer CLI on a box where the platform is running; left to fail loudly rather than given a way in. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
This commit is contained in:
@@ -128,7 +128,19 @@ export type SidecarCommand =
|
||||
* `<name>:server`, where the name is the sidecar's own — `music:server`, `pty:server`, and whatever a
|
||||
* plugin nobody has written yet decides to call itself. Deliberately open: see the note in SidecarEvent.
|
||||
*/
|
||||
export type SidecarPortAnnouncement = { type: `${string}:server`; port: number };
|
||||
export type SidecarPortAnnouncement = {
|
||||
type: `${string}:server`;
|
||||
port: number;
|
||||
/**
|
||||
* A per-boot secret for callers INSIDE the platform that reach this sidecar directly rather than
|
||||
* through its proxy — announced here, in memory on both sides, never written to disk.
|
||||
*
|
||||
* Optional because only a sidecar with a producer path to guard has one. `notify` is the first: its
|
||||
* send route accepts a target user in the body, which loopback alone stopped being enough to protect
|
||||
* once commanders could run a shell on the same machine.
|
||||
*/
|
||||
secret?: string;
|
||||
};
|
||||
|
||||
export type SidecarEvent =
|
||||
| { type: 'pong'; id: string }
|
||||
|
||||
Reference in New Issue
Block a user