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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

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.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.