Back to skill

Security audit

Ralph Loops

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed autonomous development loop, but its defaults run agents with permission checks disabled and expose underprotected dashboard, process, and Git controls.

Install only if you are comfortable running an autonomous coding loop with broad local authority. Use a disposable branch or isolated VM/container, provide only task-specific credentials, disable or restrict the dashboard to loopback with authentication, review diffs before any push or tag, and do not run it in repositories or workspaces containing sensitive files until the dashboard command-injection/XSS and unauthenticated control issues are fixed.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
dashboard/lib/ralph-reader.mjs:175
Finding

Shell Command Injection Through Attacker-Controlled Loop State

Content
View full analysis
/dev/null || true`, { encoding: 'utf8' }); const pids = result.trim().split('\n').filter(p => p && !killed.includes(p)); for (const pid of pids) { try { execSync(`kill ${pid} 2>/dev/null`); killed.push(pid); } catch (e) {} } } catch (e) {} } if (sessionId) { try { execSync(`pkill -f "${sessionId}" 2>/dev/null || true`); } catch (e) {} } ``` ### Technical Analysis The `sessionId` field is loaded from a JSON file under `/tmp` and interpolated directly into shell commands executed through `execSync`. No allowlist validation, shell escaping, or argument separation is applied. The active-loop scanner accepts every filename matching the broad `ralph-*.json` pattern: ```javascript const files = fs.readdirSync(TEMP_DIR) .filter(f => f.startsWith('ralph-') && f.endsWith('.json') && !f.includes('-done')); ``` Consequently, a local process, compromised autonomous agent, or other principal able to create a matching file in `/tmp` can place shell metacharacters in `sessionId`. When the dashboard kill endpoint is invoked, the value is interpreted by `/bin/sh` rather than passed solely as a literal process-search pattern. The same vulnerable value reaches both `pgrep` and `pkill`, providing two command-injection sinks. The loop identifier itself is also interpolated into a shell ...[truncated 1403 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
dashboard/routes/loops.mjs:148
Finding

Unauthenticated Network-Accessible Process Termination API

Content
View full analysis
{ console.log(`🎯 Q Dashboard running on http://localhost:${PORT}`); // ... console.log(` POST /api/loops/:id/kill - Kill session`); console.log(`🌐 CORS enabled for all origins`); }); ``` ```javascript // dashboard/routes/loops.mjs router.post('/:id/kill', async (req, res) => { try { const result = ralphReader.killLoop(req.params.id); if (result.success) { res.json({ success: true, message: result.message }); } else { res.status(400).json({ success: false, error: result.error }); } } catch (error) { console.error('Error killing loop:', error); res.status(500).json({ success: false, error: error.message }); } }); ``` ### Technical Analysis The endpoint that terminates processes has no authentication, authorization, anti-CSRF control, or origin validation. Any client able to connect to the dashboard can invoke it. Although the console message describes a localhost URL, `app.listen(PORT)` does not explicitly bind to `127.0.0.1`. Node.js normally listens on an unspecified address when the host is omitted, potentially making the service reachable through non-loopback interfaces depending on the host and firewall configuration. Global permissive CORS further allows arbitrary web origins to read API responses. The kill request is a simple unauthenticated `POST`, so a malicious website visited by the user may also be able to trigger it against a locally running d ...[truncated 1699 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
dashboard/public/index.html:359
Finding

Stored Cross-Site Scripting Through Unescaped Loop State

Content
View full analysis
function renderLoopCard(loop, isActive) { const status = loop.status || (loop.done ? 'completed' : 'running'); const displayName = loop.name || loop.id; const borderClass = status === 'running' ? 'running' : (loop.isSuccess ? 'success' : 'failed'); return `
${displayName}
${loop.name ? `
${loop.id}
` : ''}
Started: ${formatTime(loop.started)}
${status}
${isActive && status === 'running' ? `⏹️ Kill` : ''} 📋 History
`; } // ... activeContainer.innerHTML = runningLoops.map(l => renderLoopCard(l, true)).join(''); // ... archivedContainer.innerHTML = allArchived.map(l => renderLoopCard(l, false)).join(''); ``` ### Technical Analysis Values obtained from JSON state files are inserted directly into HTML strings and assigned to `innerHTML`. In particular: - `loop.n ...[truncated 2011 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/ralph-loop.mjs:242
Finding

Autonomous Agent Runs With Unrestricted Permissions Across the Entire Workspace

Content
View full analysis
/dev/null || { echo "Creating remote branch..." git push -u origin "$CURRENT_BRANCH" 2>/dev/null || true } fi ``` ```markdown # templates/PROMPT_build.md 0a. Study `specs/*` with up to 500 parallel Sonnet subagents to learn the application specifications. 0b. Study @IMPLEMENTATION_PLAN.md. 0c. For reference, the application source code is in `src/*`. 1. Your task is to implement functionality per the specifications using parallel subagents. 4. When the tests pass, update @IMPLEMENTATION_PLAN.md, then `git add -A` then `git commit` with a message describing the changes. After the commit, `git push`. ``` ### Technical Analysis The Node.js runner always launches Claude Code with `--dangerously-skip-permissions`, disabling interactive permission checks for tool use. It also fixes the working directory at the user's complete `~/clawd` workspace rather than the specific project directory associated with the requested task. The agent is instructed to study repository-controlled specifications, plans, source files, and operational instructions. These inputs are not established as trusted. A ma ...[truncated 2507 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
Findings (38)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 87)May include surrounding context.

md
| Generic | Create prompt file, run `ralph-loop.mjs` directly |

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
65% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · SKILL.md (reported line 517)May include surrounding context.

md
- Only the API keys needed for the task
- No access to private data beyond requirements
- Restrict network connectivity where possible
- **Escape hatches:** Ctrl+C stops the loop; `git reset --hard` reverts uncommitted changes

---

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The class name RalphReader and the surrounding method documentation describe read-oriented operations such as getting active, archived, or single loops. However, killLoop() executes pgrep/kill/pkill against matching processes and writes a -done.txt file, which are active side effects that contradict the implied read-only intent of the module.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: path-to-regexp==0.1.12 — 1 advisory(ies): CVE-2024-45296 (path-to-regexp vulnerable to Regular Expression Denial of Service via multiple r)

High
Category
Supply Chain
Confidence
94% confidence
Finding

The lockfile includes path-to-regexp 0.1.12, a version associated with Regular Expression Denial of Service. Because Express uses this library to compile and match route patterns, crafted requests can potentially trigger excessive backtracking and tie up the Node.js event loop, making this especially relevant for an HTTP-facing dashboard.

Content

No source excerpt is available for this finding.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/ralph-loop.mjs (reported line 132)May include surrounding context.

js
return readFileSync(promptArg, 'utf8');
  }
  // Otherwise treat as inline prompt
  return promptArg;
}

// Load/save state

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The script launches the agent with --dangerously-skip-permissions, explicitly disabling safety checks while feeding it prompts that may come from files or inline input. Because the agent is instructed to write files and operate iteratively, this greatly increases the risk of unauthorized filesystem changes, command execution, or persistence if the prompt is malicious or the model behaves unsafely.

Content

No source excerpt is available for this finding.

Memory Manipulation

High
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Content

Scanner excerpt · scripts/ralph-loop.mjs (reported line 441)May include surrounding context.

js
state.iteration = currentIter;  // Record completed iteration
      state.done = true;
      state.completedAt = new Date().toISOString();
      delete state.runningIteration;
      saveState(state);
      
      console.log(`\n✅ RALPH COMPLETE after ${state.iteration} iterations!`);

Memory Manipulation

High
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Content

Scanner excerpt · scripts/ralph-loop.mjs (reported line 455)May include surrounding context.

js
state.iteration = currentIter;  // Record completed iteration
      state.done = true;
      state.completedAt = new Date().toISOString();
      delete state.runningIteration;
      saveState(state);
      
      console.log(`\n✅ RALPH COMPLETE after ${state.iteration} iterations!`);

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The inline comments describe headless execution in a neutral way, but the actual command includes --dangerously-skip-permissions, which disables user approval for all Claude tool calls. This mismatch is dangerous because it obscures that the model can perform filesystem, shell, or related actions autonomously, increasing the likelihood that operators run the script without appreciating its privilege level.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script invokes Claude with --dangerously-skip-permissions, meaning all tool calls are pre-approved with no user confirmation. In the context of an autonomous loop that repeatedly feeds prompts to an agent, this creates a high-risk execution environment where prompt-induced or accidental actions can modify files, execute commands, or access sensitive data unchecked.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The quick-start and build instructions encourage users to launch an autonomous loop that can modify source code, run commands, and create commits, but they do not consistently repeat the destructive-risk warning at the exact invocation points. In a skill explicitly designed for unattended iterative code changes, omission of inline safety warnings increases the chance of accidental execution in the wrong repository or environment.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 626)May include surrounding context.

Claude API directly:

bash
# Replace loop.sh with API calls using curl or a script
curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "content-type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 627)May include surrounding context.

Claude API directly:

bash
# Replace loop.sh with API calls using curl or a script
curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"model": "claude-sonnet-4-20250514", "max_tokens": 8192, "messages": [...]}'

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

This is a real bug: pricing is declared with const and then reassigned in the unknown-model fallback path, which will throw a runtime error instead of applying the documented default pricing. If an attacker or even normal input can supply an unexpected model string, cost calculation can fail entirely, causing denial of service for billing/UI flows or preventing accurate usage accounting.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The killSession method executes a chat.abort command that terminates a session, which is a destructive operation. While the code has an internal docstring, there is no user-facing confirmation prompt, warning message, or visible disclosure before performing the abort.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The killLoop method performs destructive actions by sending kill signals to processes matched via pgrep/pkill and writing a done marker, but there are no in-code guardrails such as authorization checks, confirmation hooks, or validation that the matched processes truly belong to the intended loop. In a dashboard/backend context, if this method is exposed to untrusted or low-privilege callers, it could be abused to terminate unrelated processes that happen to match the pattern, causing denial of service.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

Lines L218-L223 show the function writes a -done.txt marker and explicitly states the state file is kept for history. Yet at L227 the success message says state file removed, which directly contradicts the actual behavior and could mislead callers about what side effects occurred.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The code fetches and displays full transcript and thinking data for a session, which can contain sensitive user or system information. There is no visible disclosure, confirmation, or warning in this file that opening a transcript may reveal private session contents.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The doc comment at L159 says "GET /api/loops/:id/kill - Kill a running loop", but the actual route is registered with router.post at L161. This is an active contradiction in intent/documentation, especially important because the endpoint performs a destructive action.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The POST /api/loops/:id/kill route performs a destructive action by terminating a running loop, but the code shows no confirmation prompt, cautionary comment/docstring about impact, or other user-facing disclosure beyond the endpoint name. For code files, destructive or irreversible operations should have some visible warning unless clearly covered elsewhere, and this file does not provide one.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The header comment claims the tool uses clawdbot agent, but the implementation actually spawns claude with --dangerously-skip-permissions. This mismatch can mislead operators and reviewers about the trust boundary and safety model, causing them to run a far more privileged workflow than documented.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

--check-cmd is passed directly to execSync, which executes arbitrary shell commands supplied by the user. In a skill/agent context this is dangerous because untrusted configuration, wrappers, or copied command examples can lead to local code execution, data exfiltration, or destructive actions before every loop iteration.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The prompt explicitly instructs the agent to run git add -A, git commit, and git push, which grants repository-wide modification and remote publication authority without any requirement for user approval or scope limitation. In a reusable build skill with unknown downstream use, this is dangerous because an agent can exfiltrate code, publish unintended changes, or alter repository history as part of normal execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The prompt tells the agent to push commits to the remote repository without any warning, confirmation, or distinction between trusted and untrusted contexts. This is a direct safety issue because remote pushes are irreversible from the agent's perspective and can publish sensitive, broken, or attacker-influenced changes beyond the local environment.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The prompt directs the agent to create git tags whenever build or test errors are absent, extending its authority into release-management operations unrelated to simply implementing code. Automatic tagging can trigger CI/CD pipelines, create misleading release artifacts, or mutate repository state in ways the user did not intend.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
dashboard/lib/ralph-reader.mjs:202

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/ralph-loop.mjs:256