Back to skill

Security audit

ClawBuddy Buddy

Security checks for vulnerabilities and agentic risk

Overview

The skill largely matches its stated ClawBuddy buddy purpose, but it has review-worthy privacy and local-integrity risks around reading workspace memory, broad env loading, and temporary consultation files.

Review carefully before installing. Use only a dedicated skill-local .env, keep GATEWAY_URL on literal loopback, avoid generate --all on private workspaces unless you have reviewed the outgoing source set, inspect generated pearls before publishing or uploading, and avoid running the production systemd service until the /tmp consultation-file handling is hardened.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
scripts/generate-pearls.js:36
Finding
Raw Private Workspace Data Can Be Transmitted to a Network Gateway<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate-pearls.js:36-45, 85-99, 120-166, 251-269, 285-300`; related destination validation in `scripts/lib/url-utils.js:24-42` **Vulnerability Type**: Sensitive-data exposure through insufficient destination restrictions and post-transmission sanitization **Risk Level**: High ### Vulnerable Code ```javascript // Security: Only allow localhost gateways for pearl generation // Pearl generation reads sensitive workspace files (MEMORY.md, AGENTS.md, TOOLS.md) // and sends content to the gateway. Remote gateways = data exfiltration risk. if (!isLocalhostUrl(GATEWAY_URL)) { console.error('❌ SECURITY: Pearl generation only works with localhost/private network gateways.'); console.error(` GATEWAY_URL (${GATEWAY_URL}) appears to be a remote host.`); console.error(' Pearl generation reads sensitive workspace files and sends to the gateway.'); console.error(' Use a local gateway (127.0.0.1, localhost, 10.x.x.x, 192.168.x.x).'); process.exit(1); } ``` ```javascript async function callGateway(messages) { const res = await fetch(`${GATEWAY_URL}/v1/chat/completions`, { method: 'POST', headers: { 'Authorization': `Bearer ${GATEWAY_TOKEN}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ model: MODEL, messages, max_tokens: 8192, }), }); if (!res.ok) { const errText = await res.text(); throw new Error(`Gateway error: ${res.status} ${errText}`); } const data = await res.json(); return data.choices?.[0]?.message?.content || ''; } ``` ```javascript const memory = readFileIfExists(path.join(WORKSPACE, 'MEMORY.md')) || readFileIfExists(path.join(WORKSPACE, 'memories', 'MEMORY.md')); if (memory) { const section = `## MEMORY.md (Long-term Memory)\n${memory}`; sections.push(section); totalChars += section.length; } const userMemory = readFileIfExists(path.join(WORKSPACE, 'USER.md')) || readFileIfExists(path.j ...[truncated 3460 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict the default gateway policy to literal loopback destinations only: - `127.0.0.0/8` - `::1` - `localhost` 2. Do not treat RFC 1918 or `.local` destinations as equivalent to localhost. 3. Require explicit, informed user approval before transmitting workspace content to any non-loopback destination. 4. Display the resolved destination, selected source files, and approximate payload size before transmission. 5. Exclude `USER.md`, raw memory, and agent configuration by default. Prefer an explicit allowlist of reviewed files. 6. Perform deterministic local redaction before constructing the network request. Do not rely on an LLM prompt as the privacy boundary. 7. Add secret scanning for API keys, tokens, passwords, private keys, URLs, IP addresses, and personal identifiers. 8. Provide a dry-run mode that writes the exact outgoing payload to a review file without sending it. 9. Separate gateway credentials for private-data processing from general gateway credentials and minimize their scope. 10. Require HTTPS and certificate validation for any explicitly approved non-loopback gateway. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/human-reply.js:12
Finding
Predictable Temporary Consultation Files Permit Local Injection and Symlink Attacks<![CDATA[ ## Vulnerability Details **File Location**: `scripts/human-reply.js:12-23`; corresponding consumer in `scripts/listen.js:365-374` **Vulnerability Type**: Unsafe temporary-file creation, unvalidated path construction, and symlink following **Risk Level**: High ### Vulnerable Code ```javascript const [sessionId, ...messageParts] = process.argv.slice(2); const message = messageParts.join(' '); if (!sessionId || !message) { console.error('Usage: node human-reply.js <session-id> "Your guidance here"'); console.error(''); console.error('Check /tmp/buddy-consult-*.txt for pending consultations.'); process.exit(1); } const consultFile = `/tmp/buddy-consult-${sessionId}.txt`; fs.writeFileSync(consultFile, message, 'utf-8'); console.log(`✅ Guidance written for session ${sessionId}`); console.log(` The buddy listener will pick this up and generate a response.`); ``` The listener consumes and deletes the same predictable path: ```javascript const consultFile = `/tmp/buddy-consult-${sessionId}.txt`; const pollInterval = setInterval(() => { try { if (fs.existsSync(consultFile)) { const humanInput = fs.readFileSync(consultFile, 'utf-8').trim(); fs.unlinkSync(consultFile); clearInterval(pollInterval); clearTimeout(timeoutHandle); pendingConsults.delete(sessionId); console.log(`👤 Human responded (${humanInput.length} chars)`); resolve(humanInput); } } catch {} }, 3000); ``` ### Technical Analysis The consultation mechanism uses a predictable pathname in the globally shared `/tmp` directory. It does not: - Validate `sessionId` - Reject path separators or traversal components - Create a private per-user directory - Use exclusive file creation - Disable symbolic-link following - Verify file ownership or file type - Set an explicit restrictive file mode - Authenticate the source of the guidance `fs.writeFileSync()` follows existing symbolic links. The listener subsequently follows the same path whe ...[truncated 2200 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate `sessionId` against the exact server-side identifier format, such as a canonical UUID. 2. Reject path separators, traversal sequences, control characters, and unexpected lengths. 3. Create a private runtime directory owned by the listener user with mode `0700`. 4. Create consultation files with mode `0600` and exclusive creation semantics. 5. Use no-follow behavior where supported and verify with `lstat` that the object is a regular file owned by the expected user. 6. Avoid separate existence checks; securely open the file first and operate through the returned descriptor. 7. Replace filesystem polling with authenticated local IPC, such as a Unix-domain socket in a private directory. 8. Authenticate consultation messages using a per-process secret or capability token. 9. Bind each consultation to a nonce generated by the listener rather than only a remotely supplied session ID. 10. Impose strict guidance size limits and record trusted audit metadata without logging sensitive content. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/lib/env.js:46
Finding
Overbroad Environment-File Discovery Accesses Unrelated Credentials and Allows Configuration Precedence Abuse<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lib/env.js:46-82` **Vulnerability Type**: Excessive secret-file access and unsafe implicit configuration discovery **Risk Level**: Medium ### Vulnerable Code ```javascript export function loadEnv({ silent = false } = {}) { const hermesHome = process.env.HERMES_HOME; const hermesProfile = process.env.HERMES_PROFILE; const candidates = [ path.join(SKILL_DIR, '.env'), path.join(process.cwd(), '.env'), hermesHome ? path.join(hermesHome, '.env') : null, hermesProfile ? path.join(os.homedir(), '.hermes', 'profiles', hermesProfile, '.env') : null, path.join(os.homedir(), '.hermes', '.env'), path.join(os.homedir(), '.openclaw', '.env'), path.join(os.homedir(), '.env'), ].filter(Boolean); for (const envPath of candidates) { if (fs.existsSync(envPath)) { if (!silent) console.log(`Loading env from: ${envPath}`); const content = fs.readFileSync(envPath, 'utf-8'); for (const line of content.split('\n')) { let trimmed = line.trim(); if (!trimmed || trimmed.startsWith('#')) continue; if (trimmed.startsWith('export ')) trimmed = trimmed.slice(7).trim(); const eqIdx = trimmed.indexOf('='); if (eqIdx < 0) continue; let key = trimmed.slice(0, eqIdx).trim(); let val = trimmed.slice(eqIdx + 1).trim(); val = stripInlineComment(val); if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'"))) { val = val.slice(1, -1); } if (process.env[key] === undefined) { process.env[key] = val; } } return; } } if (!silent) console.log('No .env file found in standard locations.'); } ``` ### Technical Analysis All scripts use a shared loader that searches several broad locations and imports every key from the first file found. These locations include the current working directory, the user's generic home `.e ...[truncated 2162 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Load configuration only from an explicit path, such as `CLAWBUDDY_ENV_FILE`, or a single Skill-local `.env`. 2. Do not automatically search the current working directory or generic home `.env`. 3. Parse only an allowlist of variables required by the Skill. 4. Ignore unrelated keys instead of copying every parsed value into `process.env`. 5. Check that the selected file is a regular file owned by the expected user. 6. Reject credential files with group- or world-writable permissions. 7. Report the selected configuration path before any network operation and require confirmation when it is outside the Skill directory. 8. Keep ClawBuddy and gateway credentials in a dedicated file containing no unrelated secrets. 9. Document exact precedence rules and provide a command that prints effective non-secret configuration. 10. For systemd deployment, use a dedicated service credential file with restrictive ownership and permissions rather than a broad OpenClaw-wide environment file. ]]>

T08 · Insecure Dependencies

Warning
Location
README.md:31
Finding
Unpinned Remote Installer Commands Create a Supply-Chain Execution Risk<![CDATA[ ## Vulnerability Details **File Location**: `README.md:31-38` **Vulnerability Type**: Unpinned third-party package retrieval and execution **Risk Level**: Medium ### Vulnerable Code ```bash ### OpenClaw npx clawhub@latest install clawbuddy-buddy ``` ```bash ### Compatible agents (via skills.sh) npx skills add clawbuddy-help/clawbuddy-buddy ``` ### Technical Analysis The documented installation flow invokes packages resolved from external package infrastructure without an exact reviewed version or integrity constraint. The explicit `@latest` reference guarantees that installation behavior can change after this Skill version has been reviewed. The second command also does not specify a package version. `npx` may download and execute package code. Therefore, compromise of the registry account, package publication pipeline, transitive dependency graph, or package-resolution source can result in code execution during installation. No evidence was found that this repository itself retrieves and executes a hidden remote payload. The risk arises from the documented unpinned installation commands rather than embedded malicious code. ### Attack Path 1. An attacker compromises the publisher account, registry package, release workflow, or a package dependency. 2. The attacker publishes a malicious version that is selected by `@latest` or the unversioned package request. 3. A user follows the README installation command. 4. `npx` downloads and executes the newly resolved package or its lifecycle behavior. 5. The malicious installer runs with the invoking user's privileges before the user can review the installed Skill. ### Impact Assessment A compromised installer can act with the privileges of the user running `npx`. Depending on that user's access, it could: - Read agent workspaces and home-directory credentials - Modify installed Skills or configuration - Steal API tokens - Install persistence under the user account - Execute arbitrary local comman ...[truncated 259 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin installer packages to exact reviewed versions rather than `@latest` or an unversioned reference. 2. Publish and verify cryptographic integrity hashes or signatures. 3. Include the expected package version and checksum in the installation documentation. 4. Use lockfiles where the installation mechanism supports them. 5. Recommend inspecting package metadata and downloaded contents before execution. 6. Disable or minimize lifecycle scripts where possible. 7. Document a manual installation path from a signed release archive. 8. Establish release provenance, protected publishing credentials, and reproducible build procedures. 9. Regularly audit transitive dependencies of the installer packages. 10. Avoid running installation commands with elevated privileges. ]]>
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (100)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
Uploading pearls to remote infrastructure is a distinct exfiltration path for local content, not merely SSE buddy interaction. Without a clear description, users may not appreciate that local markdown is transmitted off-host using bearer-token authentication.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
Uploading pearls to remote infrastructure is a distinct exfiltration path for local content, not merely SSE buddy interaction. Without a clear description, users may not appreciate that local markdown is transmitted off-host using bearer-token authentication.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
Uploading pearls to remote infrastructure is a distinct exfiltration path for local content, not merely SSE buddy interaction. Without a clear description, users may not appreciate that local markdown is transmitted off-host using bearer-token authentication.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
Uploading pearls to remote infrastructure is a distinct exfiltration path for local content, not merely SSE buddy interaction. Without a clear description, users may not appreciate that local markdown is transmitted off-host using bearer-token authentication.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
Uploading pearls to remote infrastructure is a distinct exfiltration path for local content, not merely SSE buddy interaction. Without a clear description, users may not appreciate that local markdown is transmitted off-host using bearer-token authentication.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
Uploading pearls to remote infrastructure is a distinct exfiltration path for local content, not merely SSE buddy interaction. Without a clear description, users may not appreciate that local markdown is transmitted off-host using bearer-token authentication.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
Uploading pearls to remote infrastructure is a distinct exfiltration path for local content, not merely SSE buddy interaction. Without a clear description, users may not appreciate that local markdown is transmitted off-host using bearer-token authentication.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
Uploading pearls to remote infrastructure is a distinct exfiltration path for local content, not merely SSE buddy interaction. Without a clear description, users may not appreciate that local markdown is transmitted off-host using bearer-token authentication.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Uploading pearls to remote infrastructure is a distinct exfiltration path for local content, not merely SSE buddy interaction. Without a clear description, users may not appreciate that local markdown is transmitted off-host using bearer-token authentication.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
Uploading pearls to remote infrastructure is a distinct exfiltration path for local content, not merely SSE buddy interaction. Without a clear description, users may not appreciate that local markdown is transmitted off-host using bearer-token authentication.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
Uploading pearls to remote infrastructure is a distinct exfiltration path for local content, not merely SSE buddy interaction. Without a clear description, users may not appreciate that local markdown is transmitted off-host using bearer-token authentication.

YARA rule 'agent_skill_prompt_injection_hidden_instructions': Prompt injection or hidden instructions embedded in AI agent skill text [agent_skills]

High
Category
YARA Match
Content
---
name: clawbuddy-buddy
description: Turn your AI agent into a ClawBuddy buddy — share knowledge with hatchlings via SSE.
homepage: https://clawbuddy.help
metadata:
  openclaw:
    emoji: "🦀"
    requires:
      env: ["CLAWBUDDY_TOKEN", "GATEWAY_URL", "GATEWAY_TOKEN"]
---

# ClawBuddy Buddy Skill 🦀

Turn your AI agent into a **buddy** — an experienced agent that helps hatchlings learn.

## Overview

Buddies are agents with specialized knowledge who answer questions from hatchlings (newer agents). Your agent connects to ClawBuddy via Server-Sent Events (SSE) and responds to questions using a local LLM gateway.

## Need Help Gettin
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

External Script Fetching

High
Category
Supply Chain
Content
Restart Hermes after changing env/config and verify with:

```bash
curl -sS http://127.0.0.1:8642/health
curl -sS http://127.0.0.1:8642/v1/models -H "Authorization: Bearer $GATEWAY_TOKEN"
```
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Ae1

High
Category
analysis-evasion
Content
Manage pearls with `node scripts/pearls.js`:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
Manage pearls with `node scripts/pearls.js`:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
Manage pearls with `node scripts/pearls.js`:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
Manage pearls with `node scripts/pearls.js`:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
Manage pearls with `node scripts/pearls.js`:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
Manage pearls with `node scripts/pearls.js`:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
Manage pearls with `node scripts/pearls.js`:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
Manage pearls with `node scripts/pearls.js`:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
Manage pearls with `node scripts/pearls.js`:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
Manage pearls with `node scripts/pearls.js`:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
Manage pearls with `node scripts/pearls.js`:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
Manage pearls with `node scripts/pearls.js`:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access, suspicious.install_untrusted_source (+1 more)

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/pearls.js:207

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/generate-pearls.js:31

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/listen.js:19

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/pearls.js:31

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/publications.js:30

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/report.js:25

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/setup.js:69

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/upload-pearl.js:26

Install source points to URL shortener or raw IP.

Warn
Code
suspicious.install_untrusted_source
Location
skill.json:21

Prompt-injection style instruction pattern detected.

Warn
Code
suspicious.prompt_injection_instructions
Location
SKILL.md:866