Skip to content

[claude-hackernews] Reply draft: bwrap+sshfs agent sandbox, in-mount rm -rf still possible (id=48000009)#38

Open
NiveditJain wants to merge 1 commit into
mainfrom
hn-bwrap-sshfs-agent-sandbox-48000009
Open

[claude-hackernews] Reply draft: bwrap+sshfs agent sandbox, in-mount rm -rf still possible (id=48000009)#38
NiveditJain wants to merge 1 commit into
mainfrom
hn-bwrap-sshfs-agent-sandbox-48000009

Conversation

@NiveditJain
Copy link
Copy Markdown
Member

@NiveditJain NiveditJain commented May 3, 2026

Discovery

Found via /newest sweep on HN. Story id=48000009 ("Safe(R) Repo Access for Agents") was ~30 minutes old at draft time, posted by user obiwahn, linking to https://obiwahn.org/posts/safe-sftp-access-for-agents/. OP self-replied with "A little idea to share repos with agents in a more secure manner." No third-party comments yet.

Thread

OP runs AI agents in a dedicated VM, mounts host repos via sshfs, and uses an authorized_keys command="..." forced wrapper plus a bwrap namespace to constrain what the agent can see. Push happens on the host after manual review; the agents VM has no git remote credentials. Stated invariant: even root in the VM cannot escape the bwrap mount.

Why this thread fits

Thread-fit gate: this is a "concrete-failure / proposed-solution" post about agent sandboxing, where the OP is sharing a defense-in-depth recipe and explicitly inviting engagement on it. Adjacent-product Show-HN-style framing, even though it's a personal-blog submission rather than a Show HN. Substantive engagement on the design first; one policy mention.

Proposed reply

The complementary point: bwrap protects the host from the agent, but inside the mount the agent can still happily rm -rf /mnt/repo/build or git reset --hard over uncommitted changes. Different threat models, different layers. Mentions exactly one policy (block-rm-rf) tied to the in-sandbox failure mode. ~128 words. ASCII-only punctuation. No install command, no feature catalog, single repo URL in the disclosure line.

Full draft text in drafts/2026-05-03T191243Z.md (also rendered in the diff).

Workflow

  • Status: draft, pending manual post.
  • Per CLAUDE.md "Comments via PR (never direct post)", nothing was typed into the HN composer; the textarea on the story page is open and the thread accepts replies, but Claude does not click submit.
  • Merge this PR after posting manually on HN. If you want the comment permalink appended to the HN: line in the draft file, ping for that as a follow-up.

Summary by CodeRabbit

  • Documentation
    • Added a new draft post discussing secure repository access strategies for agents. Coverage includes host-side enforcement mechanisms, protective measures against unintended repository modifications, complementary security approaches, threat model guidance, and implementation recommendations for safe agent-repository integration.

… still possible (id=48000009)

Reply on obiwahn's "Safe(R) Repo Access for Agents" post. The bwrap+sshfs
setup is a strong host-side perimeter, but inside the mount the agent can
still rm -rf or git reset --hard over uncommitted work. Frames the
PreToolUse-hook layer as complementary, not competing. One policy
mention (block-rm-rf), no install commands, ASCII-only.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 3, 2026

📝 Walkthrough

Walkthrough

A draft Markdown file documenting a Hacker News reply about safely mounting git repositories into agent VMs. The draft outlines the original post's threat model, endorses host-side enforcement, notes repo destruction risks, provides insights for the FailProof team on layered security approaches, and records metadata about thread engagement and composition preferences.

Changes

Draft HN Reply on Agent Repo Access

Layer / File(s) Summary
Draft Content
drafts/2026-05-03T191243Z.md
New draft Markdown file containing an HN reply addressing safe repository access for agents, including threat model context, security recommendations, team insights, and thread metadata notes.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Possibly related PRs

Poem

🐰 A rabbit hops through agent dreams,
Safe repos in securing beams!
Mount with care, no scripts astray—
Layers guard the mounted way. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly matches the changeset, which adds a draft reply to a specific Hacker News item (id=48000009) about bwrap+sshfs agent sandbox security, highlighting the key technical concern (in-mount rm -rf still possible).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.


Review rate limit: 1/5 review remaining, refill in 36 minutes and 40 seconds.

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@drafts/2026-05-03T191243Z.md`:
- Line 27: The inline code span contains a trailing space before the closing
backtick in the example `command="...sftp-force-directory /path/to/repos-claude"
`; remove the extra space so it reads `command="...sftp-force-directory
/path/to/repos-claude"` to satisfy markdownlint MD038 and eliminate the
trailing-space inside the inline code span.
- Around line 15-21: The markdown fenced block that begins with the disclosure
line is missing a language tag, causing markdownlint MD040; update the opening
code fence (the ``` that precedes "(disclosure: I work on FailProof AI...") to
include a language identifier such as text (i.e. change ``` to ```text) so the
block is explicitly tagged and the lint error is resolved.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d2f92b12-fd55-4889-8cd7-41fba4c642cf

📥 Commits

Reviewing files that changed from the base of the PR and between ebbce06 and 03218d2.

📒 Files selected for processing (1)
  • drafts/2026-05-03T191243Z.md

Comment on lines +15 to +21
```
(disclosure: I work on FailProof AI: https://github.com/exospherehost/failproofai)

Like the host-side enforcement here. The "VM cannot push" property holds even if the agent gets root inside the VM, which the in-process approaches (Claude Code permissions, harness hook policies) cannot match.

These layers compose well. bwrap gives a kernel-enforced perimeter around the agent, but inside the sandbox the agent can still happily `rm -rf /mnt/repo/build` and clobber a sibling directory, or `git reset --hard` over uncommitted changes you wanted to review. A PreToolUse hook that catches those calls before they reach the FUSE layer turns "agent destroyed your branch but at least it stayed in the mount" into "agent got told no and tried something else." Even with this setup I'd still want `block-rm-rf` running in the harness on top.
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add a language identifier to the reply code fence.

The fenced block currently has no language tag, which triggers markdownlint MD040.

Proposed fix
-```
+```text
 (disclosure: I work on FailProof AI: https://github.com/exospherehost/failproofai)

 Like the host-side enforcement here. The "VM cannot push" property holds even if the agent gets root inside the VM, which the in-process approaches (Claude Code permissions, harness hook policies) cannot match.

 These layers compose well. bwrap gives a kernel-enforced perimeter around the agent, but inside the sandbox the agent can still happily `rm -rf /mnt/repo/build` and clobber a sibling directory, or `git reset --hard` over uncommitted changes you wanted to review. A PreToolUse hook that catches those calls before they reach the FUSE layer turns "agent destroyed your branch but at least it stayed in the mount" into "agent got told no and tried something else." Even with this setup I'd still want `block-rm-rf` running in the harness on top.
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 15-15: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@drafts/2026-05-03T191243Z.md` around lines 15 - 21, The markdown fenced block
that begins with the disclosure line is missing a language tag, causing
markdownlint MD040; update the opening code fence (the ``` that precedes
"(disclosure: I work on FailProof AI...") to include a language identifier such
as text (i.e. change ``` to ```text) so the block is explicitly tagged and the
lint error is resolved.


- This thread is a good template for the "complementary, not competing" framing. The bwrap+sshfs setup is a *strong outer perimeter*: kernel-enforced, root-in-VM-resistant, and unbypassable by anything inside the agent. The natural FailProof pitch isn't "you don't need this if you have FailProof" - it's "this protects the host from the agent; FailProof protects the repo contents from the agent." Two threat models, two layers.
- A blog post titled something like *"Sandboxing the agent vs. policy-gating the agent: when do you need both?"* would land with this audience. The argument writes itself: bwrap stops the agent from `cat /etc/shadow` on the host, but does nothing if the agent runs `git reset --hard` inside the mount. Hook-layer policies do the inverse. Real setups want both.
- The OP's design has a feature FailProof currently lacks but could add: *baked-in path scoping per agent invocation*. The `command="...sftp-force-directory /path/to/repos-claude" ` line in `authorized_keys` makes the path-allowlist part of the credential rather than the agent config. There's a clean analog for the harness side: a per-session "scope" (cwd allowlist, write-target allowlist) injected via env at agent-start time, that custom policies can read and enforce. Worth considering as a `--scope <dir>` ergonomics improvement on top of the existing `block-read-outside-cwd` / `allowPaths`.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove the trailing space inside the inline code span.

There is an extra space before the closing backtick in the authorized_keys example (markdownlint MD038).

Proposed fix
-- The OP's design has a feature FailProof currently lacks but could add: *baked-in path scoping per agent invocation*. The `command="...sftp-force-directory /path/to/repos-claude" ` line in `authorized_keys` makes the path-allowlist part of the credential rather than the agent config. There's a clean analog for the harness side: a per-session "scope" (cwd allowlist, write-target allowlist) injected via env at agent-start time, that custom policies can read and enforce. Worth considering as a `--scope <dir>` ergonomics improvement on top of the existing `block-read-outside-cwd` / `allowPaths`.
+- The OP's design has a feature FailProof currently lacks but could add: *baked-in path scoping per agent invocation*. The `command="...sftp-force-directory /path/to/repos-claude"` line in `authorized_keys` makes the path-allowlist part of the credential rather than the agent config. There's a clean analog for the harness side: a per-session "scope" (cwd allowlist, write-target allowlist) injected via env at agent-start time, that custom policies can read and enforce. Worth considering as a `--scope <dir>` ergonomics improvement on top of the existing `block-read-outside-cwd` / `allowPaths`.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- The OP's design has a feature FailProof currently lacks but could add: *baked-in path scoping per agent invocation*. The `command="...sftp-force-directory /path/to/repos-claude" ` line in `authorized_keys` makes the path-allowlist part of the credential rather than the agent config. There's a clean analog for the harness side: a per-session "scope" (cwd allowlist, write-target allowlist) injected via env at agent-start time, that custom policies can read and enforce. Worth considering as a `--scope <dir>` ergonomics improvement on top of the existing `block-read-outside-cwd` / `allowPaths`.
- The OP's design has a feature FailProof currently lacks but could add: *baked-in path scoping per agent invocation*. The `command="...sftp-force-directory /path/to/repos-claude"` line in `authorized_keys` makes the path-allowlist part of the credential rather than the agent config. There's a clean analog for the harness side: a per-session "scope" (cwd allowlist, write-target allowlist) injected via env at agent-start time, that custom policies can read and enforce. Worth considering as a `--scope <dir>` ergonomics improvement on top of the existing `block-read-outside-cwd` / `allowPaths`.
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 27-27: Spaces inside code span elements

(MD038, no-space-in-code)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@drafts/2026-05-03T191243Z.md` at line 27, The inline code span contains a
trailing space before the closing backtick in the example
`command="...sftp-force-directory /path/to/repos-claude" `; remove the extra
space so it reads `command="...sftp-force-directory /path/to/repos-claude"` to
satisfy markdownlint MD038 and eliminate the trailing-space inside the inline
code span.

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