the binary check that was a comment, and a guard that could fire
Four fixes from the live server's review. One was a real defect.
THE BINARY WAS NEVER CHECKED. spawn-as-member passed `command` from the SDK
through untouched while a comment claimed the member's own install was what ran.
Since claude-manager resolves the OWNER'S CLAUDE_BIN at module load, wiring the
hook would have exec'd the owner's binary as the member — the precise confusion
this file exists to prevent, asserted in prose and enforced nowhere. Now throws
unless the command resolves to claudeBinIn(run.home).
NEVER_ENV COULD NOT FIRE. It tested an environment that memberEnv builds from
ALLOWED_ENV, so a denied name was already impossible; it was also missing six
credential variables the installed SDK reads. Replaced with the subset check the
reviewer proposed: anything not in ALLOWED_ENV or {HOME, CLAUDE_CONFIG_DIR} is a
leak whatever it is called. Complete by construction, and it cannot rot as the
SDK grows variables — which the denylist provably had already.
Also: one derivation of the binary path instead of two (install resolved from
the email, exec from the home — fine until they disagree), and the constraint
that ALLOWED_ENV may never hold a secret written at the list itself, since
`env K=V` in the argv is visible in /proc/<pid>/cmdline to every account.
Not acted on, and said so in COMMS: their finding that the 711 in 401dcb7 is
inert, and that a retrofit needs a mode pass. Both are theirs. Nor pulled chat
from DEFAULT_ROLE_CAPABILITIES despite agreeing a member currently sees a tile
that 403s — that is the owner's call, not a defect.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -32,8 +32,18 @@ import { osUserHome, runAs } from './os-user';
|
||||
/** Anthropic's own installer — the same one `scripts/setup.sh` uses for the owner, chosen for auto-update. */
|
||||
const CLAUDE_INSTALL_URL = 'https://claude.ai/install.sh';
|
||||
|
||||
/** Where the installer puts it. Also the first path `claude-manager.ts` probes after `$CLAUDE_BIN`. */
|
||||
export const claudeBinPath = (email: string): string => join(osUserHome(email), '.local', 'bin', 'claude');
|
||||
/**
|
||||
* Where the installer puts it, given a home. Also the first path `claude-manager.ts` probes after
|
||||
* `$CLAUDE_BIN`.
|
||||
*
|
||||
* Takes a home rather than an email because the spawn side only ever has the home — it comes from
|
||||
* `resolveHomeDir`, not from a lookup. One derivation for both sides: installing to one path and exec'ing
|
||||
* another is the kind of divergence that surfaces as "the agent works for some members".
|
||||
*/
|
||||
export const claudeBinIn = (home: string): string => join(home, '.local', 'bin', 'claude');
|
||||
|
||||
/** The same path, for callers that hold an email. */
|
||||
export const claudeBinPath = (email: string): string => claudeBinIn(osUserHome(email));
|
||||
|
||||
/**
|
||||
* The file whose existence means "this account has logged in".
|
||||
|
||||
Reference in New Issue
Block a user