Repository navigation
levain 0.6.5
A security fix for the team layer (a member could make the owner's consolidate write outside the ledger worktree; 0.6.0 to 0.6.4 are affected) and three team fixes from the nightly review.
Security
- A team member could make the owner's
levain team consolidatewrite outside the ledger worktree (0.6.0 to 0.6.4; upgrade to fix). The ledger branch is written by every member, and the owner's consolidate wrotePROJECT.mdto its path in the worktree, following a symlink. A member who pushedPROJECT.mdas a symlink therefore had the canon written over any file the owner can write (reproduced on the 0.6.4 wheel: a file outside the worktree was overwritten). The canon carries members' ruling words, so a target such as a shell startup file could turn a ruling into a command.PROJECT.mdandteam.tomlare now written as a new regular file renamed into place, so a link there is replaced, never followed, andteam.tomlis never read through a link. Run record: flowprojects/levain/reference/team_canon_symlink_run_1005/.
Fixed
- A teammate's ruling can no longer draw fake
[team]lines into your session. TheSessionStartcontext printed each ruling's words, paths and owner exactly as recorded, so a line break in a member's ruling started a new line that read as the hook's own ([team] ...) in every teammate's agent context. Every line the hooks,levain team statusandPROJECT.mdassemble is now folded onto one line as a whole, whatever field or file name fed it (words, paths, owner, pack, author, the edited file's own name, warnings and git errors), so a line break in any of them stays inside its line. Found by the nightly review, reproduced, and pinned by a test that fails on 0.6.3. team.tomlrefuses member handles that would share a ledger folder. A handle's ledger folder drops a trailing-or., soanaandana-(orana.) both wroteledger/ana/, and adding the second member made every line the first had written read as the second's: the first member's rulings stopped being enforced, and one member could sign as the other. Handles are now compared by their folder name ignoring case (which also covers the existing case-only check), and a team whoseteam.tomlholds such a pair is refused with both names. Ateam.tomlholding such a pair at the tip is treated like any unusable tip: the newest valid version is used, with a warning that now also reaches the session-start context, or the hooks print a visibleledger unavailableline. A project name that spans lines is folded onto one line when read (older files keep loading) and refused when written. Known limits: a member renamed frombentoben-(no pair at any one time) still sharesledger/ben/across the rename, and an email written as<a@x.com>is a different roster entry froma@x.comthough git records both the same way.- The
levain wrapexit-code documentation no longer says exit 1 leaves the identity unchanged; on three save paths it is not established, and the printed message says what the store shows.