aboutsummaryrefslogtreecommitdiff
path: root/lib/rites/rite_ef/dune
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-19 10:42:22 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-19 10:42:22 +0200
commitbca7dabd2b436b8fe8de21736c59437b5ea990af (patch)
tree3a8c203dd2af616cf1193f0ddeb3b67550a6a249 /lib/rites/rite_ef/dune
parentb90678e560808dd788fa7d7eb319d93a83005db4 (diff)
downloadcolitur-bca7dabd2b436b8fe8de21736c59437b5ea990af.tar.gz
colitur-bca7dabd2b436b8fe8de21736c59437b5ea990af.zip
fix(cli): publish --prune refuses a manifest entry that escapes --out
CRITICAL: .colitur-manifest lives INSIDE the tree publish writes into -- the very tree this feature exists to have committed into a git repo. A manifest entry with a ".." path component, or an absolute path, let --prune Sys.remove/Unix.rmdir a file OUTSIDE --out. No attacker is required: an ordinary bad merge, a conflict resolved the wrong way, or a hand-edit of that file is enough to plant such an entry, and publish's own stated contract -- it never deletes a file it does not own -- broke outright the moment one was present. Two independent checks, both required, applied before every deletion: - structural (manifest_entry_is_safe): reject an entry that is absolute or has a ".." path COMPONENT, by splitting on '/' and comparing components, not by substring-matching ".." (which would wrongly reject a legitimate name like foo..bar). - containment (resolves_under): resolve both --out and the candidate with Unix.realpath (closing a symlink-inside-out gap the structural check alone would miss) and verify the candidate is a genuine path descendant of --out, not merely a string with the same prefix. Applied at both the file-deletion loop and prune_empty_dirs' own directory removals. A rejected entry is skipped with a one-line stderr warning; publish completes rather than aborting -- a corrupted manifest must not make the tool itself unusable. test/cli.t reproduces the exact canary scenario (a ".." entry surviving deletion of a file outside --out), an absolute-path entry, and a legitimate dotted filename (no .. component) still pruning normally, alongside the existing --prune coverage.
Diffstat (limited to 'lib/rites/rite_ef/dune')
0 files changed, 0 insertions, 0 deletions