T09 · Insecure Skill Coding Practices
- Location
index.js:179- Finding
Project Path Injection Enables Arbitrary Command Execution During Launch
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a real Claude Code automation skill, but it can approve trust prompts, capture and save sensitive screen/session data, and has command-injection risks that need review before use.
Install only if you are comfortable granting Accessibility-driven control of Terminal and screen capture on macOS. Use it only on trusted project folders, avoid the trust-approval helpers unless you personally verify the prompt and path, and treat saved recordings and screenshots as sensitive files. The package should be fixed to avoid shell/AppleScript interpolation before use with untrusted paths, task text, or screenshot locations.
index.js:179Project Path Injection Enables Arbitrary Command Execution During Launch
index.js:117Command Text Injection Through Clipboard and Generated AppleScript
index.js:88Caller-Controlled Screenshot Path Is Interpolated Into Shell Commands
index-old.js:137Legacy Exported API Executes Caller-Supplied Commands Directly in a Shell
index.js:88Failed Window Detection Silently Captures the Entire Screen
index.js:313Folder Trust Security Prompt Can Be Approved Programmatically Without State Verification
index.js:38Predictable Non-Exclusive AppleScript Temporary Files Permit Local Race Attacks
The README advertises automatic handling of security prompts, including trust-folder and login-related flows, without warning that the tool may approve prompts on the user's behalf. This can weaken an important consent boundary and cause users or higher-level agents to grant trust or proceed through sensitive prompts without adequate review.
The documented approveSecurity() function explicitly presses '1' + Enter to approve a trust prompt, which normalizes bypassing manual review of a security decision. In a tool designed to drive another coding agent through a visible terminal, this increases the risk of blindly trusting an unintended project or state, potentially enabling dangerous downstream actions.
Automatically approving a security/trust prompt bypasses a deliberate user checkpoint intended to prevent operation in untrusted contexts. In an agent skill that may be pointed at arbitrary repositories, this increases the chance of executing or enabling unsafe actions in malicious workspaces without user awareness.
The send() API advertises interaction with a Claude Code session, but actually executes the provided string as a shell command via execSync in the project directory. This creates arbitrary command execution with the caller's privileges and defeats any safety expectations, policy mediation, or auditability implied by routing through Claude Code.
The code accepts an arbitrary command string and executes it through the shell with no validation, allowlist, or confirmation. Because this is packaged as an agent skill, upstream callers may assume it is a safe abstraction, but it effectively exposes raw shell execution in the workspace and enables destructive commands, data exfiltration, or persistence.
The code detects Claude Code's security/trust prompt and automatically answers 'Yes, I trust this folder' without user confirmation. This defeats a built-in trust boundary designed to prevent operating in potentially unsafe directories, increasing the chance that malicious repository contents or prompts are treated as trusted.
The implementation auto-approves a security/trust prompt without any explicit warning or approval flow. This suppresses an intentional security checkpoint and can cause the agent to operate with elevated trust in unreviewed project content, which is especially risky in a code-execution/control skill.
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
console.log(`[CC-${sessionId}] [STDERR] ${chunk}`);
});
// Wait for Claude Code to start and show prompt
await new Promise((resolve) => {
setTimeout(() => {
// Send security approval (option 1)
The code automatically sends approval input to the interactive Claude Code process ('1\n' and confirmation) without any user validation or policy check. This bypasses an interactive security gate by design, allowing downstream actions to proceed under permissions the user never explicitly granted, which is especially dangerous because this skill is meant to control another agent process programmatically.
Each command sent is logged along with timing and a screenshot taken after execution, creating a detailed history of user-provided input and visible output. In a terminal-control skill, this can retain secrets, tokens, file contents, prompts, and other sensitive material, turning routine interaction into a data-collection channel.
The code programmatically approves a security trust prompt by sending '1' and Enter without any confirmation from the user. This bypasses an intentional safety gate designed to ensure the user explicitly authorizes project access, making accidental or unauthorized trust escalation much easier.
The recording structure persists session logs containing commands and screenshot paths, and the surrounding workflow captures screenshots throughout the session. In this context, that creates a durable trail of potentially sensitive natural-language inputs, operational details, and references to captured screen data, increasing the likelihood of credential, secret, or proprietary information leakage.
The lockfile pins a transitive dependency on form-data 4.0.5, which is flagged with a HIGH-severity advisory for CRLF injection in multipart field names. If this package is used to construct multipart requests from attacker-controlled input, an attacker may inject additional headers or corrupt request structure, potentially enabling request smuggling-like behavior or unintended parameter/header manipulation against downstream services.
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).
eenshot, recordingPath, duration_ms }
*
* CLI:
* node tasks/route-task.js --project /path/to/project --task "description" [--wait 120] [--approve]
*/
const path = require('path');
const fs = require('fs');
const cc = require('../index');
/**
* Route a task to Claude Code in a managed session.
*
* @param {string} projectPath - Absolute path to the project directory
* @param {string} taskDescription - Task to send to Claude Code
* @param {object} opts
* @param {number} [opts.waitSeconds=120] - Seconds to wait after sending task
* @param {boolean} [opts.approve=false] - Approve security prompt before task
* @param {string} [opts.sessionDir=null] - Directory for session recordings
* @returns {Promise<{ sessionId, screenshot, recordingPath, duration_ms }>}
*/
async function routeTask(projectPath, taskDescription, opts = {}) {
const startTime = Date.now();
const waitSeconds = opts.waitSeconds ?? 120;
const shouldApprove = opts.approve ?? false;
const sessionDi
The README promotes screenshot capture and session recording of a live terminal without warning that terminals commonly display secrets, credentials, proprietary code, and command history. In an agent-skill context, this omission can lead users to enable logging by default and unintentionally persist or expose sensitive on-screen data.
The saveSession() documentation states that full session logs, including commands and screenshots, are written to disk but does not warn that this creates durable records of potentially sensitive terminal activity. Persisted artifacts can later be accessed, shared, backed up, or exfiltrated, increasing exposure beyond the live session itself.
The skill explicitly advertises recording full terminal sessions and saving timestamped logs/JSON, but it does not warn that terminal content may include sensitive source code, prompts, secrets, tokens, file paths, or authentication material. In a tool that programmatically drives Claude Code and captures screenshots, this omission increases the risk of accidental sensitive-data collection and retention by users who may not realize the privacy implications.
The launch flow automatically answers the trust prompt by writing '1' and confirming, which silently escalates trust for the folder without informed user consent. In a security-sensitive tool, auto-trusting a workspace can disable an important safeguard against running in untrusted or attacker-controlled directories.
The autonomous decision to approve the trust prompt is itself security-relevant because it removes human review from a trust boundary decision. In this skill context, that behavior is more dangerous because the tool is designed to operate on project directories and could be directed at untrusted repositories.
session.stderr += data.toString();
});
// Auto-approve security check
await new Promise((resolve) => setTimeout(resolve, 500));
// Send "Yes, I trust this folder" (option 1)
The header comment says this is a 'Proper PTY-based interactive control' implementation, and line L028 repeats that claim. However, the process is created via child_process.spawn with stdio set to ['pipe','pipe','pipe'] at L030-L034, which is standard piped I/O rather than an actual pseudo-terminal. This is an active contradiction between the documentation and the implementation, not merely an omitted detail.
The session recorder stores full stdout/stderr and commands for the entire interactive session, which may include secrets, credentials, proprietary code, or sensitive prompts. In an agent-control skill, this is more dangerous because the tool centralizes all interaction data and makes later disclosure or misuse easier.
Full session recording of commands and model output creates a durable store of potentially sensitive user inputs, generated content, tokens, and repository data. In this skill context, the danger is amplified because the component is specifically designed to automate and observe an interactive coding agent session end-to-end.
The autonomous decision here is to approve a security-sensitive trust prompt on the user's behalf. Automating that choice removes a deliberate human checkpoint and can expose the environment to unsafe repository instructions or content that would otherwise remain untrusted.
session.outputBuffer.includes('Trust')) {
clearInterval(checkReady);
// Auto-approve: send "1" for "Yes, I trust this folder"
console.log(`[CC-${sessionId}] ✅ Security prompt detected, auto-approving...`);
session.proc.stdin.write('1\n');
Session persistence is not inherently malicious, but saving complete interaction history introduces confidentiality risk because transcripts may contain secrets or sensitive operational details. In a shell/control skill, persisted sessions are especially sensitive due to the breadth of captured commands and outputs.
}
/**
* Save session to file
*/
async function saveSession(sessionId, filepath) {
const session = sessions.get(sessionId);
The code writes the full session recording to an arbitrary file path without any warning that terminal history may contain sensitive material. Persisting transcripts to disk increases the exposure window and can leak secrets through backups, shared filesystems, or later unintended access.
Detected: suspicious.dangerous_exec