Back to skill

Security audit

Django Claw

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real Django administration skill, but it grants broad code and database access and has under-disclosed persistent configuration changes, so it needs careful review before installation.

Install only if you trust the publisher and intend to give this skill administrative access to the selected Django project. Treat django-claw shell as arbitrary Python execution, not a safe read-only query tool; avoid using it on production. Review or patch the setup and heredoc handling before use, remove broad aliases if possible, keep read-only mode enabled by default, and verify exactly which project and database are configured before running migrations or user/database inspection commands.

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
scripts/db-stats.sh:8
Finding
Configuration Values Are Interpolated into Executable Python Source## Vulnerability Details **File Location**: `scripts/db-stats.sh:8-12`, `scripts/list-apps.sh:8-12`, `scripts/list-models.sh:8-12`, `scripts/list-urls.sh:8-12`, `scripts/pending-migrations.sh:8-12`, and `scripts/settings-check.sh:8-12` **Vulnerability Type**: Python code injection through unsafe source generation **Risk Level**: High ### Vulnerable Code The following pattern appears in each affected script: ```bash cat > "$TMPFILE" << PYEOF import os, sys, django os.environ.setdefault('DJANGO_SETTINGS_MODULE', '${SETTINGS}') sys.path.insert(0, '${PROJECT_PATH}') django.setup() ``` The generated temporary file is subsequently executed. For example, `scripts/db-stats.sh` executes it as follows: ```bash cd "$PROJECT_PATH" "$PYTHON" "$TMPFILE" ``` ### Technical Analysis `SETTINGS` and `PROJECT_PATH` are read by `scripts/load-config.sh` from environment variables or the skill's JSON configuration file. The affected scripts place these values directly inside single-quoted Python string literals in an unquoted heredoc. Shell quoting around a variable expansion does not serialize its value as a valid Python string. A value containing a single quote, newline, and Python syntax can terminate the generated string literal and insert additional executable statements. The resulting temporary Python file is then executed using the configured interpreter. This flaw affects commands presented as inspection or read-only operations, including application, model, URL, database, migration, and settings inspection. Consequently, enabling the skill's read-only mode does not mitigate this injection path. ### Attack Path 1. An attacker gains the ability to influence `DJANGO_SETTINGS_MODULE`, `DJANGO_PROJECT_PATH`, or the corresponding values in `~/.openclaw/skills/django-claw/config.json`. 2. The attacker supplies a value crafted to terminate the surrounding Python string literal and append Python statements. 3. A user invokes ...[truncated 878 chars]
Remediation
## Remediation Suggestions - Do not generate Python source containing interpolated configuration values. - Export the settings module and project path as environment variables, then retrieve them from `os.environ` inside a static, quoted Python program. - Alternatively, pass values as separate positional arguments and access them through `sys.argv`. - Quote heredoc delimiters, such as `&lt;&lt;'PYEOF'`, to prevent shell expansion inside the Python body. - Validate the settings module against an allowlist-compatible format, such as a dotted Python module name. - Resolve and validate the project path using canonical path operations before use. - Apply the same fix consistently to all six affected scripts. - Add regression tests using values containing quotes, newlines, backslashes, command syntax, and Python statements to verify that configuration values remain inert data.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/setup.sh:45
Finding
Setup Wizard Embeds Interactive Input into Executable Python Heredocs## Vulnerability Details **File Location**: `scripts/setup.sh:45-54` and `scripts/setup.sh:64-78` **Vulnerability Type**: Python and shell code injection through unsafe heredoc interpolation **Risk Level**: High ### Vulnerable Code ```bash # Save config.json using python3 to avoid path injection via heredoc /usr/bin/python3 - << PYEOF import json config = { "project_path": """$PROJECT_PATH""", "venv_path": """$VENV_PATH""", "settings_module": """$SETTINGS_MODULE""", "read_only": $READ_ONLY_VAL } with open("$CONFIG_FILE", "w") as f: json.dump(config, f, indent=2) print("✅ Config saved") PYEOF ``` The same unsafe construction is used while modifying OpenClaw's global configuration: ```bash /usr/bin/python3 - << PYEOF import json, os openclaw_file = "$OPENCLAW_JSON" with open(openclaw_file) as f: cfg = json.load(f) cfg.setdefault("env", {}).setdefault("vars", {}).update({ "DJANGO_PROJECT_PATH": """$PROJECT_PATH""", "DJANGO_VENV_PATH": """$VENV_PATH""", "DJANGO_SETTINGS_MODULE": """$SETTINGS_MODULE""", }) with open(openclaw_file, "w") as f: json.dump(cfg, f, indent=2) print("✅ Env vars injected into openclaw.json") PYEOF ``` ### Technical Analysis The setup wizard reads the project path, virtual-environment path, and settings module from interactive input and embeds those values directly into executable Python source. Python triple-quoted strings are not a serialization or escaping mechanism. Input containing a terminating triple quote can escape the intended string and insert Python statements. In addition, the heredoc delimiters are unquoted, so shell parameter expansion, command substitution, and arithmetic expansion are performed while constructing the Python program. The source comment claiming that this construction avoids path injection is therefore incorrect. The project-path prompt checks for a corresponding `manage.py`, but ...[truncated 1300 chars]
Remediation
## Remediation Suggestions - Replace both interpolated Python heredocs with static Python code using a quoted heredoc delimiter. - Pass user-provided values through environment variables or positional arguments rather than inserting them into Python source. - Read those values through `os.environ` or `sys.argv`, and use `json.dump` to perform correct JSON serialization. - Do not place user-controlled data directly into Python string literals, including triple-quoted literals. - Validate `SETTINGS_MODULE` as a dotted module identifier and reject control characters or unexpected syntax. - Canonicalize project and virtual-environment paths and verify that required files are regular files owned or trusted by the user. - Write configuration through a temporary file with restrictive permissions and atomically rename it into place. - Set explicit restrictive permissions, such as mode `0600`, on configuration files. - Back up `~/.openclaw/openclaw.json` before modification and require explicit confirmation before changing global OpenClaw configuration.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/run-query.sh:12
Finding
ORM Shell Executes Unrestricted Python and Relies on a Bypassable Sensitive-Keyword Denylist## Vulnerability Details **File Location**: `scripts/run-query.sh:12-39` **Vulnerability Type**: Arbitrary Python execution exposed as an ORM query interface **Risk Level**: High ### Vulnerable Code ```bash # Block access to sensitive settings values if printf '%s' "$1" | grep -qiE '(SECRET_KEY|AWS_SECRET|API_KEY|PRIVATE_KEY|PASSWORD|\.conf\s+import\s+settings)'; then echo "ERROR: Accessing sensitive settings is not permitted via django-claw shell." exit 1 fi if [ "$READ_ONLY" = "true" ]; then echo "⛔ Read-only mode: 'shell' is disabled. Run 'django-claw readonly off' to enable." exit 1 fi TMPFILE=$(mktemp /tmp/django_query_XXXXXX.py) trap 'rm -f "$TMPFILE"' EXIT # Write Django boilerplate (heredoc — only our trusted vars expand here) cat > "$TMPFILE" << PYEOF import os, sys, django os.environ.setdefault('DJANGO_SETTINGS_MODULE', '${SETTINGS}') sys.path.insert(0, '${PROJECT_PATH}') django.setup() PYEOF # Append user code safely — printf avoids heredoc variable/command expansion printf '%s\n' "$1" >> "$TMPFILE" cd "$PROJECT_PATH" "$PYTHON" "$TMPFILE" ``` ### Technical Analysis The command accepts user-supplied text, appends it verbatim to a Python file, and executes that file after initializing Django. Although the feature is described as a Django ORM query mechanism, there is no parser, operation allowlist, sandbox, or capability restriction limiting input to ORM reads. The regular-expression denylist only searches for a small set of literal sensitive terms. It cannot prevent Python code from using dynamic imports, computed attribute names, alternate modules, direct filesystem operations, process execution, environment access, database APIs, or network clients. Keyword denylisting is not an effective security boundary for a general-purpose programming language. The optional read-only mode blocks the command as a whole when enabled, but it does not make execution safe when disable ...[truncated 1317 chars]
Remediation
## Remediation Suggestions - Remove general-purpose Python evaluation from the ORM-query feature. - Define a structured query format containing only explicitly supported model names, fields, filters, ordering, and limits. - Resolve models through Django's application registry and enforce allowlists for models, fields, lookup operators, and output columns. - Restrict the database identity used by query operations to `SELECT` permissions at the database layer. - Reject mutation methods and cap result counts, execution time, and output size. - Do not rely on keyword or regular-expression denylists to secure executable Python. - If arbitrary Python execution is an intentional administrative feature, rename and document it as unrestricted code execution, require explicit confirmation for every invocation, and restrict it to trusted administrators. - Run any intentionally supported code execution in an isolated sandbox with a dedicated low-privilege account, restricted filesystem, disabled or tightly controlled network access, process limits, and short execution timeouts. - Independently fix the unsafe interpolation of `SETTINGS` and `PROJECT_PATH` in the generated bootstrap code.
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (27)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill reportedly performs interactive setup, writes persistent configuration under the user's home directory, modifies global OpenClaw configuration, and injects environment variables into gateway configuration, none of which are disclosed by the declared purpose. Hidden persistence and configuration mutation are dangerous because they can silently alter future execution behavior, broaden access to projects, or plant long-lived environment changes beyond the user's immediate request.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill reportedly performs interactive setup, writes persistent configuration under the user's home directory, modifies global OpenClaw configuration, and injects environment variables into gateway configuration, none of which are disclosed by the declared purpose. Hidden persistence and configuration mutation are dangerous because they can silently alter future execution behavior, broaden access to projects, or plant long-lived environment changes beyond the user's immediate request.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill reportedly performs interactive setup, writes persistent configuration under the user's home directory, modifies global OpenClaw configuration, and injects environment variables into gateway configuration, none of which are disclosed by the declared purpose. Hidden persistence and configuration mutation are dangerous because they can silently alter future execution behavior, broaden access to projects, or plant long-lived environment changes beyond the user's immediate request.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The skill reportedly performs interactive setup, writes persistent configuration under the user's home directory, modifies global OpenClaw configuration, and injects environment variables into gateway configuration, none of which are disclosed by the declared purpose. Hidden persistence and configuration mutation are dangerous because they can silently alter future execution behavior, broaden access to projects, or plant long-lived environment changes beyond the user's immediate request.

Vague Triggers

High
Confidence
97% confidence
Finding
Single-word aliases like "showmigrations" and "show migrations" are excessively broad for automatic activation and relate to deployment-state inspection. In agent systems, terse operational words are especially collision-prone and can reveal schema history or deployment details unintentionally.

Vague Triggers

High
Confidence
99% confidence
Finding
Aliases for makemigrations such as "makemigrations" and "make migrations" are broad and invoke a state-changing operation. Accidental activation can generate migration files or alter repository state, which is especially dangerous in automated or agent-driven environments.

Vague Triggers

High
Confidence
99% confidence
Finding
Aliases like "migrate" and "apply migrations" are highly generic yet map to a schema-changing administrative action. In the context of a Django management skill with broad project access, unintended activation could modify the database schema and application state, causing outages, data corruption, or irreversible operational impact.

Vague Triggers

High
Confidence
98% confidence
Finding
Aliases like "run query" and "orm query" are ambiguous and feed user input directly into a script intended to execute Django shell/ORM actions. In this skill context, accidental or adversarial activation could lead to arbitrary code or query execution against the Django application environment, with potential for data theft, modification, or full application compromise depending on how run-query.sh is implemented.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The README advertises `makemigrations` and `migrate`, which can change application schema and modify the database, but it does not clearly warn about operational risk, environment scoping, backups, or production impact. In a tool designed to run commands directly against arbitrary configured Django projects, that omission can lead users or agents to execute state-changing operations in the wrong environment.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README documents `django-claw shell: <code>` as a way to run Django ORM queries, but this effectively exposes arbitrary code execution inside the Django application context without a strong safety warning. Because the skill can target any configured Django project, misuse could access sensitive data, alter records, or execute privileged application logic, especially if read-only mode is disabled or not enabled by default.

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill advertises executable capabilities and clearly dispatches to shell scripts, but it does not declare any explicit tool scope such as allowed-tools or permissions. That weakens containment and auditability because the runtime may grant broader file/environment access than users expect, especially given setup and readonly commands that imply persistent state changes.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The manifest describes running Django management commands or Django ORM queries, but this script performs an application-wide inventory by iterating over every installed model and counting all records. That bulk introspection/statistics behavior is materially different from the listed command set and broader than a normal targeted ORM query implied by the description.

Description-Behavior Mismatch

Medium
Confidence
88% confidence
Finding
The script explicitly enumerates all Django users and prints usernames, email addresses, privilege roles, and active status. In the context of an agent skill, this goes beyond generic operational management and exposes sensitive account metadata that can aid reconnaissance, targeted phishing, and privilege mapping if invoked by an unauthorized or overly broad caller.

Context-Inappropriate Capability

Medium
Confidence
84% confidence
Finding
The code retrieves and displays sensitive user account data for every account in the database without any apparent need-limiting logic, filtering, or purpose restriction in the file itself. Even if intended for administration, bulk exposure of account identifiers and email addresses creates unnecessary data disclosure risk within an automation environment.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The script prints sensitive account information directly with no warning, consent prompt, or disclosure that user records will be enumerated. In a skill ecosystem, that lack of transparency increases the chance that operators trigger personal-data exposure unexpectedly, especially because the metadata emphasizes Django management commands rather than account-data listing.

Description-Behavior Mismatch

Medium
Confidence
81% confidence
Finding
The manifest says the skill can run Django ORM queries and separately mentions a 'readonly' mode, which implies queries remain available with read-only restrictions. In this implementation, enabling READ_ONLY blocks the shell entirely, so the behavior does not match the described capability of supporting ORM queries under a readonly concept.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The setup script modifies the broader OpenClaw gateway configuration by writing into ~/.openclaw/openclaw.json, which is outside the skill-local config file and affects global runtime behavior. Even though it only injects environment variables, this creates side effects beyond the skill's stated setup scope and can unintentionally alter other skills or gateway behavior if the global config is shared or trusted by other components.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
Editing the global gateway configuration is not clearly necessary for a skill whose purpose is to run Django management commands and ORM queries, so the behavior exceeds least-privilege expectations. In a security-sensitive agent platform, hidden or non-obvious modification of global config increases risk because it can persistently influence future executions and broaden the blast radius of misconfiguration or abuse.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The description implies mostly read-oriented Django operations, but the manifest includes state-changing actions such as makemigrations, migrate, and disabling read-only mode. This mismatch is dangerous because it can cause users or orchestrators to authorize the skill under false assumptions, leading to unintended schema or configuration changes.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The description implies mostly read-oriented Django operations, but the manifest includes state-changing actions such as makemigrations, migrate, and disabling read-only mode. This mismatch is dangerous because it can cause users or orchestrators to authorize the skill under false assumptions, leading to unintended schema or configuration changes.

Vague Triggers

Medium
Confidence
96% confidence
Finding
Aliases like "list models" and "show models" are broad enough to collide with normal user requests unrelated to this skill. In an agent environment, ambiguous activation can trigger unintended code or environment introspection without the user explicitly asking to invoke the skill.

Vague Triggers

Medium
Confidence
95% confidence
Finding
Aliases such as "list apps" and "show apps" are common phrases that may match benign requests and unintentionally invoke the skill. Because this skill operates on configured Django projects, accidental activation can expose project structure and installed app information.

Vague Triggers

Medium
Confidence
94% confidence
Finding
Generic URL-related aliases like "list urls" or "url patterns" can be triggered by routine discussion, causing unintentional disclosure of route structure. In a Django context, URL maps may reveal internal endpoints, admin paths, or sensitive application architecture.

Vague Triggers

Medium
Confidence
94% confidence
Finding
Aliases such as "list users" and "show users" are highly ambiguous and map to a command that likely enumerates application users. Unintended activation could expose personally identifiable information or account metadata from the Django project.

Vague Triggers

Medium
Confidence
93% confidence
Finding
Aliases like "pending migrations" and "check pending migrations" are somewhat vague and may activate on normal maintenance-oriented language. While less severe than direct mutation commands, unintended migration-state disclosure can still reveal deployment posture and schema drift.

Static analysis

No suspicious patterns detected.