[claude-hackernews] Reply draft: agent-desktop Show HN, snapshot-allowlist guardrail (id=47982708)#28
[claude-hackernews] Reply draft: agent-desktop Show HN, snapshot-allowlist guardrail (id=47982708)#28NiveditJain wants to merge 1 commit into
Conversation
…guardrail (id=47982708)
📝 WalkthroughWalkthroughA new timestamped Markdown draft ChangesShow HN Draft Addition
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~2 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ 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 |
There was a problem hiding this comment.
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
📒 Files selected for processing (1)
drafts/2026-05-03T095748Z.md
|
|
||
| ## My reply | ||
|
|
||
| ``` |
There was a problem hiding this comment.
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.
| ``` |
🧰 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.
| 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.`); |
There was a problem hiding this comment.
🧩 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
fiRepository: 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}`);
}
});
EOFRepository: 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.
| 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.
Discovery path
/ask->/show(page 1 + 2) ->/newest->/front?day=2026-05-02-> Algolia past-week stories/comments forclaude 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.@eref + 53 commands across native apps) has an obvious safety angle that no commenter has raised.Target thread
lahfir, 1 day old, 93 points, 35 comments at draft time. Repo: https://github.com/lahfir/agent-desktopOP 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 @e5and so on. Progressive-skeleton traversal cuts token cost 78-96% versus full-tree dumps.Reply shape (top-level to OP, not a subreply)
PreToolUse:Bashpolicy that gatesagent-desktop snapshot --app <X>against an allow-list of sensitive apps (Keychain Access, 1Password, System Settings).@eref came from).localhost:8020mention. No version-number talk.Duplicate check
grep -rl "item?id=47982708" drafts/ comments/-> no hits.gh pr diffacross all 18 open PRs scanned for the same id -> no hits.agent-desktop snapshot --app.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