Back to skill

Security audit

AI Shield — OpenClaw Security Audit

Security checks for vulnerabilities and agentic risk

Overview

This is a local OpenClaw config auditing tool, but its sanitizer is advertised for sharing while using incomplete redaction rules that can leave secrets behind.

Install only if you treat it as a local heuristic audit aid. Do not assume its sanitize command makes a config safe to share; manually review sanitized output and avoid sharing live OpenClaw configs that may contain tokens, gateway credentials, cookies, or private keys.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
src/audit.js:341
Finding
Secret leakage audit skips nested and nonstandard configuration locations<![CDATA[ ## Vulnerability Details **File Location**: `src/audit.js:341-422` **Vulnerability Type**: Incomplete recursive secret detection **Risk Level**: Medium ### Vulnerable Code ```javascript const configStr = JSON.stringify(config); const foundSecrets = new Set(); // Check top-level env scanObj('env', config.env || {}, secretPatterns, push, foundSecrets); // Check skill entries env const skills = (config.skills && config.skills.entries) || {}; for (const [skillName, skill] of Object.entries(skills)) { scanObj(`skills.entries.${skillName}.env`, skill.env || {}, secretPatterns, push, foundSecrets); } // Check channel configs for tokens const channels = config.channels || {}; for (const [chName, ch] of Object.entries(channels)) { if (ch.botToken) { for (const sp of secretPatterns) { if (sp.pattern.test(ch.botToken)) { const key = `channels.${chName}.botToken`; if (!foundSecrets.has(key)) { foundSecrets.add(key); push({ category: 'secret_leakage', severity: 'critical', issue: `Channel "${chName}" has a ${sp.type} in botToken — this is expected for channel config but MUST NOT be shared.`, recommendation: 'Ensure this config file is never shared, committed to git, or sent to external services without sanitization.', }); } } } } } // Check gateway auth token exposure const gwToken = (config.gateway && config.gateway.auth && config.gateway.auth.token) || ''; if (gwToken) { push({ category: 'secret_leakage', severity: 'medium', issue: 'Gateway auth token is stored in plaintext in the config file.', recommendation: 'Consider using environment variable references or a secrets manager for the gateway token.', }); } // Check remote token const remote = (config.gateway && config.gateway.remote) || {}; if (remote.token && remote.token ...[truncated 3414 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace shallow, location-specific scanning with recursive traversal of every object, array, key, and string value in the configuration. 2. Preserve the full property path for every detected value so findings remain actionable without printing the secret itself. 3. Either scan `configStr` or remove the unused variable; recursive structured traversal is preferable because it can report accurate paths. 4. Detect suspicious key names in addition to value formats, including `authorization`, `cookie`, `session`, `clientSecret`, `accessToken`, `refreshToken`, `webhook`, and equivalent variants. 5. Treat malformed or unexpected configuration structures safely rather than silently skipping them. 6. Add regression tests for secrets in nested objects, arrays, plugin-specific fields, custom channel properties, authorization headers, and neutral field names. 7. Document that pattern-based detection is heuristic and must not be treated as proof that a configuration contains no secrets. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/sanitize.js:11
Finding
Sanitizer can preserve common credentials in output represented as safe to share<![CDATA[ ## Vulnerability Details **File Location**: `src/sanitize.js:11-61` **Vulnerability Type**: Incomplete sensitive-data redaction **Risk Level**: High ### Vulnerable Code ```javascript const SECRET_KEY_PATTERNS = [ /key$/i, /token$/i, /secret$/i, /password$/i, /credential$/i, /private/i, ]; const SECRET_VALUE_PATTERNS = [ /^sk-or-v1-[a-f0-9]+$/i, // OpenRouter /^sk-[a-zA-Z0-9]+$/i, // Generic API key /^\d+:[A-Za-z0-9_-]{35,}$/, // Telegram bot token /^0x[a-fA-F0-9]{64}$/i, // Private key /^xai-[a-zA-Z0-9]+$/i, // xAI /^ghp_[a-zA-Z0-9]+$/i, // GitHub /^gho_[a-zA-Z0-9]+$/i, // GitHub OAuth /^glpat-[a-zA-Z0-9_-]+$/i, // GitLab /^AKIA[0-9A-Z]{16}$/i, // AWS ]; function sanitizeConfig(config) { return deepSanitize(JSON.parse(JSON.stringify(config)), []); } function deepSanitize(obj, path) { if (obj === null || obj === undefined) return obj; if (Array.isArray(obj)) { return obj.map((item, i) => deepSanitize(item, [...path, String(i)])); } if (typeof obj === 'object') { const result = {}; for (const [key, val] of Object.entries(obj)) { result[key] = deepSanitize(val, [...path, key]); } return result; } if (typeof obj === 'string') { const currentKey = path[path.length - 1] || ''; // Check if key name suggests a secret if (SECRET_KEY_PATTERNS.some(p => p.test(currentKey))) { return REDACTED; } // Check if value looks like a secret if (SECRET_VALUE_PATTERNS.some(p => p.test(obj))) { return REDACTED; } // Redact env sections aggressively if (path.includes('env') && obj.length > 20) { return REDACTED; } } return obj; } ``` ### Technical Analysis The recursive traversal is structurally sound, but its redaction decision is limited to: - A small set of secret-related key suffixes. - A small set of anchored credential formats. - Strings longer tha ...[truncated 2410 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Expand sensitive key-name matching to include authorization headers, cookies, sessions, access and refresh tokens, client secrets, webhook credentials, signing material, mnemonics, and provider-specific aliases. 2. Add detection for PEM private keys, JWTs, bearer values, connection strings with embedded credentials, session identifiers, webhook URLs, and additional current provider-token formats. 3. Normalize key names before matching so separators and naming styles such as `client_secret`, `client-secret`, and `clientSecret` are treated consistently. 4. Use conservative redaction for known credential containers and security-sensitive configuration sections, even when a value does not match a recognized token format. 5. Consider a configurable allowlist model for external sharing: retain only fields known to be nonsensitive rather than attempting to enumerate every possible secret format. 6. Add automated tests containing representative secrets under both descriptive and neutral field names, including values nested in objects and arrays. 7. Add a prominent warning that sanitization is heuristic and require manual review before sharing generated output. 8. Avoid logging, embedding, or returning detected secret values in diagnostic messages. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • 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 (5)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill description says it performs security auditing, but the documented behavior also includes sanitization/redaction and direct access to ~/.openclaw/openclaw.json, which are materially different capabilities. This mismatch can mislead users and orchestrators into granting or invoking broader file access than expected, especially because OpenClaw configs may contain tokens, secrets, and sensitive topology data.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill description says it performs security auditing, but the documented behavior also includes sanitization/redaction and direct access to ~/.openclaw/openclaw.json, which are materially different capabilities. This mismatch can mislead users and orchestrators into granting or invoking broader file access than expected, especially because OpenClaw configs may contain tokens, secrets, and sensitive topology data.

Credential Access

High
Category
Privilege Escalation
Content
{ pattern: /\b[0-9]+:[A-Za-z0-9_-]{35,}\b/, type: 'Telegram bot token' },
    { pattern: /0x[a-fA-F0-9]{64}/i, type: 'Private key (hex 256-bit)' },
    { pattern: /xai-[a-zA-Z0-9]{20,}/i, type: 'xAI API key' },
    { pattern: /ghp_[a-zA-Z0-9]{36,}/i, type: 'GitHub personal access token' },
    { pattern: /gho_[a-zA-Z0-9]{36,}/i, type: 'GitHub OAuth token' },
    { pattern: /glpat-[a-zA-Z0-9_-]{20,}/i, type: 'GitLab personal access token' },
    { pattern: /AKIA[0-9A-Z]{16}/i, type: 'AWS access key' },
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
{ pattern: /\b[0-9]+:[A-Za-z0-9_-]{35,}\b/, type: 'Telegram bot token' },
    { pattern: /0x[a-fA-F0-9]{64}/i, type: 'Private key (hex 256-bit)' },
    { pattern: /xai-[a-zA-Z0-9]{20,}/i, type: 'xAI API key' },
    { pattern: /ghp_[a-zA-Z0-9]{36,}/i, type: 'GitHub personal access token' },
    { pattern: /gho_[a-zA-Z0-9]{36,}/i, type: 'GitHub OAuth token' },
    { pattern: /glpat-[a-zA-Z0-9_-]{20,}/i, type: 'GitLab personal access token' },
    { pattern: /AKIA[0-9A-Z]{16}/i, type: 'AWS access key' },
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding
The skill instructs the agent to read a live user configuration file and references environment-capable execution, but it declares no explicit tool scope or permissions boundary. In a security-audit context this increases the chance of unnecessary access to sensitive local data such as secrets in config files or environment variables without clear user-visible limitation.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
bin/shield.js:49