v0.19.0 — Workspace sensitive-path gate (#64)
Breaking by design (pre-1.0 minor bump): a workspace that resolves to a
sensitive host path is now refused unless --unsafe-dir is given. Repository
workspaces are unaffected.
Security
- BREAKING (by design): the sensitive-path gate now covers the primary
workspace (#64).dir_is_sensitiverefused/, system directories,
$HOMEand its ancestors, and credential directories for every--dir/
--dir-ro— but never for the workspace itself. On a machine whose dotfiles
repository is rooted at$HOME,tjor runfrom~(or from any
non-repository directory under it) resolved the workspace to$HOMEvia
git rev-parse --show-topleveland mounted the entire home directory
writable and git-trusted as a tree, silently. The workspace is now checked
with the same rule, on the launch path only, before the session state
directory is created and before any credential is minted; a refusal leaves
nothing behind. When git discovery climbed above the launch directory to
reach a sensitive toplevel, the error says so (<cwd> is not a repository; git resolved the workspace to <toplevel> via <toplevel>/.git — launch from a repository (or pass --unsafe-dir)).--unsafe-dirremains the single
override and now prints a loud warning naming the exposed path whenever it
actually overrides a refusal (workspace or extra dir); it stays silent when
nothing needed overriding. Lifecycle commands (down,status,reset,
denials) never apply the gate, so a session launched under the override
remains manageable. Repository workspaces are unaffected. - tjor's own roots join the sensitive set (#64). The effective
session.root(every state dir under it holds a session's proxy CA key,
broker material and harness auth) and the effective user-config directory
($TJOR_USER_CONFIG's dir, else$XDG_CONFIG_HOME/tjor, else
~/.config/tjor) are refused when a path equals, contains, or lies under
them — for the workspace and for--dir/--dir-roalike (--dir ~/.tjor/sessionswas accepted before). Custom locations are honored. - The cage refuses a system-directory mount root at direct invocation
(#64). The entrypoint now aborts (exit 90) when any approved root in
TJOR_SAFE_DIRSis/etc,/usr,/var,/bin,/sbin,/boot,
/sys,/proc,/dev,/rootor a child of one;/was already refused.
The launcher's--unsafe-dirreaches the cage (TJOR_UNSAFE_DIR) and
downgrades this to a loud warning, so the one override holds end to end.
Honest scope: this is the only half of the gate the cage can judge —
the host home, its credential dirs, the session root and the config dir are
host facts the container cannot see, so those remain a launcher
guarantee, and the docs say so rather than claiming an in-cage re-check. - Coverage: a new daemon-free launcher test
(tests/integration/workspace_gate_test.sh,unitCI job) proves every
refusal, the override, the no-state-dir property and the lifecycle
exemption; it is the third suite source of the boundary matrix
(workspace-gate, launcher-side) with six renderedsession-launchrows.
Theagent-imageCI job gains the direct-invocation negative path.
session-launchspec amended.