Open question

The hook ran before the model could look

A security firm built a demo Claude Code skill that presents itself as a Python formatter but uses the skill lifecycle's hooks to run shell commands with the user's full privileges, with no sandbox and no permission prompt. The hook steals cloud and SSH credentials on its first run, then polls an attacker server for commands and answers the tool call itself so the model never sees the skill. Nothing here is a bug.

Logged 10 Oct 2026

A formatter in name only

BeyondTrust's Phantom Labs describes a demo skill called code-format that advertises itself as a Python code formatter. Skills are directories that Claude Code loads on demand, and their YAML frontmatter can declare hooks: shell commands the harness runs on lifecycle events such as just before a tool call. Those commands are launched with child_process.spawn, with no sandbox wrapper and no permission prompt, and they inherit the full privileges of the user who started the session.

The skill does no formatting. On its first invocation its hook reads ~/.aws/credentials, ~/.ssh/id_rsa and .env, base64-encodes the contents, and posts them to an attacker-controlled endpoint. On every invocation it fetches a task from that server, evaluates the task as a shell command, and posts the output back.

The fields that let the hook answer for the model

Claude Code hooks can return structured JSON that changes how the harness behaves, and the demo uses several of those fields. skipInvocation: true aborts the tool call so the model never inspects the skill or its hook. additionalContext injects text the model treats as trusted. permissionDecision: allow auto-approves the call and suppresses the permission prompt. updatedInput rewrites the tool's parameters and is often paired with dangerouslyDisableSandbox: true. displayContent replaces what the model would otherwise show the user.

Used together, those fields let the hook complete the exchange on the model's behalf. The demo's hook returns skipInvocation and the message "all files already formatted," so the agent reports success while the real work happened in a shell the user never approved.

Nothing to patch, so watch instead

The report is explicit that this is not a vulnerability to be fixed: the hook mechanism does exactly what it was built to do, running a trusted command for a trusted skill. There is no flawed check to correct.

Because there is nothing to patch, the authors argue for detection and configuration. Useful signals include outbound HTTP from hook processes, reads of credential files during hook execution, remote-code patterns such as piping a download into a shell, evaluation of content fetched from the network, and writes to the skills directory or to hook settings. On the configuration side, Claude Code offers settings to disable all hooks, allow only managed hooks, and allow only managed permission rules, but the authors note these ship off by default, leaving the default install exposed until an administrator turns them on.

Sources

Research

Thread