Back to skill

Security audit

Governance Inheritance

Security checks for vulnerabilities and agentic risk

Overview

The skill’s governance purpose is coherent, but it writes durable agent policy files and includes scripts with weak path containment and incomplete validation for security-sensitive policy data.

Review before installing. This skill is not shown exfiltrating data or running hidden commands, but it creates persistent governance files that can affect later agent behavior. Use only in a trusted workspace, keep GOVERNANCE_ROOT explicit and controlled, avoid untrusted organization/team/project/session names, and fix path containment plus schema validation before relying on it for security enforcement.

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

Error
Location
scripts/init_governance.py:133
Finding

Governance Root Escape Through Unsanitized Path Identifiers

Content
View full analysis
list[Path]: """Resolve the policy chain from root to leaf based on context.""" chain = [] # Organization org = context.get('organization', 'default') org_path = root / 'organizations' / org if org_path.exists(): chain.append(org_path) # Team team = context.get('team') if team: team_path = root / 'teams' / team if team_path.exists(): chain.append(team_path) # Project project = context.get('project') if project: project_path = root / 'project ...[truncated 2596 chars]
Remediation
View remediation
str: if not isinstance(value, str) or not IDENTIFIER.fullmatch(value): raise ValueError("Invalid governance identifier") if value in {".", ".."}: raise ValueError("Invalid governance identifier") return value ``` 2. Canonicalize the expected base and candidate paths before filesystem access: ```python base = (Path(path) / "teams").expanduser().resolve() candidate = (base / validate_identifier(name)).resolve() if not candidate.is_relative_to(base): raise ValueError("Policy path escapes the governance root") ``` 3. Apply the same validation and containment check to all identifiers received through JSON context. 4. Consider symlink attacks. Check containment after resolution and avoid following attacker-controlled symlinks where the deployment threat model permits them. 5. Do not overwrite an existing policy by default. Use exclusive creation mode (`x`) or require an explicit `--force` option after verifying the destination. 6. Add tests covering absolute paths, `../` traversal, nested separators, symlink escapes, empty identifiers, and valid identifiers. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/validate_chain.py:65
Finding

Incomplete Policy Validation and Unhandled Nested File Rules

Content
View full analysis
list[str]: """Validate a single policy file.""" errors = [] # Required fields if 'version' not in policy: errors.append(f"{path}: Missing 'version' field") if 'level' not in policy: errors.append(f"{path}: Missing 'level' field") if 'policies' not in policy: errors.append(f"{path}: Missing 'policies' section") # Validate level value valid_levels = {'organization', 'team', 'project', 'session'} if policy.get('level') not in valid_levels: errors.append(f"{path}: Invalid level '{policy.get('level')}'") # Validate inheritance if present inheritance = policy.get('inheritance', {}) mode = inheritance.get('mode', 'merge') if mode not in {'merge', 'override', 'isolate'}: errors.append(f"{path}: Invalid inheritance mode '{mode}'") return errors ``` ```python # scripts/validate_chain.py:90-129 def check_conflicts(chain: list[Path]) -> list[str]: """Check for conflicts across the policy chain.""" warnings = [] if len(chain) < 2: return warnings policies = [load_policy(p) for p in chain] # Check for deny/allow conflicts for i in range(len(policies) - 1): parent = policies[i] child = policies[i + 1] parent_level = parent.get('level', 'unknown') child_level = child.get('level', 'unknown') # Check for explicit denies that might be overridden parent_policies = parent.get('policies', {}) child_policies = child.get('policies', {}) for action_type in ['http', 'shell', 'file', 'browser']: parent_rules ...[truncated 4670 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Rogue AgentSelf-Modification, Session Persistence
Findings (32)

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 54)May include surrounding context.

md
shell:
    - command: "git *"
      action: allow
    - command: "rm -rf /*"
      action: deny
      reason: "Destructive command blocked"
    - command: "*"

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 · references/policy-schema.md (reported line 79)May include surrounding context.

md
shell:
    - command: "git *"
      action: allow
    - command: "rm -rf /*"
      action: deny
      reason: "Destructive command blocked"
    - command: "*"

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 · references/policy-schema.md (reported line 93)May include surrounding context.

md
shell:
    - command: "git *"
      action: allow
    - command: "rm -rf /*"
      action: deny
      reason: "Destructive command blocked"
    - command: "*"

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 54)May include surrounding context.

md
shell:
    - command: "git *"
      action: allow
    - command: "rm -rf /*"
      action: deny
      reason: "Destructive command blocked"
    - command: "*"

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 · references/policy-schema.md (reported line 79)May include surrounding context.

md
shell:
    - command: "git *"
      action: allow
    - command: "rm -rf /*"
      action: deny
      reason: "Destructive command blocked"
    - command: "*"

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 54)May include surrounding context.

md
shell:
    - command: "git *"
      action: allow
    - command: "rm -rf /*"
      action: deny
      reason: "Destructive command blocked"
    - command: "*"

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 · references/policy-schema.md (reported line 79)May include surrounding context.

md
shell:
    - command: "git *"
      action: allow
    - command: "rm -rf /*"
      action: deny
      reason: "Destructive command blocked"
    - command: "*"

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 · references/policy-schema.md (reported line 93)May include surrounding context.

md
shell:
    - command: "git *"
      action: allow
    - command: "rm -rf /*"
      action: deny
      reason: "Destructive command blocked"
    - command: "*"

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 · references/policy-schema.md (reported line 93)May include surrounding context.

md
Patterns match against the full command string:
- `git *` matches `git status`, `git commit`, etc.
- `docker run *` matches `docker run ubuntu`, etc.
- `rm -rf /*` matches exactly that dangerous command

## File Policies

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

inheritance: mode: merge # merge | override | isolate exceptions: # Policies that don't inherit - shell.sudo extensions: # Child can extend these - http.allowlist

text

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/inheritance-algorithm.md (reported line 151)May include surrounding context.

inheritance: mode: merge # merge | override | isolate exceptions: # Policies that don't inherit - shell.sudo extensions: # Child can extend these - http.allowlist

text

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/inheritance-algorithm.md (reported line 152)May include surrounding context.

inheritance: mode: merge # merge | override | isolate exceptions: # Policies that don't inherit - shell.sudo extensions: # Child can extend these - http.allowlist

text

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/inheritance-algorithm.md (reported line 155)May include surrounding context.

inheritance: mode: merge # merge | override | isolate exceptions: # Policies that don't inherit - shell.sudo extensions: # Child can extend these - http.allowlist

text

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/policy-schema.md (reported line 83)May include surrounding context.

inheritance: mode: merge # merge | override | isolate exceptions: # Policies that don't inherit - shell.sudo extensions: # Child can extend these - http.allowlist

text

Session Persistence

Medium
Category
Rogue Agent
Confidence
72% confidence
Finding

The skill initializes and stores governance state under ~/.openclaw/governance, creating persistent policy files outside the current session. Persistent modifications to a user's home directory can survive session boundaries and may silently alter future agent behavior if misused or if untrusted sessions can write these paths.

Content

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

python scripts/init_governance.py --level organization --path ~/.openclaw/governance

text

### 2. Create Team-Level Override

```bash
python scripts/init_governance.py --level team --name engineering --parent ~/.openclaw/governance/organization

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 100)May include surrounding context.

typescript
const result = await context.tools.governanceInheritance.evaluate({
  action: "http",
  details: { method: "GET", url: "https://api.example.com/data" },
  context: {
    sessionId: "sess_123",
    project: "my-project",

Session Persistence

Medium
Category
Rogue Agent
Confidence
66% confidence
Finding

The initPolicyLevel interface allows callers to create policy levels at arbitrary paths, which implies durable filesystem writes and potential cross-session persistence. Without explicit path restrictions and approval gates, a caller could place policy files in sensitive or globally effective locations that influence later sessions.

Content

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

md
- `level` (string): organization, team, project, or session
- `name` (string): Identifier for this level
- `parent` (string, optional): Path to parent policy
- `path` (string): Where to create the policy

### validatePolicyChain

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation states that child rules are checked first and that first-match semantics apply, but the pseudocode later sorts rules by specificity before evaluation. In a governance system, this inconsistency can lead implementers or operators to misunderstand which rule actually wins, causing unintended allows or denies and potentially bypassing restrictive parent policies.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The conflict section says a child allow can override a parent deny, while the precedence rules explicitly say deny always wins. In a hierarchical security policy engine, contradictory guidance about deny override behavior is dangerous because different components or administrators may implement opposite semantics, leading to exposure of actions that should remain blocked.

Content

No source excerpt is available for this finding.

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 · references/policy-schema.md (reported line 32)May include surrounding context.

md
| Action | Description |
|--------|-------------|
| `allow` | Permit the action without approval |
| `deny` | Block the action (always wins) |
| `require_approval` | Allow but require explicit user approval |
| `log` | Allow but log for audit |

Rp1

Medium
Category
MCP Rug Pull
Confidence
75% confidence
Finding

Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
75% confidence
Finding

Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/policy-schema.md (reported line 229)May include surrounding context.

md
- command: "sudo *"
      action: deny
      reason: "Sudo not allowed"
  
  file:
    read:

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/inheritance-algorithm.md (reported line 140)May include surrounding context.

md
inheritance:
  mode: merge
  exceptions:
    - shell.sudo
  extensions:
    - http.allowlist
'''

Static analysis

No suspicious patterns detected.