.be anchors — store-root redirect, TOML injectiondog/HOME.c's cwd-walk discovery is the git CVE-2022-24765 class: it probes
every ancestor for .be and adopts the first hit with ZERO trust validation.
For a secondary-worktree anchor (a .be regular file), home_anchor_resolve
(HOME.c:637-682) takes row-0's URI path VERBATIM and makes it h->root — the
store root — with no ownership check, no symlink rejection (FILEStat follows
symlinks; FILELStat exists and is unused), and no containment/absolute-path
requirement. Running any dog inside a hostile cloned/untarred directory then
routes rw opens (home_ensure_markers, DOGPupCreate) to an attacker-chosen
path. Separately home_bootstrap_config (HOME.c:110-125) writes git config
user.name/email into .be/config as name = "<value>" with NO escaping, so
a value containing " or \n injects arbitrary TOML (e.g. forging the
HOMEHost ref-authority). Method: Issues.
home_walk_up (HOME.c:922-983) →
home_anchor_resolve (:637-682) → DOGRepoFromBe sets h->root from
row-0 (home_peek_repo_uri :562-587); nothing bounds it to the worktree.FILEStat (HOME.c:650, :997 home_is_exe) resolves
symlinks; a planted .be symlink or a symlinked sibling exe is followed,
then the caller execvps it (TOCTOU between stat and exec).getenv("PATH") scan (HOME.c:1056) picks the sibling binary to exec — an
attacker-controlled PATH chooses the code that runs.HOME.c:110-125, value slice {name_start,name[0]} fed raw;
also silent truncation (256-byte emailbuf, FILEEnsureSoft fills what fits).DOGPupThinTail (DOG.c:714-733) unlinks a recomposed path decoupled from
the mmap it released — check/unlink race in a shared .be dir... NOT rejected in project/branch segments: PATHu8sVerifySegment rejects
//NUL/CR/LF/TAB but not ./..; DOGProjectFromBe (DOG.h:227-251) rejects
only .be; DPATHBranchNormFeed (DPATH.h:57-78) never rejects ... A row-0
path or ref containing .. composes <root>/.be/.. (= <root>) so shard
mkdir -p/refs reads+writes ESCAPE the .be store. (DPATH already ships the
correct rejecter DPATHu8sDrainSeg/DPATHVerify — applied to git tree names,
not to these segments; reuse it here.)FILECreate (abc/FILE.c) opens O_CREAT|O_RDWR|O_TRUNC with NO O_NOFOLLOW
(and no O_EXCL on the pup tmp): callers HOME.c:128 (.be/config), :154
(wtlog), DOG.c:674 (pup tmp). A planted symlink at <repo>/.be/config or
the <seqno>.<ext>.tmp redirects create+truncate to an arbitrary
victim-writable file — classic repo-dir symlink TOCTOU.home_be_subdirs returns fail(OK) on the subdirs>1 break BEFORE setting
*out_count (HOME.c:786-796), so it stays 0; home_dir_shieldlike
(:963) then misclassifies a populated MULTI-project store as shieldlike and
adopts the wrong anchor instead of walking past it.geteuid vs FILELStat owner) and
reject symlinked .be; make row-0 store roots resolve inside the discovered
worktree (absolute + realpath containment) or fail.", \, and control bytes in config values before
emitting TOML; never silently truncate a value.../. in project + branch segments (reuse DPATHVerify) so no
composed store path escapes .be; re-normalize before filesystem use.O_NOFOLLOW on .be/config/wtlog creates and O_EXCL on the pup tmp.home_be_subdirs to set *out_count before the multi-shard break.dog/ libdog, ABC style; keep the ordinary single-user primary-worktree flow
(own .be/) working unchanged — the guard only bites foreign/planted anchors.safe.directory intent: an anchor is trusted only if owned by
the invoking uid (or explicitly allow-listed); no ambient adoption..be file whose row-0 points the
store root outside the tree; assert be refuses instead of writing there.FILELStat symlink checks on the discovered anchor...//relative/outside;
reject ../. project+branch segments (reuse DPATHVerify).home_bootstrap_config; reject NUL/newline;
O_NOFOLLOW/O_EXCL on the marker + pup creates.home_be_subdirs *out_count on the multi-shard break.DOGParseURI/DOGRepoFromBe/home_peek_repo_uri (attacker URIs).DOGRepoFromBe/DOGParseURI (DOG.h:186-280, DOG.c:238-284)
is bounds-safe today but fragile; cleanup tracked under PTR-002.79612854 — raw TOML value feed HOME.c:108-125, no FILELStat/geteuid/O_NOFOLLOW anywhere in HOME.c, home_be_subdirs multi-shard break still skips *out_count (the fail(__) with __==OK precedes the assignment). NOTHING landed; WIP fix UNLANDED in worktree ~/src/DOG-009 (HOME.c modified).