Back to skill

Security audit

Safe Guardian

Security checks for vulnerabilities and agentic risk

Overview

This skill presents itself as a protective OpenClaw enforcement layer, but the shipped code is only a weak helper and can approve dangerous operations if users rely on the documented API.

Do not rely on this skill as an OpenClaw enforcement boundary. Treat it only as an unsafe sample until it implements real tool interception, validates the documented API shape, parses commands structurally, applies deny rules before allow exceptions, removes broad sensitive-file defaults, and stops overwriting administrator policy on initialization.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
index.js:116
Finding

Allowlist Substring Matching Bypasses All Subsequent Security Checks

Content
View full analysis

Vulnerability Details

File Location: index.js:116-123 and index.js:143-151
Vulnerability Type: Allowlist policy bypass
Risk Level: High

Vulnerable Code

javascript
// Check allowlist
if (this.isWhitelisted(toolCall)) {
  return {
    allowed: true,
    reason: 'Whitelisted operation',
    type: 'whitelist'
  };
}
javascript
isWhitelisted(toolCall) {
  return this.whitelist.some(item => {
    // Simple allowlist matching logic
    return (
      (item.pattern && item.pattern.test(toolCall)) ||
      (item.command && toolCall.includes(item.command))
    );
  });
}

The relevant packaged allowlist includes entries such as:

json
{
  "command": "cat /etc/passwd",
  "reason": "Admin monitoring",
  "description": "Allow reading password file for admin monitoring"
}

Technical Analysis

Allowlist entries are matched using String.prototype.includes(). Consequently, an allowlist entry does not need to equal the submitted command; it only needs to appear anywhere within it.

Allowlist processing also occurs before blocklist and strict intent validation. Once isWhitelisted() returns true, checkToolCall() immediately returns an allowed decision. The remaining security controls are never evaluated.

This creates a policy bypass for compound shell commands. For example:

text
cat /etc/passwd; rm -rf /var/log

The complete string contains the allowlisted substring cat /etc/passwd. It is therefore approved even though its second command matches a destructive blocklist rule.

The library does not execute commands itself, so exploitation depends on an integrating application executing commands after receiving an allowed result. This is precisely the usage pattern promoted by the project documentation.

Attack Path

  1. Identify a packaged or administrator-added allowlist command, such as cat /etc/passwd or ...[truncated 1126 chars]
Remediation
View remediation

Remediation Suggestions

  1. Replace substring matching with exact matching of a normalized command representation.
  2. Parse commands using a shell-aware parser and validate the executable and each argument separately.
  3. Reject shell control operators, including command separators, pipelines, redirections, substitutions, and background execution, unless explicitly required and independently validated.
  4. Apply mandatory deny rules before allowlist exceptions.
  5. Split compound expressions and validate every command independently; one allowlisted component must not authorize the entire expression.
  6. Bind allowlist entries to an exact executable, approved arguments, permitted paths, and expected operation type.
  7. Remove sensitive generic entries such as cat /etc/passwd unless they are essential and constrained to an exact read-only operation.
  8. Add regression tests covering appended commands, prefixed commands, pipelines, command substitutions, newlines, and shell separators.

T09 · Insecure Skill Coding Practices

Error
Location
index.js:154
Finding

Textual Blocklist Matching Is Bypassable Through Equivalent Shell Syntax

Content
View full analysis

Vulnerability Details

File Location: index.js:154-170, with affected rules in index.js:74-111 and config/blacklist.json:2-58
Vulnerability Type: Incomplete command validation and blocklist evasion
Risk Level: High

Vulnerable Code

javascript
checkBlacklist(toolCall) {
  for (const rule of this.blacklist) {
    for (const pattern of rule.patterns) {
      const regex = new RegExp(pattern, 'i');
      if (regex.test(toolCall)) {
        return {
          blocked: true,
          reason: `Blocked by blacklist rule: ${rule.name}`,
          severity: rule.severity
        };
      }
    }
  }
  return { blocked: false };
}

Representative blocklist rules include:

javascript
patterns: [
  'rm -rf .*',
  'del .*',
  'delete .*'
]
javascript
patterns: [
  'useradd',
  'usermod',
  'chmod 777',
  'chown root',
  'su -'
]

Technical Analysis

The implementation treats policy strings as regular expressions and evaluates them directly against the unparsed command text. It does not normalize whitespace, executable paths, option order, combined options, quoting, escapes, environment prefixes, or shell indirection.

The rules therefore recognize only narrow textual representations rather than command semantics. For example, the pattern rm -rf .* requires the exact spacing and option form represented by the expression. An equivalent form using additional whitespace can evade the check:

text
rm  -rf /var/log

Other semantic variations may include reordered flags, separate or combined options, absolute executable paths, or commands invoked through another shell construct. Because the system returns allowed: true when no pattern matches, unknown or reformatted destructive operations fail open.

The strict-mode validator does not resolve the weakness. It uses another small set of raw regular expressions and is disabled by def ...[truncated 1152 chars]

Remediation
View remediation

Remediation Suggestions

  1. Do not use raw textual blocklists as the primary authorization boundary.
  2. Parse shell input into an abstract syntax tree and validate each executable, argument, redirection, substitution, and pipeline component.
  3. Normalize executable paths, whitespace, quoting, option forms, and argument ordering before policy evaluation.
  4. Prefer an allow-by-capability model in which only explicitly approved executable and argument combinations are accepted.
  5. Fail closed when parsing fails or when unsupported shell syntax is encountered.
  6. Make strict validation mandatory for security-sensitive integrations rather than optional.
  7. Use structured tool-call objects instead of accepting arbitrary shell command strings where possible.
  8. Add adversarial tests for whitespace variations, tabs, newlines, reordered flags, absolute paths, aliases, wrappers, escaping, substitutions, and pipelines.

T09 · Insecure Skill Coding Practices

Warning
Location
index.js:27
Finding

Initialization Unconditionally Overwrites Administrator-Supplied Blocklist Policy

Content
View full analysis

Vulnerability Details

File Location: index.js:27-30 and index.js:65-115
Vulnerability Type: Security configuration overwrite
Risk Level: Medium

Vulnerable Code

javascript
// Load configuration
this.loadBlacklist();
this.loadWhitelist();

// Create default blacklist if it does not exist
this.createDefaultBlacklist();
javascript
createDefaultBlacklist() {
  const defaultBlacklist = [
    {
      name: 'dangerous-exec',
      patterns: [
        'rm -rf /',
        'mkfs',
        'dd if=/dev/zero',
        'fdisk',
        'format',
        'shutdown',
        'reboot',
        'killall -9',
        'systemctl stop',
        'systemctl disable'
      ],
      severity: 'critical'
    },
    {
      name: 'data-deletion',
      patterns: [
        'rm -rf .*',
        'del .*',
        'delete .*'
      ],
      severity: 'high'
    },
    {
      name: 'system-modification',
      patterns: [
        'useradd',
        'usermod',
        'chmod 777',
        'chown root',
        'su -'
      ],
      severity: 'high'
    },
    {
      name: 'network-operation',
      patterns: [
        'iptables -F',
        'iptables -X',
        'iptables -t nat -F',
        'iptables -P INPUT DROP',
        'iptables -P OUTPUT DROP'
      ],
      severity: 'medium'
    }
  ];

  fs.writeFileSync(
    this.config.blacklistPath,
    JSON.stringify(defaultBlacklist, null, 2)
  );
  this.blacklist = defaultBlacklist;
}

Technical Analysis

The initialization sequence first loads the configured blocklist and then unconditionally calls createDefaultBlacklist(). Despite the comment claiming that defaults are created only when the file does not exist, the method contains no existence check.

Every construction of SafeGuardian consequently replaces both the in-memory blocklist and the blocklist ...[truncated 1461 chars]

Remediation
View remediation

Remediation Suggestions

  1. Call the default-policy creation method only when the configured blocklist file does not exist.
  2. Add an explicit existence check inside createDefaultBlacklist() as a second layer of protection.
  3. Never overwrite administrator policy during ordinary initialization.
  4. Keep packaged defaults immutable and merge them with user policy using a documented, deterministic precedence model.
  5. Write configuration changes atomically through a temporary file followed by a rename.
  6. Validate the loaded JSON schema and fail closed when the policy is malformed or unreadable.
  7. Log policy source, rule count, validation status, and any migration activity without exposing sensitive rule contents.
  8. Add tests proving that custom rules and packaged rules remain present after repeated initialization.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (39)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The documented behavior claims OpenClaw interception of exec/write/edit with strong safety guarantees, but the file shows only examples of a callable checker and also mentions filesystem writes for logs/config without declaring them. This mismatch is dangerous because operators may rely on the skill as an enforcement boundary when it may not actually be integrated, creating a false sense of protection while sensitive writes still occur.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% 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 143)May include surrounding context.

javascript
// 危险命令(会被阻止)
const result1 = guardian.checkToolCall('exec', {
  command: 'rm -rf /var/log',
  args: ['*.log']
});
// 结果: { allowed: false, reason: '安全检查失败:命令包含危险模式' }

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

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

Content

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

javascript
// 危险写操作
const result = guardian.checkToolCall('write', {
  path: '/etc/shadow',
  content: 'root:$1$...'
});
// 结果: { allowed: false, reason: '尝试写入系统核心文件' }

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% 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 199)May include surrounding context.

md
safetyScore: 0.967,
  lastCheck: '2026-04-06T22:00:00Z',
  recommendations: [
    '建议检查更多 rm 命令的使用',
    '可以考虑启用白名单模式'
  ]
}

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% 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 423)May include surrounding context.

md
const guardian = new SafeGuardian();

// 测试 1: 危险命令
console.log(guardian.checkToolCall('exec', { command: 'rm -rf /' }));

// 测试 2: 安全命令
console.log(guardian.checkToolCall('exec', { command: 'ls -la' }));

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% 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 347)May include surrounding context.

md
{
    "name": "dangerous-exec",
    "patterns": [
      "rm -rf /",
      "mkfs",
      "dd if=/dev/zero",
      "fdisk",

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% 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 · config/blacklist.json (reported line 5)May include surrounding context.

json
{
    "name": "dangerous-exec",
    "patterns": [
      "rm -rf /",
      "mkfs",
      "dd if=/dev/zero",
      "fdisk",

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

The presence of /etc/passwd in an execution whitelist maps to credential and account discovery behavior, enabling enumeration of valid local accounts and system structure. Even without password hashes, this information materially improves targeting, privilege escalation attempts, and lateral movement planning.

Content

Scanner excerpt · config/whitelist.json (reported line 3)May include surrounding context.

json
[
  {
    "command": "cat /etc/passwd",
    "reason": "Admin monitoring",
    "description": "Allow reading password file for admin monitoring"
  },

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

Allowing access to /etc/passwd grants attackers or untrusted workflows a built-in reconnaissance primitive that reveals local usernames, service accounts, shells, and filesystem paths. In the context of a plugin advertised as a protective interception layer, this exception is especially dangerous because it normalizes sensitive system inspection under a vague justification of 'Admin monitoring'.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% 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 · index.js (reported line 80)May include surrounding context.

js
{
        name: 'dangerous-exec',
        patterns: [
          'rm -rf /',
          'mkfs',
          'dd if=/dev/zero',
          'fdisk',

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% 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 · config/blacklist.json (reported line 32)May include surrounding context.

json
patterns: [
          'useradd',
          'usermod',
          'chmod 777',
          'chown root',
          'su -'
        ],

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% 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 · index.js (reported line 107)May include surrounding context.

js
patterns: [
          'useradd',
          'usermod',
          'chmod 777',
          'chown root',
          'su -'
        ],

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% 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 · index.js (reported line 220)May include surrounding context.

js
// 目前使用简单的规则引擎作为示例
    
    const suspiciousPatterns = [
      /rm -rf/gi,
      /dd if=\/dev/gi,
      /mkfs/gi,
      /format/gi

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
100% 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 64)May include surrounding context.

md
// 测试2: 危险的工具调用 (rm -rf)
console.log('2. 测试危险的工具调用 (rm -rf):');
const dangerousCall = 'rm -rf /var/log';
const result2 = guardian.checkToolCall(dangerousCall);
console.log('   工具调用:', dangerousCall);
console.log('   结果:', result2);

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
100% 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 143)May include surrounding context.

md
// 测试2: 危险的工具调用 (rm -rf)
console.log('2. 测试危险的工具调用 (rm -rf):');
const dangerousCall = 'rm -rf /var/log';
const result2 = guardian.checkToolCall(dangerousCall);
console.log('   工具调用:', dangerousCall);
console.log('   结果:', result2);

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
100% 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 347)May include surrounding context.

md
// 测试2: 危险的工具调用 (rm -rf)
console.log('2. 测试危险的工具调用 (rm -rf):');
const dangerousCall = 'rm -rf /var/log';
const result2 = guardian.checkToolCall(dangerousCall);
console.log('   工具调用:', dangerousCall);
console.log('   结果:', result2);

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
100% 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 423)May include surrounding context.

md
// 测试2: 危险的工具调用 (rm -rf)
console.log('2. 测试危险的工具调用 (rm -rf):');
const dangerousCall = 'rm -rf /var/log';
const result2 = guardian.checkToolCall(dangerousCall);
console.log('   工具调用:', dangerousCall);
console.log('   结果:', result2);

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
100% 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 · config/blacklist.json (reported line 5)May include surrounding context.

json
// 测试2: 危险的工具调用 (rm -rf)
console.log('2. 测试危险的工具调用 (rm -rf):');
const dangerousCall = 'rm -rf /var/log';
const result2 = guardian.checkToolCall(dangerousCall);
console.log('   工具调用:', dangerousCall);
console.log('   结果:', result2);

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
100% 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 · index.js (reported line 80)May include surrounding context.

js
// 测试2: 危险的工具调用 (rm -rf)
console.log('2. 测试危险的工具调用 (rm -rf):');
const dangerousCall = 'rm -rf /var/log';
const result2 = guardian.checkToolCall(dangerousCall);
console.log('   工具调用:', dangerousCall);
console.log('   结果:', result2);

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
100% 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 · test.js (reported line 18)May include surrounding context.

js
// 测试2: 危险的工具调用 (rm -rf)
console.log('2. 测试危险的工具调用 (rm -rf):');
const dangerousCall = 'rm -rf /var/log';
const result2 = guardian.checkToolCall(dangerousCall);
console.log('   工具调用:', dangerousCall);
console.log('   结果:', result2);

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% 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 64)May include surrounding context.

md
// 测试2: 危险的工具调用 (rm -rf)
console.log('2. 测试危险的工具调用 (rm -rf):');
const dangerousCall = 'rm -rf /var/log';
const result2 = guardian.checkToolCall(dangerousCall);
console.log('   工具调用:', dangerousCall);
console.log('   结果:', result2);

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% 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 · test.js (reported line 18)May include surrounding context.

js
// 测试2: 危险的工具调用 (rm -rf)
console.log('2. 测试危险的工具调用 (rm -rf):');
const dangerousCall = 'rm -rf /var/log';
const result2 = guardian.checkToolCall(dangerousCall);
console.log('   工具调用:', dangerousCall);
console.log('   结果:', result2);

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
100% 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 64)May include surrounding context.

md
// 测试2: 危险的工具调用 (rm -rf)
console.log('2. 测试危险的工具调用 (rm -rf):');
const dangerousCall = 'rm -rf /var/log';
const result2 = guardian.checkToolCall(dangerousCall);
console.log('   工具调用:', dangerousCall);
console.log('   结果:', result2);

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
100% 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 143)May include surrounding context.

md
// 测试2: 危险的工具调用 (rm -rf)
console.log('2. 测试危险的工具调用 (rm -rf):');
const dangerousCall = 'rm -rf /var/log';
const result2 = guardian.checkToolCall(dangerousCall);
console.log('   工具调用:', dangerousCall);
console.log('   结果:', result2);

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
100% 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 · test.js (reported line 18)May include surrounding context.

js
// 测试2: 危险的工具调用 (rm -rf)
console.log('2. 测试危险的工具调用 (rm -rf):');
const dangerousCall = 'rm -rf /var/log';
const result2 = guardian.checkToolCall(dangerousCall);
console.log('   工具调用:', dangerousCall);
console.log('   结果:', result2);

Static analysis

No suspicious patterns detected.