Back to skill

Security audit

Trigger Evaluator

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed wrapper for one OpenClaw trigger, but it runs an unreviewed external script and uses broad database/Docker authority for a narrow inspection task.

Install only if you trust the local OpenClaw workspace script it executes and the Docker/PostgreSQL environment it can access. Prefer packaging or pinning the engine and using a dedicated read-only database role before broad use.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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 (2)

T07 · Tool Hijacking and Spoofing

Warning
Location
scripts/trigger-evaluator.sh:4
Finding
Unverified Delegation to an External Executable<![CDATA[ ## Vulnerability Details **File Location**: `scripts/trigger-evaluator.sh`, lines 4-5 and 30-34 **Vulnerability Type**: `T07: Tool Hijacking and Spoofing` **Risk Level**: Medium ### Vulnerable Code ```sh WORKSPACE="/home/cmart/.openclaw/workspace" ENGINE="$WORKSPACE/scripts/stale_missions_engine.sh" # ... [ -x "$ENGINE" ] || { echo "Error: engine not executable: $ENGINE" >&2 exit 1 } exec "$ENGINE" ``` ### Technical Analysis The skill delegates its primary evaluation operation to an executable outside the audited project directory. Before execution, the wrapper checks only whether the target has its executable permission set. It does not validate the target's owner, permissions, cryptographic integrity, or whether the path resolves through a symbolic link. The external dependency is disclosed in `SKILL.md`, so no concealed malicious payload was identified in the packaged files. Nevertheless, the effective behavior of the `evaluate` command cannot be determined from this package alone. If another user or compromised process can replace the engine, modify its contents, or redirect its path through a symbolic link, a legitimate invocation of the skill will execute attacker-controlled code. ### Attack Path 1. An attacker obtains write access to `/home/cmart/.openclaw/workspace/scripts/stale_missions_engine.sh` or one of its parent directories. 2. The attacker modifies the engine or replaces it with an executable symbolic link or malicious program. 3. A user or agent invokes: ```sh trigger-evaluator.sh evaluate stale_missions_alert ``` 4. The wrapper's executable check succeeds because the substituted target is executable. 5. `exec "$ENGINE"` transfers control to the attacker-controlled program under the privileges of the invoking account. ### Impact Assessment Successful exploitation provides arbitrary command execution with the privileges of the user running the skill. The resulting access may include local files, environment vari ...[truncated 325 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Package the evaluation engine inside the audited skill directory whenever possible. 2. Store the engine in an administrator-owned location that is not writable by the invoking user or other untrusted accounts. 3. Resolve the target to its canonical path and reject symbolic links or paths that escape the expected directory. 4. Verify that the engine and every parent directory have trusted ownership and restrictive permissions before execution. 5. Pin and validate a cryptographic digest or verify a signed artifact before transferring control. 6. Fail closed if any ownership, permission, path, or integrity check is unsuccessful. 7. Include the engine in future code-audit scope so the complete evaluation behavior can be reviewed. ]]>

T05 · Unauthorized Access and Privilege Escalation

Note
Location
scripts/trigger-evaluator.sh:7
Finding
Database Inspection Uses an Overprivileged PostgreSQL Role<![CDATA[ ## Vulnerability Details **File Location**: `scripts/trigger-evaluator.sh`, lines 7-8 and 41-58 **Vulnerability Type**: `T05: Unauthorized Access and Privilege Escalation` **Risk Level**: Low ### Vulnerable Code ```sh DB_USER="postgres" DB_NAME="postgres" # ... docker exec -i "$DB_CONTAINER" psql -U "$DB_USER" -d "$DB_NAME" -At -F $'\t' -c " SELECT id, name, trigger_event, conditions::text, action_config::text, target_agent, cooldown_minutes, enabled, fire_count, COALESCE(last_fired_at::text, ''), created_at::text FROM public.openclaw_trigger_rules WHERE name = 'stale_missions_alert' LIMIT 1; " ``` ### Technical Analysis The `inspect` operation performs a fixed, read-only query against one table but connects using the PostgreSQL `postgres` role. This role is conventionally a database superuser and therefore provides substantially broader authority than the operation requires. The SQL statement is static and does not interpolate the user-supplied trigger name, so no direct SQL-injection path was found. The weakness is excessive ambient authority: if the script, command invocation, or relevant execution environment is compromised, the available database session can provide administrative access rather than narrowly scoped read-only access. ### Attack Path 1. An attacker gains the ability to alter the wrapper, influence the database command, or execute an alternative command through the same authorized operational context. 2. The altered command connects to the `postgres` database as the `postgres` role. 3. Instead of issuing only the intended `SELECT`, the attacker performs administrative queries against other schemas or databases accessible to that role. 4. The attacker reads, modifies, or deletes data beyond `public.openclaw_trigger_rules`, subject to the actual PostgreSQL and container configuration. ### Impact Assessment The intended operation requires only read access to a single trigger-rule record. Use of the `pos ...[truncated 477 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create a dedicated PostgreSQL login for trigger inspection. 2. Grant only the minimum necessary permissions: - `CONNECT` on the required database. - `USAGE` on the `public` schema. - `SELECT` on `public.openclaw_trigger_rules`. 3. Consider exposing only the required columns and row through a restricted view or security-reviewed stored function. 4. Configure the role as read-only and deny role creation, schema modification, data modification, and administrative capabilities. 5. Avoid using the `postgres` superuser for routine application or inspection tasks. 6. Review Docker access separately because permission to invoke `docker exec` can itself represent a highly privileged system capability. ]]>
Vulnerability Patterns
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (1)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The description suggests a general evaluator for real OpenClaw trigger rules against current database state, particularly using openclaw_trigger_rules, openclaw_missions, and openclaw_proposals. In contrast, this code chunk is narrowly scoped to one trigger name, stale_missions_alert. Its inspect path only fetches the trigger rule record from public.openclaw_trigger_rules and does not inspect mission or proposal state. Its evaluate path simply execs another script whose behavior is not visible here, so this chunk itself does not demonstrate the claimed database-backed trigger evaluation. Because the implemented behavior is materially narrower and relies on an undisclosed external engine, the declared description is not accurately represented by the supplied code chunk.

Static analysis

No suspicious patterns detected.