Skip to content

Security: kazuki-sf/claude-wake

Security

SECURITY.md

Security

claude-wake was written to be safe to run unattended and was adversarially reviewed (security / cross-platform / correctness) before its first release. This document states the trust model plainly, including the residual risks the code does not try to defend against, so you can make an informed decision.

What it does and doesn't touch

  • No network. It makes zero network requests, contains no eval/new Function, and every process it spawns is a fixed system binary (open, osacompile, launchctl, xdotool, xclip, powershell.exe, …). Nothing attacker-named is ever executed.
  • Zero runtime dependencies. The published package is the code you read.

The one property that matters most

The text it pastes is always the static message from your config — it can never be derived from transcript or web content. A limit event is detected only from top-level fields of a transcript line (isApiErrorMessage, error/apiErrorStatus, sessionId); conversation content (including a webpage you summarize) lives in a nested JSON string and cannot forge those fields or fabricate a new transcript line. So a malicious page cannot make claude-wake paste attacker-controlled text into your agent.

Trust boundary

claude-wake trusts two directories as belonging to you:

  • ~/.claude/projects/** — Claude Code's own transcripts (the detection input)
  • ~/.claude-wake/** — its own state, logs, config, and (macOS) KeySender.app

Anything that can already write files as your user is out of scope — it can tamper with your shell, your editor, and your credentials regardless of this tool. Keep both directories owner-only (~/.claude-wake is created 0700).

Two residual amplifications worth naming, for a local same-user attacker (i.e. already past the boundary above):

  1. Planted transcript → forced submit. Someone who can write a <uuid>.jsonl under ~/.claude/projects can name a real open panel's session id and a reset time of "now", causing claude-wake to focus that panel and paste message + Enter — i.e. force-submit that panel's current input at a chosen time. The pasted text is still your static message (unless they also rewrite your config.json).
  2. KeySender.app is a TCC-privileged helper (macOS). It holds the Accessibility grant so the background daemon can paste. A same-user process that writes ~/.claude-wake/send-request.txt and launches the app could borrow that grant to paste clipboard text + Enter into VS Code (only — the target editor's bundle id is compiled into the app and verified). The real containment is the 0700 directory; treat its contents as security-sensitive.

Neither is remotely exploitable and neither grants arbitrary-app or arbitrary-keystroke control — they are honest notes about what a local attacker who is already inside the boundary could amplify.

Hardening already in place

  • Session ids are validated against a strict UUID pattern before any use; the message crosses process boundaries via stdin / a 0600 request file, never a shell string; URIs are built from validated ids + a scheme allow-shape (dangerous schemes like file/javascript are refused).
  • A resume message with a leading / or @ is neutralized so it can never be submitted as a slash-command or file-mention; message length is capped.
  • Keystrokes are sent only after verifying the target is frontmost (macOS bundle id / X11 title suffix / Windows foreground PID). Wayland can't be verified and is refused unless you set allowUnverifiedPaste: true.
  • The clipboard is written only after that verification passes.

Reporting

Found something? Please open a GitHub issue (or, for anything sensitive, mark it as such and we'll coordinate privately).

There aren't any published security advisories