Skip to content

[claude-hackernews] Reply draft: agent-desktop Show HN, snapshot-allowlist guardrail (id=47982708)#28

Open
NiveditJain wants to merge 1 commit into
mainfrom
hn-agent-desktop-snapshot-allowlist
Open

[claude-hackernews] Reply draft: agent-desktop Show HN, snapshot-allowlist guardrail (id=47982708)#28
NiveditJain wants to merge 1 commit into
mainfrom
hn-agent-desktop-snapshot-allowlist

Conversation

@NiveditJain
Copy link
Copy Markdown
Member

@NiveditJain NiveditJain commented May 3, 2026

Discovery path

  • Sweep: /ask -> /show (page 1 + 2) -> /newest -> /front?day=2026-05-02 -> Algolia past-week stories/comments for claude code broke, agent rm -rf, claude code hooks, claude code permission, agent sandbox, agent deleted, cursor agent, claude code allowlist, claude code wiped, guardrails agent, force push, yolo claude code, claude code my, claude code main, etc.
  • The FailProof-fit space is heavily exhausted by the cron's prior runs (18 open PRs already cover most agent-destructive-failure threads, the Cursor-deleted-Railway-DB recurrences, and adjacent Show HNs of policy / gateway / sandbox / hook-manager / agent-harness products).
  • Picked id=47982708 because (a) it is a Show HN of an adjacent category not yet covered (native-app driving via accessibility tree), (b) the OP explicitly invites design feedback, (c) the existing 35-comment subthread is mostly LLM-detection drama with no engaged design-substance reviewer, and (d) the design choice (stable @e ref + 53 commands across native apps) has an obvious safety angle that no commenter has raised.

Target thread

OP describes a Rust CLI exposing accessibility-tree state of native apps to an agent via 53 commands; loop is snapshot -> agent picks @eN -> click @e12 / type @e5 and so on. Progressive-skeleton traversal cuts token cost 78-96% versus full-tree dumps.

Reply shape (top-level to OP, not a subreply)

  • Disclosure line in parens at top.
  • ~115 words of substantive design engagement: acknowledges the snapshot-loop token-economy choice, identifies the stable-@e-ref blast-radius problem, proposes constraining the perception step rather than the action step, and one snippet showing a PreToolUse:Bash policy that gates agent-desktop snapshot --app <X> against an allow-list of sensitive apps (Keychain Access, 1Password, System Settings).
  • Closing line acknowledges the action-layer alternative and its tradeoff (tracking which app's tree an @e ref came from).
  • ASCII punctuation only. No install commands. No comma-list of policy names. One repo URL (in the disclosure line). No dashboard / localhost:8020 mention. No version-number talk.

Duplicate check

Per CLAUDE.md "Comments via PR (never direct post)"

Draft only. Did not click submit on HN, did not type into a composer, did not vote. Status: draft (pending manual post). After manual post, ping back with the comment permalink and we'll append it to the HN: line and re-commit.

Summary by CodeRabbit

  • Documentation
    • Added internal technical documentation containing architecture discussions and security policy considerations.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 3, 2026

📝 Walkthrough

Walkthrough

A new timestamped Markdown draft drafts/2026-05-03T095748Z.md is added containing a Show HN reply discussing agent-desktop's accessibility-tree snapshot workflow, risk perception constraints, a Bash policy example, and internal team insights on architecture framing and threat mitigation.

Changes

Show HN Draft Addition

Layer / File(s) Summary
Draft Content
drafts/2026-05-03T095748Z.md
New draft file containing Show HN reply summary, agent-desktop approach overview, risk-perception policy example, FailProof team insights on architecture tagging and opaque ref limitations, and operational notes on MCP/CLI session-lock and thread fit.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~2 minutes

Possibly related PRs

Poem

🐰✨ A draft born from thought, timestamped and true,
Agent-desktop tales with policies new,
Show HN whispers in markdown dressed,
Careful perception—the FailProof test! 📋

🚥 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 accurately and specifically identifies the main change: a reply draft to a Show HN post about agent-desktop, focusing on snapshot-allowlist guardrail design with the referenced HN item ID.
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: 4/5 reviews remaining, refill in 12 minutes.

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-03T095748Z.md`:
- Line 20: The fenced code block currently uses an untyped triple-backtick
fence; update the opening fence to include a language tag (e.g., change the
opening ``` to ```text or ```markdown) so the block is typed and MD040 is
satisfied, keeping the closing ``` unchanged; locate the untyped fenced block in
the markdown content and add the language tag to the opening fence.
- Around line 30-33: The regex used to parse toolInput?.command (const m =
(toolInput?.command ??
"").match(/agent-desktop\s+snapshot\s+--app\s+"?([^"\s]+)/)) stops at whitespace
and thus truncates quoted multi-word app names; update the pattern to properly
capture quoted multi-word names (for example:
/agent-desktop\s+snapshot\s+--app\s+(?:"([^"]+)"|([^\s]+))/) and then use the
captured group (m[1] || m[2]) when checking the blocklist before calling allow()
or deny(); ensure the code paths referencing m (variable m and functions
allow(), deny()) are updated to use the resolved appName.
🪄 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: 44b62800-f938-46cd-9dac-44296092de62

📥 Commits

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

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


## My reply

```
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 tag to the fenced block.

Line 20 uses an untyped fence and triggers MD040. Use text (or markdown) to keep lint clean.

Suggested fix
-```
+```text
📝 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
```
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 20-20: 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-03T095748Z.md` at line 20, The fenced code block currently
uses an untyped triple-backtick fence; update the opening fence to include a
language tag (e.g., change the opening ``` to ```text or ```markdown) so the
block is typed and MD040 is satisfied, keeping the closing ``` unchanged; locate
the untyped fenced block in the markdown content and add the language tag to the
opening fence.

Comment on lines +30 to +33
const m = (toolInput?.command ?? "").match(/agent-desktop\s+snapshot\s+--app\s+"?([^"\s]+)/);
if (!m) return allow();
if (["Keychain Access","1Password","System Settings"].includes(m[1])) {
return deny(`snapshot of "${m[1]}" blocked.`);
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 | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Check if the file exists and read the relevant section
if [ -f drafts/2026-05-03T095748Z.md ]; then
  echo "=== File content (lines 1-50) ==="
  head -50 drafts/2026-05-03T095748Z.md | cat -n
else
  echo "File not found. Searching for draft files..."
  find . -name "*.md" -path "*/drafts/*" -type f 2>/dev/null | head -20
fi

Repository: exospherehost/claude-hackernews

Length of output: 5495


🏁 Script executed:

# Test the regex behavior to verify the bypass claim
node <<'EOF'
// Test the original regex with multi-word app names
const originalRegex = /agent-desktop\s+snapshot\s+--app\s+"?([^"\s]+)/;

const testCases = [
  'agent-desktop snapshot --app "Keychain Access"',
  'agent-desktop snapshot --app Keychain Access',
  'agent-desktop snapshot --app "1Password"',
  'agent-desktop snapshot --app "System Settings"',
  'agent-desktop snapshot --app "System"',
];

console.log("=== Original Regex Test ===");
testCases.forEach(input => {
  const match = input.match(originalRegex);
  console.log(`Input: "${input}"`);
  console.log(`  Captured: ${match ? match[1] : 'NO MATCH'}`);
});

// Test the suggested fix
const suggestedRegex = /agent-desktop\s+snapshot\s+--app\s+(?:"([^"]+)"|([^\s]+))/;

console.log("\n=== Suggested Fix Regex Test ===");
testCases.forEach(input => {
  const match = input.match(suggestedRegex);
  if (match) {
    const app = match[1] ?? match[2];
    console.log(`Input: "${input}"`);
    console.log(`  Captured: "${app}"`);
  } else {
    console.log(`Input: "${input}"`);
    console.log(`  NO MATCH`);
  }
});

// Check against blocklist
const blocklist = ["Keychain Access", "1Password", "System Settings"];
console.log("\n=== Blocklist Matching ===");
testCases.forEach(input => {
  const match = input.match(originalRegex);
  if (match) {
    const blocked = blocklist.includes(match[1]);
    console.log(`Original regex - Input "${input}": captured="${match[1]}", blocked=${blocked}`);
  }
});
EOF

Repository: exospherehost/claude-hackernews

Length of output: 1440


Regex allows bypass for multi-word app names in the guardrail snippet.

On Line 30, ([^"\s]+) stops at whitespace, so quoted multi-word apps like "Keychain Access" or "System Settings" are truncated at the first space and fail to match the blocklist. Testing confirms: "Keychain Access" captures as "Keychain", and "System Settings" as "System", both unblocked despite being in the blocklist.

Suggested fix
-      const m = (toolInput?.command ?? "").match(/agent-desktop\s+snapshot\s+--app\s+"?([^"\s]+)/);
+      const m = (toolInput?.command ?? "").match(/agent-desktop\s+snapshot\s+--app\s+(?:"([^"]+)"|([^\s]+))/);
       if (!m) return allow();
-      if (["Keychain Access","1Password","System Settings"].includes(m[1])) {
-        return deny(`snapshot of "${m[1]}" blocked.`);
+      const app = m[1] ?? m[2];
+      if (["Keychain Access", "1Password", "System Settings"].includes(app)) {
+        return deny(`snapshot of "${app}" blocked.`);
       }
📝 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
const m = (toolInput?.command ?? "").match(/agent-desktop\s+snapshot\s+--app\s+"?([^"\s]+)/);
if (!m) return allow();
if (["Keychain Access","1Password","System Settings"].includes(m[1])) {
return deny(`snapshot of "${m[1]}" blocked.`);
const m = (toolInput?.command ?? "").match(/agent-desktop\s+snapshot\s+--app\s+(?:"([^"]+)"|([^\s]+))/);
if (!m) return allow();
const app = m[1] ?? m[2];
if (["Keychain Access", "1Password", "System Settings"].includes(app)) {
return deny(`snapshot of "${app}" blocked.`);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@drafts/2026-05-03T095748Z.md` around lines 30 - 33, The regex used to parse
toolInput?.command (const m = (toolInput?.command ??
"").match(/agent-desktop\s+snapshot\s+--app\s+"?([^"\s]+)/)) stops at whitespace
and thus truncates quoted multi-word app names; update the pattern to properly
capture quoted multi-word names (for example:
/agent-desktop\s+snapshot\s+--app\s+(?:"([^"]+)"|([^\s]+))/) and then use the
captured group (m[1] || m[2]) when checking the blocklist before calling allow()
or deny(); ensure the code paths referencing m (variable m and functions
allow(), deny()) are updated to use the resolved appName.

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