fix(tools): make memory.include_list read-only + harden temp include-cache path (#474, #473) - #489
Draft
TYRMars wants to merge 1 commit into
Draft
fix(tools): make memory.include_list read-only + harden temp include-cache path (#474, #473)#489TYRMars wants to merge 1 commit into
TYRMars wants to merge 1 commit into
Conversation
…th (#474, #473) Two self-contained security/correctness bugs in the memory include-cache plumbing (packages/tools/src/memory-tools.ts). #474 — memory.include_list is declared read-only ("No mutations", category "read", ungated) but its invoke() called resolveInclude(), which for an uncached git+ directive performs a network `git clone` into the local cache. Merely *listing* directives could therefore write to disk, egress to a directive-named host, and stall a turn by the git timeout per uncached entry. resolveInclude now takes an `allowClone` option (default true, preserving the include_add/include_refresh behaviour); include_list passes `allowClone:false` so an uncached git include is reported `resolves:false` ("git include not cached; run memory.include_refresh …") instead of being fetched. #473 — with no userRoot configured, includeCacheRoot fell back to a single predictable, world-readable path ($TMPDIR/jarvis-include-cache) that any local user could pre-create ("squat") or read, exposing private include repos. The fallback is now namespaced by uid ($TMPDIR/jarvis-include-cache-<uid>) and the cache dir is created 0o700 so cloned repos stay out of other users' reach. Regression tests cover all three behaviours (no-clone list, uid-namespaced fallback path, and the private userRoot path). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K2iufag2eVqbcsk9UMmDWT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Auto-resolving open issues. Two self-contained security/correctness bugs in the memory include-cache plumbing (
packages/tools/src/memory-tools.ts), each with a regression test. The branch is constrained toclaude/vibrant-dijkstra-wddus3, so both land here.Fixes #474 —
memory.include_list(a read-only, ungated tool) performed a networkgit cloneMemoryIncludeListTooladvertises itself as read-only (description "No mutations",category: "read", not approval-gated). But itsinvoke()calledresolveInclude(d, cache), which for an uncachedgit+directive doesfs.mkdir+git clone --depth 1into the local cache.Consequences of merely listing directives:
MEMORY.mdcontent, i.e. can be attacker-influenced) — with no approval gate;GIT_TIMEOUT_MS, ~60s) per uncached entry.Fix:
resolveIncludenow takes anopts.allowCloneflag (defaulttrue, soinclude_add/include_refreshkeep fetching as before).include_listpassesallowClone: false, so an uncached git include is reportedresolves: falsewith"git include not cached; run memory.include_refresh …"instead of being fetched. Local-path includes and already-cached git includes still resolve normally.Fixes #473 — predictable, world-readable temp include-cache path
With no
userRootconfigured,includeCacheRootfell back to a single fixed path$TMPDIR/jarvis-include-cache. That path is:Fix: the temp fallback is namespaced by uid (
$TMPDIR/jarvis-include-cache-<uid>), and the cache dir is created with mode0o700inresolveInclude, so cloned repos stay out of other users' reach. TheuserRoot-present path (<userRoot>/.jarvis/include-cache) is unchanged.Tests
packages/tools/src/memory-tools.test.ts(3 new, network-free):resolveIncludewithallowClone: falsethrowsnot cachedfor a git include and leaves the cache dir untouched;include_listreports an uncached git include asresolves: falseand never creates/populates the cache;includeCacheRoottemp fallback is uid-namespaced (not the bare shared path); theuserRootpath is unchanged.pnpm --filter @jarvis/tools test→ 270 pass / 0 fail;typecheckandeslintclean.🤖 Generated with Claude Code
Generated by Claude Code