Skip to content

fix(goals): allow quoted-heredoc writes through the memory VFS#229

Open
khustup2 wants to merge 1 commit into
mainfrom
fix/goals-heredoc-edit
Open

fix(goals): allow quoted-heredoc writes through the memory VFS#229
khustup2 wants to merge 1 commit into
mainfrom
fix/goals-heredoc-edit

Conversation

@khustup2
Copy link
Copy Markdown
Contributor

@khustup2 khustup2 commented Jun 3, 2026

Problem

Editing a goal/KPI body through the Hivemind memory VFS uses the documented multi-line form:

cat > ~/.deeplake/memory/goal/<owner>/<status>/<uuid>.md <<'EOF'
<body>
EOF

…but this never worked. The isSafe gate in the pre-tool-use hook splits the entire command string on \n and validates each line as a command stage. The heredoc body lines (arbitrary goal prose) aren't safe builtins, so isSafe returned false, getShellCommand returned null, the hook never intercepted the write, and raw bash hit a nonexistent path. Goal bodies were effectively uneditable via tooling — users had to abandon a goal and create a fresh one to "update" it.

The downstream deeplake-shell.js already handles heredoc create and overwrite (version-bump) correctly — verified end-to-end. This one gate was the entire blocker.

Fix

src/hooks/memory-path-utils.ts: add stripHeredocBodies() and call it from isSafe().

  • For quoted heredocs (<<'EOF' / <<"EOF"), which bash never expands, the body + closing delimiter are dropped before validation — the body is inert data. The command in front (cat > …) is still fully validated.
  • Unquoted heredocs keep their body in validation, so injection via <<EOF … $(rm -rf ~) … EOF is still rejected.

Tests

  • 4 new isSafe cases in tests/claude-code/pre-tool-use-branches.test.ts (quoted accepted incl. <<- / double-quote / backticks-in-body; unquoted $() and a non-builtin in front still rejected).
  • All hook suites green: 107 tests across claude-code / cursor / hermes / codex.

Summary by CodeRabbit

Bug Fixes

  • Enhanced command validation to correctly process shell heredocs, preventing incorrect validation of quoted heredoc bodies while maintaining validation for unquoted heredocs.

Editing a goal/KPI body uses the documented multi-line form
`cat > <path> <<'EOF' ... EOF`, but isSafe split the whole command on
newlines and validated the heredoc *body* lines as command stages. Any
prose body failed validation, so getShellCommand returned null, the hook
never intercepted the write, and raw bash hit a nonexistent path —
goal bodies were effectively uneditable via tooling.

Strip quoted-heredoc bodies (`<<'EOF'`/`<<"EOF"`, which bash never
expands) before validation: the body is inert data, while the command in
front is still fully checked. Unquoted heredocs keep their body in
validation, so `<<EOF ... $(...) ... EOF` style injection stays rejected.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 3, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 153aa4f1-b0fe-4359-b462-2fabc0da140c

📥 Commits

Reviewing files that changed from the base of the PR and between 2bf77fb and 4c6abec.

📒 Files selected for processing (2)
  • src/hooks/memory-path-utils.ts
  • tests/claude-code/pre-tool-use-branches.test.ts

📝 Walkthrough

Walkthrough

The PR updates command validation in the isSafe hook to handle shell heredocs correctly. A new stripHeredocBodies helper removes quoted heredoc bodies before validation, preventing false positives from arbitrary heredoc content. Unquoted heredocs remain validated. Two test cases cover safe quoted heredocs and rejection of unsafe commands or unquoted heredoc variants.

Changes

Heredoc Handling in Command Validation

Layer / File(s) Summary
Heredoc preprocessing and isSafe integration
src/hooks/memory-path-utils.ts
New stripHeredocBodies helper detects quoted heredoc delimiters (<<'EOF', <<"EOF") and removes their bodies and closing lines. The isSafe function applies unsafe-character validation against the heredoc-stripped command, while unquoted heredocs remain intact for body validation.
isSafe heredoc validation test coverage
tests/claude-code/pre-tool-use-branches.test.ts
Test assertions verify that cat commands with quoted heredoc delimiters (including indented <<- forms) are safe regardless of body content; unsafe commands before heredocs are rejected; unquoted delimiters require body content validation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A heredoc hop, clean and neat,
Quoted bodies won't trick the beat,
Strip those lines with fuzzy delight,
isSafe sleeps soundly through the night! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: allowing quoted-heredoc writes through the memory VFS, which is the core problem being solved.
Description check ✅ Passed The description covers all key sections from the template: Problem is well-documented, Fix is clearly explained, and Test plan is provided with test counts. Version bump guidance is acknowledged implicitly.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/goals-heredoc-edit

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 3, 2026

Coverage Report

Scope: files changed in this PR. Enforced threshold: 90% per metric (per file via vitest.config.ts).

Status Category Percentage Covered / Total
🟢 Lines 100.00% (🎯 90%) 29 / 29
🟢 Statements 100.00% (🎯 90%) 35 / 35
🟢 Functions 100.00% (🎯 90%) 4 / 4
🟢 Branches 94.74% (🎯 90%) 18 / 19
File Coverage — 1 file changed
File Stmts Branches Functions Lines
src/hooks/memory-path-utils.ts 🟢 100.0% 🟢 94.7% 🟢 100.0% 🟢 100.0%

Generated for commit c114d02.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant