Back to skill

Security audit

Local Deep Research

Security checks for vulnerabilities and agentic risk

Overview

This local research skill is mostly coherent, but it should be reviewed because its shell script can execute a sourced .env file and may send credentials to an insufficiently constrained login URL.

Install only if you control the LDR service and can run the skill in a constrained environment. Prefer environment variables over the .env path, verify that any LDR .env is private and contains only simple trusted assignments, keep LDR_BASE_URL and LDR_LOGIN_URL on the same trusted local origin, and use a dedicated low-privilege LDR account with a unique password.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/ldr-research.sh:24
Finding

Arbitrary Shell Execution Through Sourced Environment File

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ldr-research.sh:35
Finding

LDR Credentials Can Be Sent to an Untrusted, Plaintext, or Redirected Endpoint

Content
View full analysis
/dev/null) || true if [[ -z "$login_page" ]]; then log_error "Could not fetch login page at $LDR_LOGIN_URL" return 1 fi # Extract CSRF token from form (common: name="csrf_token" or "_csrf" or "csrf_token") CSRF_TOKEN=$(echo "$login_page" | sed -n 's/.*name="csrf_token"[^>]*value="\([^"]*\)".*/\1/p' | head -1) [[ -z "$CSRF_TOKEN" ]] && CSRF_TOKEN=$(echo "$login_page" | sed -n 's/.*name="_csrf"[^>]*value="\([^"]*\)".*/\1/p' | head -1) [[ -z "$CSRF_TOKEN" ]] && CSRF_TOKEN=$(echo "$login_page" | sed -n 's/.*value="\([^"]*\)"[^>]*name="csrf_token".*/\1/p' | head -1) if [[ -z "$CSRF_TOKEN" ]]; then log_warn "No CSRF token found on login page; POST may still work if LDR uses cookie-only CSRF" fi # POST login form (application/x-www-form-urlencoded) local post_data post_data="username=$(printf '%s' "$LDR_USERNAME" | jq -sRr @uri)&password=$(printf '%s' "$LDR_PASSWORD" | jq -sRr @uri)" [[ -n "$CSRF_TOKEN ...[truncated 4046 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (20)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 33)May include surrounding context.

md
end data to any endpoint other than the configured LDR service. You can review `scripts/ldr-research.sh` before use. For higher assurance, run it in an isolated

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 86)May include surrounding context.

md
end data to any endpoint other than the configured LDR service. You can review `scripts/ldr-research.sh` before use. For higher assurance, run it in an isolated

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 89)May include surrounding context.

md
end data to any endpoint other than the configured LDR service. You can review `scripts/ldr-research.sh` before use. For higher assurance, run it in an isolated

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 116)May include surrounding context.

md
end data to any endpoint other than the configured LDR service. You can review `scripts/ldr-research.sh` before use. For higher assurance, run it in an isolated

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 151)May include surrounding context.

md
end data to any endpoint other than the configured LDR service. You can review `scripts/ldr-research.sh` before use. For higher assurance, run it in an isolated

Context Leakage

High
Category
Data Exfiltration
Confidence
85% confidence
Finding

Code or instructions that leak agent conversation context to external services, potentially exposing sensitive user interactions.

Content

Scanner excerpt · references/api.md (reported line 72)May include surrounding context.

md
### GET /research/api/status/{research_id}

Check the status of a research job. Send session cookie.

**Path Parameters:** `research_id` — research job UUID.

Context Leakage

High
Category
Data Exfiltration
Confidence
85% confidence
Finding

Code or instructions that leak agent conversation context to external services, potentially exposing sensitive user interactions.

Content

Scanner excerpt · references/api.md (reported line 99)May include surrounding context.

md
### GET /research/api/status/{research_id}

Check the status of a research job. Send session cookie.

**Path Parameters:** `research_id` — research job UUID.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 246)May include surrounding context.

md
#   3. Reuses the session cookie (and CSRF token for POSTs) for API calls
# Credentials are for local LDR only; never transmitted elsewhere.
#
# Optional: ~/.config/local_deep_research/config/.env is sourced if present (verify its contents).
#

set -e

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/examples.md (reported line 77)May include surrounding context.

md
#   3. Reuses the session cookie (and CSRF token for POSTs) for API calls
# Credentials are for local LDR only; never transmitted elsewhere.
#
# Optional: ~/.config/local_deep_research/config/.env is sourced if present (verify its contents).
#

set -e

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/examples.md (reported line 80)May include surrounding context.

md
#   3. Reuses the session cookie (and CSRF token for POSTs) for API calls
# Credentials are for local LDR only; never transmitted elsewhere.
#
# Optional: ~/.config/local_deep_research/config/.env is sourced if present (verify its contents).
#

set -e

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/ldr-research.sh (reported line 18)May include surrounding context.

sh
#   3. Reuses the session cookie (and CSRF token for POSTs) for API calls
# Credentials are for local LDR only; never transmitted elsewhere.
#
# Optional: ~/.config/local_deep_research/config/.env is sourced if present (verify its contents).
#

set -e

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/ldr-research.sh (reported line 325)May include surrounding context.

sh
#   3. Reuses the session cookie (and CSRF token for POSTs) for API calls
# Credentials are for local LDR only; never transmitted elsewhere.
#
# Optional: ~/.config/local_deep_research/config/.env is sourced if present (verify its contents).
#

set -e

Credential Access

High
Category
Privilege Escalation
Confidence
92% confidence
Finding

The script sources a .env file from a user-controllable path using Bash source, which executes arbitrary shell code, not just key=value assignments. If an attacker can modify that file or influence LDR_CONFIG_DIR, they can achieve arbitrary command execution in the context of the script and access credentials or alter network destinations.

Content

Scanner excerpt · scripts/ldr-research.sh (reported line 23)May include surrounding context.

sh
set -e

# Load LDR's local .env if present (secrets stay local)
LDR_ENV="${LDR_CONFIG_DIR:-$HOME/.config/local_deep_research/config}/.env"
if [[ -f "$LDR_ENV" ]]; then
    set -a

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

The conditional around source causes any existing .env at the resolved path to be executed. Because this is an execution sink for local file contents, it creates a strong local code-execution and credential-compromise risk if the file path or file contents are attacker-controlled.

Content

Scanner excerpt · scripts/ldr-research.sh (reported line 24)May include surrounding context.

sh
set -e

# Load LDR's local .env if present (secrets stay local)
LDR_ENV="${LDR_CONFIG_DIR:-$HOME/.config/local_deep_research/config}/.env"
if [[ -f "$LDR_ENV" ]]; then
    set -a
    # shellcheck source=/dev/null

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README advertises very broad trigger phrases such as "research this topic" and "investigate [topic]", which are common natural-language requests and can cause the skill to activate unintentionally. In an agent environment, accidental invocation can expand the skill’s network and shell use, potentially sending user queries to the local research service without clear intent.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · README.md (reported line 45)May include surrounding context.

md
## Credentials (local-only)

LDR uses **session-cookie authentication with CSRF protection** (not HTTP Basic Auth). The script performs a proper login flow: fetches the login page for a session cookie and CSRF token, then POSTs the login form. Your username and password are used **only** to create that session with **your local** LDR instance (and for LDR’s per-user encrypted results).

- **They are not transmitted** to any third party or to ClawHub/GitHub — only to your own LDR instance (e.g. on localhost).
- **Do not** put credentials in the skill config file or commit them to git.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger list includes broad phrases such as "research this topic", "quick summary on [topic]", and "detailed report on [topic]", which are common user requests and may cause unintended activation beyond this specific skill. The description also says the skill is used for "any research requiring exhaustive web search," which lacks clear exclusion boundaries or negative examples.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · SKILL.md (reported line 39)May include surrounding context.

md
### Credentials (local-only, never transmitted)

LDR uses **session-cookie auth with CSRF protection** (not HTTP Basic Auth). The skill script performs a proper login flow: GET login page → obtain session cookie and CSRF token → POST credentials + CSRF → reuse session cookie (and CSRF for POSTs) for all API calls. Username and password are used **only** to create a session with your **local** LDR instance; they are never sent to ClawHub, GitHub, or any other server.

**Do not** put credentials in skill config or committed files. Use **environment variables or a local `.env` file** only (e.g. `LDR_SERVICE_USER`, `LDR_SERVICE_PASSWORD`, or `LDR_USERNAME`/`LDR_PASSWORD`). Optional: LDR’s `~/.config/local_deep_research/config/.env` is sourced by the script if present. Use a dedicated LDR user (e.g. `openclaw_service`) for this skill.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/ldr-research.sh (reported line 88)May include surrounding context.

sh
[[ -n "$CSRF_TOKEN" ]] && post_data="csrf_token=$(printf '%s' "$CSRF_TOKEN" | jq -sRr @uri)&$post_data"

    local http_code
    http_code=$(curl -s -o /dev/null -w "%{http_code}" -c "$COOKIE_JAR" -b "$COOKIE_JAR" -L --max-time "$HTTP_TIMEOUT" \
        -X POST \
        -H "Content-Type: application/x-www-form-urlencoded" \
        -d "$post_data" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/ldr-research.sh (reported line 113)May include surrounding context.

sh
while [[ $attempt -lt $RETRY_COUNT ]]; do
        local response http_code
        if [[ "$method" == "GET" ]]; then
            response=$(curl -s -w "\n%{http_code}" -b "$COOKIE_JAR" --max-time "$HTTP_TIMEOUT" "$url" 2>/dev/null)
        else
            if [[ -n "$CSRF_TOKEN" ]]; then
                response=$(curl -s -w "\n%{http_code}" -b "$COOKIE_JAR" -H "X-CSRFToken: $CSRF_TOKEN" --max-time "$HTTP_TIMEOUT" \