Skip to content

levain 0.6.5

Choose a tag to compare

@phillipclapham phillipclapham released this 05 Oct 15:20
· 4335 commits to main since this release

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 consolidate write 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 wrote PROJECT.md to its path in the worktree, following a symlink. A member who pushed PROJECT.md as 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.md and team.toml are now written as a new regular file renamed into place, so a link there is replaced, never followed, and team.toml is never read through a link. Run record: flow projects/levain/reference/team_canon_symlink_run_1005/.

Fixed

  • A teammate's ruling can no longer draw fake [team] lines into your session. The SessionStart context 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 status and PROJECT.md assemble 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.toml refuses member handles that would share a ledger folder. A handle's ledger folder drops a trailing - or ., so ana and ana- (or ana.) both wrote ledger/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 whose team.toml holds such a pair is refused with both names. A team.toml holding 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 visible ledger unavailable line. 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 from ben to ben- (no pair at any one time) still shares ledger/ben/ across the rename, and an email written as <a@x.com> is a different roster entry from a@x.com though git records both the same way.
  • The levain wrap exit-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.