Back to skill

Security audit

Cyber Security Engineer

Security checks for vulnerabilities and agentic risk

Overview

This security-hardening skill is coherent in purpose, but it installs a persistent sudo wrapper and has approval, environment, logging, and notifier weaknesses that need review before use.

Review carefully before installing. Only use this skill if you intentionally want OpenClaw sudo calls routed through its guard, and first require mandatory command policy files, remove or replace the sudo PATH shim, eliminate shell=True notifier execution, restrict env-file parsing to needed flags, protect/redact audit logs, and make approval state unforgeable.

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
  • 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
Findings (5)

T07 · Tool Hijacking and Spoofing

Error
Location
scripts/install-openclaw-runtime-hook.sh:21
Finding
Persistent sudo interception through PATH modification<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install-openclaw-runtime-hook.sh:21-57, 61-81` **Vulnerability Type**: Persistent tool hijacking **Risk Level**: High ### Vulnerable Code ```bash OPENCLAW_DIR="${HOME}/.openclaw" BIN_DIR="${OPENCLAW_DIR}/bin" SKILL_DIR_DEFAULT="${OPENCLAW_DIR}/workspace/skills/cyber-security-engineer" mkdir -p "${BIN_DIR}" chmod 700 "${OPENCLAW_DIR}" "${BIN_DIR}" || true WRAPPER="${BIN_DIR}/sudo" cat > "${WRAPPER}" <<EOF #!/usr/bin/env bash set -euo pipefail REAL_SUDO="\${OPENCLAW_REAL_SUDO:-${REAL_SUDO}}" SKILL_DIR="\${OPENCLAW_CYBER_SKILL_DIR:-${SKILL_DIR_DEFAULT}}" # Pass-through for sudo bookkeeping. if [[ \$# -eq 0 ]]; then exec "\${REAL_SUDO}" fi case "\${1:-}" in -h|--help|-V|--version|-v|-l|-k) exec "\${REAL_SUDO}" "\$@" ;; esac # Refuse non-interactive privilege escalation by default (safety). if [[ ! -t 0 && "\${OPENCLAW_ALLOW_NONINTERACTIVE_SUDO:-0}" != "1" ]]; then echo "[cyber-security-engineer] Refusing non-interactive sudo (set OPENCLAW_ALLOW_NONINTERACTIVE_SUDO=1 to override)." >&2 exit 2 fi REASON="\${OPENCLAW_PRIV_REASON:-OpenClaw requested privileged execution}" export OPENCLAW_REAL_SUDO="\${REAL_SUDO}" exec python3 "\${SKILL_DIR}/scripts/guarded_privileged_exec.py" \\ --reason "\${REASON}" \\ --use-sudo \\ -- "\$@" EOF chmod 755 "${WRAPPER}" log "Installed sudo shim: ${WRAPPER}" ``` ```bash if [[ "$(uname -s)" == "Darwin" ]]; then PLIST="${HOME}/Library/LaunchAgents/ai.openclaw.gateway.plist" if [[ -f "${PLIST}" ]] && command -v /usr/libexec/PlistBuddy >/dev/null 2>&1; then # Ensure EnvironmentVariables exists and prepend ~/.openclaw/bin to PATH. /usr/libexec/PlistBuddy -c "Add :EnvironmentVariables dict" "${PLIST}" 2>/dev/null || true EXISTING_PATH="$(/usr/libexec/PlistBuddy -c "Print :EnvironmentVariables:PATH" "${PLIST}" 2>/dev/null || true)" if [[ -z "${EXISTING_PATH}" ]]; then NEW_PATH="${BIN_DIR}:/usr/bin:/bin:/usr/sbin:/sbin" ...[truncated 2780 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not shadow the system `sudo` executable through `PATH`. - Use an explicitly named command, such as `openclaw-guarded-exec`, or a dedicated privileged broker API. - Keep the privileged broker outside a user-writable workspace and verify its ownership, permissions, and cryptographic integrity before each use. - Require explicit installation approval and display every persistent file or LaunchAgent modification before applying it. - Add a verified uninstall procedure that removes the shim and restores the original LaunchAgent `PATH`. - Resolve the real `sudo` binary to a trusted absolute system path and reject environment-based overrides in privileged contexts. - Restrict the gateway environment so untrusted processes cannot modify the wrapper, referenced Skill directory, or relevant environment variables. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/root_session_guard.py:197
Finding
Approval state can be forged through an unauthenticated state-management command<![CDATA[ ## Vulnerability Details **File Location**: `scripts/root_session_guard.py:197-207, 276-289, 319-329`; `scripts/guarded_privileged_exec.py:145-154` **Vulnerability Type**: Approval-boundary bypass **Risk Level**: High ### Vulnerable Code ```python def approve_command(state: SessionState, reason: str, argv: List[str], session_id: Optional[str]) -> None: ts = to_iso(now_utc()) state.privilege_mode = "elevated" state.last_elevated_activity_utc = ts state.last_transition_utc = ts state.last_action = "approved-command" state.approved_reason = reason state.approved_session_id = session_id if argv and not is_allowed(state, argv): state.allowed_commands.append(AllowedCommand(argv=argv, added_at_utc=ts)) ``` ```python approve = sub.add_parser( "approve", help="Approve a specific argv for elevated execution (adds to allowlist)", ) approve.add_argument("--reason", required=True, help="Approval reason") approve.add_argument( "--argv-json", required=True, help='Command argv as JSON array, e.g. ["launchctl","print","..."]', ) approve.add_argument("--session-id", help="Task session id to scope approvals") ``` ```python if args.command == "approve": argv = json.loads(args.argv_json) if not isinstance(argv, list) or not all(isinstance(x, str) for x in argv): print('{"status":"ERROR","error":"argv-json must be a JSON array of strings"}') return 2 approve_command(state, args.reason, argv, args.session_id) save_state(state_file, state) print('{"status":"OK","action":"approved-command"}') return 0 ``` The forged state is accepted by the guarded executor: ```python if session_id: authz = run_guard(args, "authorize", "--argv-json", argv_json, "--session-id", session_id) else: authz = run_guard(args, "authorize", "--argv-json", argv_json) if authz.returncode not in (0, 2): sys.stderr.write(authz.stderr or authz.stdout) return authz.returncode needs_appr ...[truncated 2023 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove the publicly callable `approve` state mutation interface. - Place approval issuance in a separate, trusted process that the agent cannot invoke as an unrestricted CLI. - Issue cryptographically signed, short-lived approval capabilities bound to: - the exact command and arguments; - the task session; - the requesting identity; - an expiration time; - a unique nonce. - Verify approval signatures inside the privileged broker rather than trusting mutable JSON state. - Store state with explicit owner-only permissions and reject files with unexpected ownership, modes, links, or parent directories. - Add file locking and atomic writes to prevent state races and corruption. - Make command policy mandatory and fail closed if the policy is absent, invalid, or empty. - Ensure the process displaying the approval prompt is isolated from the process requesting privileged execution. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/notify_on_violation.py:101
Finding
Environment-controlled notification command is executed through a shell<![CDATA[ ## Vulnerability Details **File Location**: `scripts/notify_on_violation.py:101-109` **Vulnerability Type**: OS command injection **Risk Level**: High ### Vulnerable Code ```python def _send_notification(message: str) -> int: cmd = os.environ.get("OPENCLAW_VIOLATION_NOTIFY_CMD", "").strip() if not cmd: sys.stdout.write(message) return 0 # Best-effort: never crash the cycle due to a notifier. try: p = subprocess.run(cmd, shell=True, input=message, text=True) return int(p.returncode) except Exception: return 1 ``` ### Technical Analysis The complete value of `OPENCLAW_VIOLATION_NOTIFY_CMD` is interpreted by the platform shell. Shell metacharacters, pipelines, substitutions, redirections, and compound commands are therefore active. The command is invoked by the automated security cycle when a new compliance violation or severity escalation is detected. No executable allowlist, argument validation, trusted configuration source, or privilege separation is applied. This is not injection through the notification message itself because the message is passed through standard input. The vulnerability is the execution of an environment-controlled string with `shell=True`. ### Attack Path 1. An attacker gains the ability to influence the environment used by the assessment cycle or gateway. 2. The attacker sets `OPENCLAW_VIOLATION_NOTIFY_CMD` to a shell payload, such as a compound command. 3. A new compliance finding is introduced or the notification state is removed so existing findings appear new. 4. `auto_invoke_cycle.sh` runs `notify_on_violation.py`. 5. `_send_notification` passes the attacker-controlled string to the shell. 6. The shell executes the payload with the privileges and filesystem/network access of the account running the cycle. ### Impact Assessment Successful exploitation provides arbitrary command execution as the OpenClaw gateway or assessment-cycle user. The attacker can ...[truncated 261 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove `shell=True`. - Configure notifier commands as a validated argument array and execute them with `subprocess.run(argv, shell=False, ...)`. - Prefer fixed notifier adapters with explicit configuration fields over arbitrary commands. - Resolve the notifier executable to an approved absolute path. - Reject shell metacharacters and unexpected executable paths if backward compatibility requires parsing a string. - Load notifier configuration from an owner-only configuration file rather than an inherited environment variable. - Run the notifier with minimal filesystem and network permissions. - Add execution timeouts and capture bounded output to prevent notifier hangs or resource exhaustion. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/live_assessment.py:68
Finding
Live assessment unnecessarily reads all values from the OpenClaw environment file<![CDATA[ ## Vulnerability Details **File Location**: `scripts/live_assessment.py:68-83, 185` **Vulnerability Type**: Excessive sensitive-data access **Risk Level**: Medium ### Vulnerable Code ```python def load_env_flags() -> Dict[str, str]: env_path = Path.home() / ".openclaw" / "env" if not env_path.exists(): return {} flags: Dict[str, str] = {} for line in env_path.read_text(encoding="utf-8").splitlines(): line = line.strip() if not line or line.startswith("#"): continue if line.startswith("export "): line = line[len("export ") :] if "=" in line: key, value = line.split("=", 1) flags[key.strip()] = value.strip().strip('"') return flags ``` ```python return { "openclaw_config_text": openclaw_config_text, "openclaw_config_json": load_openclaw_config(), "doctor_text": doctor_text, "gateway_status_text": gateway_status_text, "version_text": version_text, "port_report": port_report, "egress_report": egress_report, "env_flags": load_env_flags(), "command_policy": load_json_file(Path.home() / ".openclaw" / "security" / "command-policy.json"), "prompt_policy": load_json_file(Path.home() / ".openclaw" / "security" / "prompt-policy.json"), "egress_allowlist": load_json_file(Path.home() / ".openclaw" / "security" / "egress_allowlist.json"), } ``` ### Technical Analysis The assessment reads and stores every key-value pair from `~/.openclaw/env` in memory. Environment files commonly contain authentication tokens, API keys, webhook secrets, or service credentials. The subsequent checks only need to determine whether `OPENCLAW_REQUIRE_SESSION_ID` equals `1` and whether an approval token is configured; they do not need the actual values of unrelated entries or the approval token itself. No external transmission or report persistence of the complete `env_flags` object was identified in the reviewed code. The issue is ...[truncated 930 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Parse only an explicit allowlist of required keys. - For `OPENCLAW_APPROVAL_TOKEN`, record only a Boolean indicating whether a non-empty value exists. - Do not retain the token value in the returned signal dictionary. - Avoid reading unrelated entries from the file. - Store secrets in a dedicated secret manager or protected credential store rather than a general environment file where practical. - Ensure `~/.openclaw/env` is owned by the expected account and has mode `0600`. - Add tests confirming that unrelated environment-file values never appear in signals, logs, assessment JSON, or generated HTML. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/audit_logger.py:19
Finding
Privileged command arguments are logged without redaction or explicit permission enforcement<![CDATA[ ## Vulnerability Details **File Location**: `scripts/audit_logger.py:19-25`; `scripts/guarded_privileged_exec.py:32-41, 45-56` **Vulnerability Type**: Plaintext sensitive-data exposure **Risk Level**: Medium ### Vulnerable Code ```python def append_audit(event: Dict[str, Any]) -> None: """ Append an audit event to an on-disk JSONL timeline. Best-effort only: audit logging must never block privileged operations. """ try: AUDIT_LOG.parent.mkdir(parents=True, exist_ok=True) payload = {"ts_utc": _utc_now_iso(), **event} with AUDIT_LOG.open("a", encoding="utf-8") as f: f.write(json.dumps(payload, separators=(",", ":")) + "\n") except Exception: return ``` Complete command arguments are supplied to the logger: ```python def ask_for_approval(reason: str, command_argv: List[str]) -> bool: append_audit({"action": "approval_requested", "reason": reason, "argv": command_argv}) print("Approval required for elevated execution.") print(f"Reason: {reason}") print("Command argv:") print(json.dumps(command_argv, indent=2)) answer = input("Approve elevated access for this command? [y/N]: ").strip().lower() approved = answer in {"y", "yes"} append_audit({"action": "approval_decision", "reason": reason, "argv": command_argv, "approved": approved}) return approved ``` ```python def run_command(argv: List[str], use_sudo: bool, sudo_kill_cache: bool) -> int: sudo_bin = os.environ.get("OPENCLAW_REAL_SUDO", "sudo") exec_argv = [sudo_bin, "--"] + argv if use_sudo else argv print("Executing argv:") print(json.dumps(exec_argv, indent=2)) if use_sudo and sudo_kill_cache: subprocess.run([sudo_bin, "-k"], check=False, capture_output=True, text=True) append_audit({"action": "exec_start", "argv": argv, "use_sudo": use_sudo}) result = subprocess.run(exec_argv) append_audit({"action": "exec_finish", "argv": argv, "use_sudo": use_sudo, "r ...[truncated 1603 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Redact sensitive arguments before printing or logging them. - Recognize common secret-bearing options such as `--password`, `--token`, `--secret`, authorization headers, and credential-bearing URLs. - Prefer recording an approved command identifier or cryptographic hash instead of complete arguments. - Reject commands that provide secrets directly through command-line arguments and require protected standard input, file descriptors, or a secret manager. - Explicitly create and enforce mode `0700` on `~/.openclaw/security` and mode `0600` on the audit log. - Validate file ownership and reject symbolic links or unexpected file types before appending. - Use safe file-opening flags and atomic permission handling to reduce link and race risks. - Surface audit failures and, for high-risk privileged operations, fail closed when a trustworthy audit record cannot be written. - Define secure retention, rotation, and deletion policies for the audit log. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (75)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The finding suggests the skill's actual primary behavior is prompt-policy configuration loading, not the broad hardening workflow it advertises. In this context, the mismatch materially increases danger because defenders may defer other safeguards expecting this skill to provide them.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The finding suggests the skill's actual primary behavior is prompt-policy configuration loading, not the broad hardening workflow it advertises. In this context, the mismatch materially increases danger because defenders may defer other safeguards expecting this skill to provide them.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The finding suggests the skill's actual primary behavior is prompt-policy configuration loading, not the broad hardening workflow it advertises. In this context, the mismatch materially increases danger because defenders may defer other safeguards expecting this skill to provide them.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The finding suggests the skill's actual primary behavior is prompt-policy configuration loading, not the broad hardening workflow it advertises. In this context, the mismatch materially increases danger because defenders may defer other safeguards expecting this skill to provide them.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The finding suggests the skill's actual primary behavior is prompt-policy configuration loading, not the broad hardening workflow it advertises. In this context, the mismatch materially increases danger because defenders may defer other safeguards expecting this skill to provide them.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The finding suggests the skill's actual primary behavior is prompt-policy configuration loading, not the broad hardening workflow it advertises. In this context, the mismatch materially increases danger because defenders may defer other safeguards expecting this skill to provide them.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
The finding suggests the skill's actual primary behavior is prompt-policy configuration loading, not the broad hardening workflow it advertises. In this context, the mismatch materially increases danger because defenders may defer other safeguards expecting this skill to provide them.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
rules.append(rule)

    rules.sort(key=lambda r: (int(r.get("port", 0)), str(r.get("protocol", "")), str(r.get("command", ""))))
    return rules, len(seen)


def main() -> int:
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
# Best-effort: never crash the cycle due to a notifier.
    try:
        p = subprocess.run(cmd, shell=True, input=message, text=True)
        return int(p.returncode)
    except Exception:
        return 1
Confidence
98% confidence
Finding
This is tool parameter abuse because the script exposes shell command execution through a configurable notification hook. In the context of a cyber-security-engineer skill focused on privilege governance and monitoring, such a hook is more dangerous because the script may run in privileged or sensitive environments, turning misconfiguration or env injection into full command execution.

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill advertises and references capabilities that imply shell execution, file access, and environment-variable use, but it does not declare any explicit tool scope or permission boundaries. In a security-sensitive skill, this creates ambiguity about what the agent may access or execute and weakens review-time enforcement of least privilege.

Session Persistence

Medium
Category
Rogue Agent
Content
<tr><td>privilege_approval_required</td><td>Route all privileged tasks through guarded_privileged_exec.py and enforce approval prompts for elevated execution.</td><td>Security Engineering</td><td>2026-03-15</td></tr>
<tr><td>least_privilege_enforced</td><td>Fix state dir ownership/permissions and enforce command allowlist/approval defaults.</td><td>Platform Security</td><td>2026-03-07</td></tr>
<tr><td>elevation_timeout_30m</td><td>Invoke guarded_privileged_exec.py for every elevated operation path.</td><td>Security Engineering</td><td>2026-03-15</td></tr>
<tr><td>audit_logging_privileged_actions</td><td>Create append-only correlated audit records linking approval, execution, and drop events.</td><td>SecOps</td><td>2026-03-22</td></tr>
<tr><td>open_ports_approved</td><td>Populate ~/.openclaw/security/approved_ports.json and remove unnecessary listeners.</td><td>Infrastructure</td><td>2026-02-28</td></tr>
<tr><td>insecure_ports_remediated</td><td>Enforce baseline checks to block insecure service ports.</td><td>Network Security</td><td>2026-04-01</td></tr>
        </tbody>
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
"observed_state": "Gateway logs and session transition logs are available.",
        "evidence": "gateway status reports log paths; root_session_guard records transition metadata.",
        "gap": "No single correlated privileged action audit timeline is guaranteed.",
        "mitigation": "Create append-only correlated audit records linking approval, execution, and drop events.",
        "owner": "SecOps",
        "due_date": "2026-03-22"
      },
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
"observed_state": "Gateway logs and session transition logs are available.",
      "evidence": "gateway status reports log paths; root_session_guard records transition metadata.",
      "gap": "No single correlated privileged action audit timeline is guaranteed.",
      "mitigation": "Create append-only correlated audit records linking approval, execution, and drop events.",
      "owner": "SecOps",
      "due_date": "2026-03-22"
    },
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
"iso27001": ["A.5.15"],
    "nist": ["PR.AA-05"],
    "default_risk": "medium",
    "expected_state": "su/doas or other escalation paths are restricted or guarded."
  },
  {
    "check_id": "backup_configured",
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
"iso27001": ["A.5.15"],
    "nist": ["PR.AA-05"],
    "default_risk": "medium",
    "expected_state": "su/doas or other escalation paths are restricted or guarded."
  },
  {
    "check_id": "backup_configured",
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
"iso27001": ["A.5.15"],
    "nist": ["PR.AA-05"],
    "default_risk": "medium",
    "expected_state": "su/doas or other escalation paths are restricted or guarded."
  },
  {
    "check_id": "backup_configured",
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Missing User Warnings

Medium
Confidence
85% confidence
Finding
This shell script performs safety-relevant actions including subprocess execution and persistent file writes to assessment and log locations. While it logs timestamps, it does not disclose to the user that it will create or overwrite output artifacts or run monitoring commands, and no inline comment or docstring provides a user warning about these effects.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The helper writes JSON objects to disk and is used for both assessment scaffolds and compliance summaries, which may contain risk ratings, evidence, gaps, owners, and mitigations. Although the command prints output paths after writing, there is no prior comment, docstring, or warning that sensitive compliance information will be persisted locally.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The HTML dashboard embeds assessment-controlled fields such as system name, title, gap, evidence, mitigation, owner, and due_date directly into HTML without escaping. If any of those values contain HTML or JavaScript, opening the generated dashboard can trigger stored cross-site scripting in the viewer’s browser, which is especially relevant because compliance evidence may include externally sourced or manually pasted content.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
str(args.timeout_minutes),
        *guard_args,
    ]
    return subprocess.run(cmd, capture_output=True, text=True)


def ask_for_approval(reason: str, command_argv: List[str]) -> bool:
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
print(json.dumps(exec_argv, indent=2))
    if use_sudo and sudo_kill_cache:
        # Best-effort: ensure sudo timestamp for this user is not reused implicitly.
        subprocess.run([sudo_bin, "-k"], check=False, capture_output=True, text=True)
    append_audit({"action": "exec_start", "argv": argv, "use_sudo": use_sudo})
    result = subprocess.run(exec_argv)
    append_audit({"action": "exec_finish", "argv": argv, "use_sudo": use_sudo, "returncode": result.returncode})
Confidence
96% confidence
Finding
The script invokes a sudo-related binary whose path is taken from OPENCLAW_REAL_SUDO. If an attacker can influence the environment, they can substitute a malicious executable, causing arbitrary code execution when the script attempts to clear sudo state.

Tainted flow: 'sudo_bin' from os.environ.get (line 46, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Content
print(json.dumps(exec_argv, indent=2))
    if use_sudo and sudo_kill_cache:
        # Best-effort: ensure sudo timestamp for this user is not reused implicitly.
        subprocess.run([sudo_bin, "-k"], check=False, capture_output=True, text=True)
    append_audit({"action": "exec_start", "argv": argv, "use_sudo": use_sudo})
    result = subprocess.run(exec_argv)
    append_audit({"action": "exec_finish", "argv": argv, "use_sudo": use_sudo, "returncode": result.returncode})
Confidence
98% confidence
Finding
This is a direct environment-to-exec path: sudo_bin comes from OPENCLAW_REAL_SUDO and is passed to subprocess.run. Because this script is designed to manage privileged operations, any environment injection substantially increases risk and can lead to arbitrary code execution.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# Best-effort: ensure sudo timestamp for this user is not reused implicitly.
        subprocess.run([sudo_bin, "-k"], check=False, capture_output=True, text=True)
    append_audit({"action": "exec_start", "argv": argv, "use_sudo": use_sudo})
    result = subprocess.run(exec_argv)
    append_audit({"action": "exec_finish", "argv": argv, "use_sudo": use_sudo, "returncode": result.returncode})
    return result.returncode
Confidence
89% confidence
Finding
This call executes attacker-influenced argv and can optionally prefix it with a sudo binary taken from an environment variable. Although evaluate_command() provides a policy gate, this file still directly executes privileged commands and trusts external policy/guard modules; if policy is bypassed, misconfigured, or incomplete, this becomes arbitrary command execution with elevated privileges.

Tainted flow: 'exec_argv' from os.environ.get (line 47, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Content
# Best-effort: ensure sudo timestamp for this user is not reused implicitly.
        subprocess.run([sudo_bin, "-k"], check=False, capture_output=True, text=True)
    append_audit({"action": "exec_start", "argv": argv, "use_sudo": use_sudo})
    result = subprocess.run(exec_argv)
    append_audit({"action": "exec_finish", "argv": argv, "use_sudo": use_sudo, "returncode": result.returncode})
    return result.returncode
Confidence
97% confidence
Finding
The tainted flow is real: exec_argv incorporates sudo_bin from os.environ and is then executed. In a privileged-execution workflow, environment-controlled executable resolution is especially dangerous because it can turn an approval wrapper into an attacker-controlled code launcher.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
append_audit({"action": "drop_elevation", "argv": argv, "reason": "post-command"})
        if args.use_sudo and args.sudo_kill_cache:
            sudo_bin = os.environ.get("OPENCLAW_REAL_SUDO", "sudo")
            subprocess.run([sudo_bin, "-k"], check=False, capture_output=True, text=True)


if __name__ == "__main__":
Confidence
96% confidence
Finding
This repeats the same environment-controlled sudo binary execution during cleanup. Cleanup paths are still exploitable execution paths, so a malicious OPENCLAW_REAL_SUDO value could run arbitrary code even after the main command completes.

Static analysis

No suspicious patterns detected.