Back to skill

Security audit

OpenClaw Universal Memory

Security checks for vulnerabilities and agentic risk

Overview

The skill has a reasonable database-memory purpose, but its launcher can run unbundled Python code from outside the reviewed skill while forwarding database credentials and the user environment.

Review before installing. Only run this in a trusted project where you have verified the actual openclaw_memory package being executed, use a dedicated least-privilege database credential, and avoid exposing unrelated secrets in the environment when invoking the launcher.

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

T07 · Tool Hijacking and Spoofing

Error
Location
scripts/run_memory.py:11
Finding

Out-of-Scope Python Module Execution Through Attacker-Influenced PYTHONPATH

Content
View full analysis
Path: here = Path(__file__).resolve() return here.parents[3] ``` ```python def main() -> None: args = _parse_args() repo_root = _find_repo_root() subprocess_env = os.environ.copy() if args.dsn.strip(): subprocess_env[args.dsn_env] = args.dsn.strip() repo_src = str((repo_root / "src").resolve()) existing_pythonpath = subprocess_env.get("PYTHONPATH", "").strip() subprocess_env["PYTHONPATH"] = f"{repo_src}:{existing_pythonpath}" if existing_pythonpath else repo_src base = [ sys.executable, "-m", "openclaw_memory.cli", args.action, "--dsn-env", args.dsn_env, "--dsn-file", args.dsn_file, "--dsn-key", args.dsn_key, ] ``` ```python result = subprocess.run(base, cwd=repo_root, capture_output=True, text=True, env=subprocess_env) ``` The subprocess invocation also occurs in the `configure-dsn` branch at line 84. ### Technical Analysis The launcher calculates its repository root using `here.parents[3]`. Given the audited layout: ```text /tmp//artifact/scripts/run_memory.py ``` the calculated path is `/tmp`, rather than the `artifact` project directory. The launcher consequently prepends `/tmp/src` to `PYTHONPATH` and executes: ```text python -m openclaw_memory.cli ``` The audited project does not contain the referenced `openclaw_memory` package. Python therefore attempts to resolve the module from the calculated external source directory or other environment paths. If an attacker can create or control `/tmp/src/openclaw_memory`, their module can be loaded instead of the intended implementation. The child process receives a copy of the caller's environment. When `--dsn` is supplied, th ...[truncated 2408 chars]
Remediation
View remediation
Path: return Path(__file__).resolve().parent.parent ``` 2. Validate that the expected package exists beneath the trusted root before executing it: ```python repo_root = _find_repo_root() module_path = repo_root / "src" / "openclaw_memory" / "cli.py" if not module_path.is_file(): raise RuntimeError(f"Expected CLI module is missing: {module_path}") ``` 3. Ensure the resolved package path remains within the trusted project root: ```python repo_root = repo_root.resolve() repo_src = (repo_root / "src").resolve() repo_src.relative_to(repo_root) ``` 4. Avoid prepending a broadly writable ancestor directory such as `/tmp/src` to `PYTHONPATH`. Prefer installing the package into a controlled virtual environment and invoking its verified entry point. 5. Package the complete `openclaw_memory` implementation with the project, including an appropriate packaging manifest, so the executable backend is included in security review. 6. Consider importing the bundled module directly after validating its location rather than delegating resolution to an externally influenced Python search path. 7. Minimize the subprocess environment by passing only required variables. Do not forward unrelated secrets from `os.environ` to the child process. 8. Add a startup assertion and automated test verifying that `repo_root` equals the expected project directory and that module resolution cannot escape it. 9. Fail closed if the expected local module is missing, has an unexpected resolved path, or cannot be integrity-verified. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (4)

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/run_memory.py (reported line 61)May include surrounding context.

python
def main() -> None:
    args = _parse_args()
    repo_root = _find_repo_root()
    subprocess_env = os.environ.copy()
    if args.dsn.strip():
        subprocess_env[args.dsn_env] = args.dsn.strip()
    repo_src = str((repo_root / "src").resolve())

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill exposes shell and environment-variable based capabilities through documented commands, but it does not declare any explicit tool scope such as permissions or allowed-tools. In an agent setting, this can lead to overbroad execution authority, allowing the skill to access local environment secrets like DATABASE_DSN or invoke arbitrary shell operations beyond the minimum needed for database workflows.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/run_memory.py (reported line 87)May include surrounding context.

python
base.extend(["--config-path", args.config_path.strip()])
        if args.force:
            base.append("--force")
        result = subprocess.run(base, cwd=repo_root, capture_output=True, text=True, env=subprocess_env)
        if result.stdout:
            print(result.stdout.strip())
        if result.stderr:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/run_memory.py (reported line 167)May include surrounding context.

python
base.extend(["--config-path", args.config_path.strip()])
        if args.force:
            base.append("--force")
        result = subprocess.run(base, cwd=repo_root, capture_output=True, text=True, env=subprocess_env)
        if result.stdout:
            print(result.stdout.strip())
        if result.stderr:

Static analysis

No suspicious patterns detected.