Back to skill

Security audit

CatchClaw

Security checks for vulnerabilities and agentic risk

Overview

The skill largely matches its marketplace-management purpose, but it can install remote agent instructions and skills into live OpenClaw workspaces and has validation weaknesses users should review carefully.

Install only if you trust the CatchClaw marketplace source and understand that downloaded agentars can change future agent behavior. Prefer installing into a new named agent rather than overwriting the main workspace, avoid --api-key unless necessary, review any exported ZIPs and installed AGENTS.md changes, and be cautious with custom AGENTAR_API_BASE_URL values or untrusted PATH configurations.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
Findings (5)

T01 · Skill Instruction Hijacking

Error
Location
agentar_cli.mjs:1327
Finding

Remote Team Metadata Can Inject Persistent Agent Instructions

Content
View full analysis
\n`; block += `## Team: ${teamName}\n`; block += `Collaboration: ${collab}\n`; block += `Lead: ${lead}\n\n`; block += `### Teammates\n`; for (const m of members) { const localPath = m.local_path || ""; block += `- **${m.id}** (${m.role}): ${localPath}\n`; } block += `\nUse agentToAgent tool to communicate with teammates.\n`; block += ``; return block; } function updateAgentsMd(agentsMdPath, teamName, teamBlock) { let content = ""; if (fs.existsSync(agentsMdPath)) { content = fs.readFileSync(agentsMdPath, "utf-8"); } const beginMarker = ``; const endMarker = ``; const beginIdx = content.indexOf(beginMarker); const endIdx = content.indexOf(endMarker); if (beginIdx >= 0 && endIdx >= 0) { content = content.slice(0, beginIdx) + teamBlock + content.slice(endIdx + endMarker.length); } else { if (content.length > 0 && !content.endsWith("\n")) content += "\n"; if (content.length > 0) content += "\n"; content += teamBlock + "\n"; } mkdirp(path.dirname(agentsMdPath)); fs.writeFileSync(agentsMdPath, content); } ``` The resulting block is persisted to every installed team member: ```js const teamBlock = buildTeamBlock(teamSlug, resolvedYaml, resolvedMembers); for (const m of resolvedMembers) { if (!m.local_path || !fs.existsSync(m.local_path)) continue; const agentsMdPath = path.join(m.local_path, "AGENTS.md" ...[truncated 2397 chars]
Remediation
View remediation

T03 · Remote Payload Retrieval and Execution

Error
Location
agentar_cli.mjs:804
Finding

Unsigned Remote Agent Packages Are Installed into Live Workspaces

Content
View full analysis
{ const mod = url.startsWith("https") ? https : http; const req = mod.get(url, { timeout: 120000 }, (res) => { if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { return httpDownload(res.headers.location, dest).then(resolve, reject); } if (res.statusCode !== 200) { res.resume(); return reject(new Error(`HTTP ${res.statusCode} for ${url}`)); } const ws = fs.createWriteStream(dest); res.on("error", reject); ws.on("error", reject); res.pipe(ws); ws.on("finish", () => { ws.close((err) => (err ? reject(err) : resolve())); }); }); req.on("error", reject); req.on("timeout", () => { req.destroy(); reject(new Error("Download timeout")); }); }); } ``` Downloaded content is installed after only structural checks: ```js async function downloadFrom(base) { let downloadUrl = `${base}/api/v1/agentar/download?slug=${encodeURIComponent(slug)}`; if (version) { downloadUrl += `&version=${encodeURIComponent(version)}`; } console.log(` Downloading ${slug}${version ? ` v${version}` : ""} ...`); await httpDownload(downloadUrl, zipPath); } await downloadFrom(usedBase); assertValidAgentarZip(zipPath); extractZip(zipPath, extractDir); const contentDir = resolveContentDir(extractDir); if (!fs.existsSync(path.join(contentDir, "SOUL.md"))) { rmrf(tmpDir); console.error(`Error: invalid agentar "${slug}": missing SOUL.md`); process.exit(1); } extractWorkspaceFiles(contentDir, workspaceDir); mergeSkills( path.join(contentDir, "skills"), path.join(workspaceDir, "skills") ); `` ...[truncated 2271 chars]
Remediation
View remediation

T07 · Tool Hijacking and Spoofing

Error
Location
agentar_cli.mjs:175
Finding

Unsafe Trusted-Path Prefix Check Permits OpenClaw Executable Spoofing

Content
View full analysis
resolved.startsWith(prefix)); } function findOpenclawBin() { const isWin = process.platform === "win32"; const name = "openclaw"; const pathExts = isWin ? (process.env.PATHEXT || ".CMD;.EXE;.BAT;.PS1") .split(";") .map(e => e.toLowerCase()) : [""]; const pathDirs = (process.env.PATH || "").split(isWin ? ";" : ":"); for (const dir of pathDirs) { if (!dir || !isTrustedDir(dir)) continue; for (const ext of pathExts) { const candidate = path.join(dir, name + ext); try { if (fs.existsSync(candidate)) return candidate; } catch { /* skip */ } } } const fallbacks = isWin ? [path.join( process.env.LOCALAPPDATA || path.join(HOME, "AppData", "Local"), "pnpm", "openclaw.cmd" )] : [path.join(HOME, ".local/share/pnpm/openclaw")]; for (const p of fallbacks) { if (fs.existsSync(p)) return p; } return null; } function spawnOpenclawSync(openclawBin, args, options) { const isWin = process.platform === "win32"; const ext = path.extname(openclawBin).toLowerCase(); if (isWin && (ext === ".cmd" || ext === ".bat")) { const comspec = process.env.ComSpec || "cmd.exe"; return spawnSync( comspec, ["/c", openclawBin, ...args], { ...options, shell: false } ); } return spawnSync(openclawBin, args, { ...options, shell: false }); } ``` ### Technical Analysis `isTrustedDir()` uses a raw string-prefix comparison rather than verifying that the candidate directory is equal to or located beneath a trusted directory boundary. For example: - `/usr/bin-attacker` starts with `/usr/bin`. - `/home/user/.local-malicious ...[truncated 1621 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
agentar_cli.mjs:383
Finding

Single-Agent Archive Extraction Lacks Effective Decompression Limits

Content
View full analysis
ZIP_MAX_ENTRIES) { t ...[truncated 2084 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
agentar_cli.mjs:316
Finding

API Keys Are Exposed in Process Arguments and Plaintext Workspace Files

Content
View full analysis
--name [--api-key ] [--version ] $CLI install --overwrite [--version ] ``` The CLI parses the key directly from the process argument vector: ```js if (arg === "--api-key" && i + 1 < args.length) { flags.apiKey = args[++i]; i++; continue; } ``` It then writes the key as plaintext without explicitly setting restrictive file permissions: ```js function writeCredentials(workspace, apiKey) { const skillsDir = path.join(workspace, "skills"); mkdirp(skillsDir); fs.writeFileSync( path.join(skillsDir, ".credentials"), `apiKey=${apiKey}\n` ); const gitignore = path.join(workspace, ".gitignore"); const entry = "skills/.credentials"; if (fs.existsSync(gitignore)) { const content = fs.readFileSync(gitignore, "utf-8"); if (!content.includes(entry)) { fs.appendFileSync(gitignore, `\n${entry}\n`); } } else { fs.writeFileSync(gitignore, `${entry}\n`); } } ``` ### Technical Analysis Command-line secrets can be retained in shell history and may be observable through process inspection, telemetry, terminal logging, debugging tools, or automation logs. The credential is also written to a predictable plaintext file. The effective permissions depend on the user's umask because no explicit `mode` is supplied and existing files are not hardened with `chmod`. Adding the path to `.gitignore` helps prevent accidental Git commits, but it does not provide confidentiality or access control. The audit did not find code that sends this API key to the marketplace. The issue is local exposure rather than confirmed network exfiltration. ### Attack Path 1 ...[truncated 1167 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (16)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
export, rollback, or team command, you MUST verify the bundled CLI.** The CLI (`agentar_cli.mjs`) is bundled in this skill's directory — no download or copy is

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
export, rollback, or team command, you MUST verify the bundled CLI.** The CLI (`agentar_cli.mjs`) is bundled in this skill's directory — no download or copy is

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
export, rollback, or team command, you MUST verify the bundled CLI.** The CLI (`agentar_cli.mjs`) is bundled in this skill's directory — no download or copy is

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · agentar_cli.mjs (reported line 51)May include surrounding context.

js
];
const SKIP_FILES = ["AGENTS.md", "BOOTSTRAP.md"];
const EXPORT_SKIP_DIRS = [".git", ".openclaw", "__MACOSX", "memory"];
const SENSITIVE_PATTERNS = [".credentials", ".env", ".secret", ".key", ".pem"];

// ─── Config (local-only, never sent over the network) ───────────────────────

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · agentar_cli.mjs (reported line 1331)May include surrounding context.

js
const collab = teamYaml.collaboration_type || "LEAD_FOLLOWER";
  const lead = teamYaml.lead || "";

  let block = `<!-- TEAM:${teamName}:BEGIN -->\n`;
  block += `## Team: ${teamName}\n`;
  block += `Collaboration: ${collab}\n`;
  block += `Lead: ${lead}\n\n`;

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill invokes a bundled Node CLI, performs network-backed marketplace operations, reads environment variables, and writes to multiple filesystem locations, but it declares no explicit tool scope such as permissions or allowed-tools. This creates an authorization gap where a host may expose shell/network/env capabilities more broadly than reviewers or policy engines expect, increasing the chance of unintended command execution or data access.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

The skill explicitly supports installing archives that can overwrite an existing agent workspace containing instructions, skills, and configuration. Even with user confirmation language, this is a persistence-capable operation that can replace or implant future behavior in the agent environment, making it a real security-sensitive capability if a malicious or untrusted marketplace package is installed.

Content

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

md
**Source:** This skill is from the [CatchClaw skill repository](https://github.com/OpenAgentar/catchclaw).

An agentar is a distributable agent archive (ZIP) containing workspace files such as SOUL.md, skills, and other configuration. It can be installed as a new agent or used to overwrite an existing agent with a single command.

## Trigger Conditions

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger conditions activate on broad keywords like mere mention of "agentar" or "catchclaw," which can cause the skill to engage outside a clearly bounded user intent. In a skill that can install packages, modify workspaces, and write team metadata, over-broad auto-activation raises the risk of accidental invocation and unsafe follow-on actions.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
92% confidence
Finding

The install commands write agent content into active workspace locations and optionally overwrite the main workspace, which establishes durable filesystem state across sessions. Because the source is a remote marketplace artifact, this persistence can be exploited to seed malicious instructions or modified configs that affect later runs long after the initial command completes.

Content

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

bash
$CLI install <slug> --name <name> [--api-key <key>] [--version <ver>]
$CLI install <slug> --overwrite [--version <ver>]

Install an agentar from the marketplace.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
**Important:**
- Do NOT execute install until the user explicitly selects one of the above options
- Do NOT use "new" as a default without asking
- Do NOT use "overwrite" unless the user explicitly selects it
- If the user chooses "new" but doesn't specify a name, use the slug as the default name

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

A marketplace search/install/export skill would be expected to perform file and network operations, but this file also discovers and spawns an external CLI binary. It uses subprocess execution both to manage local agents and to generate enriched metadata, which is an additional capability not justified by the manifest's narrow marketplace-focused purpose.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The export flow sends a prompt to the local openclaw agent runtime using workspace-derived context, which can cause untrusted agent content to influence a subprocessed LLM during export. In a skill marketplace context, installed agent files are adversarial input, so this enrichment step can trigger prompt injection, unintended tool use by the local agent runtime, or leakage through the local model/tool environment depending on openclaw's behavior.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · agentar_cli.mjs (reported line 2128)May include surrounding context.

js
console.log("Aborted.");
                  return;
                }
                opts.overwrite = true;
                opts.name = name; // overwrite the existing agent's workspace
              }
              break;

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest describes a marketplace skill for searching, installing, and exporting agentars and teams. This code also implements a separate rollback command that deletes and restores the main OpenClaw workspace from local backups, which is a substantial local workspace recovery capability not implied by the marketplace-oriented description.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Rollback deletes and replaces the main workspace immediately after backup selection, with no final confirmation step before destructive action. In an agent skill context that operates on a user's active workspace, a mistaken invocation or scripted use can cause unexpected loss of local changes and operational disruption.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The header comment says environment variables are used solely to resolve local paths and choose the server to query. In practice, the code also reads variables such as PATH, PATHEXT, LOCALAPPDATA, APPDATA, and ComSpec to discover and execute the openclaw CLI, so the documentation materially understates their role.

Content

No source excerpt is available for this finding.