docs(roadmap): add git fetch read-only gap

This commit is contained in:
Yeachan-Heo
2026-05-22 04:31:16 +00:00
parent 1882c9582a
commit 2bb5d49ce3

View File

@@ -6687,3 +6687,5 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed)
566. **Workspace-write outside-workspace detection misses exact sensitive directory targets like `/etc` because `command_targets_outside_workspace` only searches for paths with trailing slashes** — dogfooded 2026-05-22 from the `#clawcode-building-in-public` 03:00 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@665dd1f`. Active tmux sessions at probe time: none. Code inspection: `runtime/src/bash_validation.rs:286-295` routes `PermissionMode::WorkspaceWrite` through `command_targets_outside_workspace`, and that helper at `bash_validation.rs:302-323` only warns for write/state-modifying commands when the command string contains one of `"/etc/", "/usr/", "/var/", "/boot/", "/sys/", "/proc/", "/dev/", "/sbin/", "/lib/", "/opt/"`. Existing coverage checks `validate_mode("cp file.txt /etc/config", PermissionMode::WorkspaceWrite)` and therefore exercises the trailing-slash case. But a write target that is exactly the directory name, such as `cp file.txt /etc`, `mv config /usr`, `install file /opt`, or `tee /etc`, does not contain `"/etc/"` / `"/usr/"` / `"/opt/"`; the helper returns false and `validate_mode` falls through to `Allow`. This is adjacent to, but distinct from, Jobdori's #570 traversal-substring bypass: even without `..`, exact system directory operands evade the workspace-write out-of-scope warning because the heuristic uses substring sentinels instead of token/path boundary checks. **Required fix shape:** (a) tokenize shell words enough to inspect path-like operands rather than raw substring matching; (b) treat exact sensitive directories (`/etc`, `/usr`, `/var`, `/boot`, `/sys`, `/proc`, `/dev`, `/sbin`, `/lib`, `/opt`) and descendants equivalently; (c) include command/path evidence in the warning so operators see which operand escaped workspace scope; (d) add regressions for `cp file.txt /etc`, `mv file /usr`, `install file /opt`, and keep the existing `/etc/config` case green; (e) consider unifying this with the #570 path-resolution hardening so workspace-write/read-only path scope checks use one boundary-aware path classifier. **Why this matters:** workspace-write mode is supposed to allow project edits while warning on system-level writes. Missing exact-directory operands lets an agent attempt writes into sensitive roots with no permission warning, which is precisely the boundary the mode is meant to make visible. Source: gaebal-gajae dogfood response to Clawhip message `1507216459665772677` on 2026-05-22.
567. **Path traversal validation treats any command string containing the workspace path as safe, so mixed outside-target commands can smuggle `../` escapes past the warning** — dogfooded 2026-05-22 from the `#clawcode-building-in-public` 04:00 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@665dd1f`. Active tmux session at probe time: `omc-issue-3079-plugin-cache-commands`; no active claw-code implementation session. Code inspection: `rust/crates/runtime/src/bash_validation.rs::validate_paths` checks `if command.contains("../")`, then suppresses the traversal warning whenever the *entire command string* contains `workspace.to_string_lossy()`. That means a command with one operand inside the workspace and a separate traversal operand outside it, such as `cp /workspace/file ../../../etc/passwd` (workspace `/workspace`) or `tar -cf /workspace/out.tar ../../..`, is treated as `Allow` because the workspace prefix appears somewhere in the command. The validator never tokenizes operands, resolves each candidate path, or proves that the specific `../` path stays under the workspace root. Existing tests cover `cat ../../../etc/passwd` without a workspace substring, but not mixed safe+unsafe operands. This is a separate path-scope gap from #566's exact sensitive-directory miss: here the escape uses traversal and is hidden by an unrelated in-workspace token. **Required fix shape:** (a) tokenize shell words enough to collect path-like operands independently; (b) resolve each relative/absolute candidate against cwd/workspace and warn/block when any operand escapes, rather than checking whether the command string contains the workspace root; (c) keep quoted/non-path text from causing false positives; (d) add regressions for `cp /workspace/file ../../../etc/passwd`, `tar -cf /workspace/out.tar ../../..`, and a positive `cp /workspace/file /workspace/sub/../safe`; (e) align this with the boundary-aware classifier required by #566 so workspace-write/read-only path validation shares one per-operand path-scope primitive. **Why this matters:** path validation is supposed to make workspace escapes visible. A global substring exemption lets one benign workspace path launder a different `../` operand, producing false `Allow` evidence for commands that still target outside the workspace. Source: gaebal-gajae dogfood response to Clawhip message `1507231563484500048` on 2026-05-22.
568. **Read-only bash validation classifies `git fetch` as safe even though fetch mutates `.git/FETCH_HEAD`, remote-tracking refs, packfiles, and optional tags** — dogfooded 2026-05-22 from the `#clawcode-building-in-public` 04:30 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@1882c95`. Active tmux sessions at probe time: `gajae-pr-323-bootstrap-context-readiness-review`, `omx-issue-2451-madmax-detached-lock-timeout`; no active claw-code implementation session. Code inspection: `rust/crates/runtime/src/bash_validation.rs::validate_read_only` delegates `git` commands to `validate_git_read_only`, and `GIT_READ_ONLY_SUBCOMMANDS` includes `fetch` alongside pure inspection commands like `status`, `log`, and `show`. But `git fetch` is not read-only: even without checkout it writes `.git/FETCH_HEAD`, may update remote-tracking refs, downloads pack/object data, updates tags depending on flags/config, and can run hooks/config-driven network behavior. There is no mode distinction for `git fetch --dry-run` versus mutating fetch forms, and no test asserts that read-only mode blocks repository/network mutation. This creates a stale-branch/confusion footgun in the opposite direction: agents can claim read-only validation while changing the local base/ref state used by later freshness checks. **Required fix shape:** (a) remove plain `fetch` from `GIT_READ_ONLY_SUBCOMMANDS` or split it into a separate `NetworkMetadataMutation`/workspace-write classification; (b) allow only explicitly non-mutating forms if Git actually guarantees them for the chosen flags, otherwise require WorkspaceWrite/Prompt; (c) add read-only regressions proving `git fetch`, `git fetch origin main`, and `git fetch --tags` are blocked/warned, while `git status`, `git log`, and `git diff` remain allowed; (d) include a clear reason mentioning `.git` metadata/ref mutation and network access; (e) align stale-branch preflight code so any fetch it performs is an explicit trusted preflight action, not hidden inside user-command read-only permission. **Why this matters:** read-only mode is used as safety evidence. Treating `git fetch` as read-only lets commands mutate repository metadata and remote refs under a permission label that promises observation only, making later branch-freshness and audit results harder to trust. Source: gaebal-gajae dogfood response to Clawhip message `1507239113550725231` on 2026-05-22.