Back to skill

Security audit

Trawl

Security checks for vulnerabilities and agentic risk

Overview

This skill is purpose-aligned lead-generation automation, but it gives local configuration too much power over credentials and outbound network destinations.

Review this before installing. Use a dedicated MoltBook token with limited privileges, keep ~/.config/trawl writable only by you, do not point api_base at non-MoltBook hosts, and avoid setting api_key_env to any credential other than MOLTBOOK_API_KEY. Treat auto_approve_inbound and scheduled sweeps as account-impacting automation because they can message other agents on your behalf.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/sweep.sh:47
Finding

Configurable API destination can receive arbitrary environment credentials

Content
View full analysis
/dev/null || echo '{"success":false,"results":[],"count":0}' ``` ```bash # scripts/qualify.sh:32-34 API_BASE=$(jq -r '.sources.moltbook.api_base' "$CONFIG") API_KEY_ENV=$(jq -r '.sources.moltbook.api_key_env' "$CONFIG") API_KEY="${!API_KEY_ENV:-}" ``` ```bash # scripts/qualify.sh:216-219 curl -s -f -X POST "$API_BASE/agents/dm/conversations/$conv_id/send" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d "$(jq -n --arg msg "$next_question" '{message:$msg}')" > /dev/null 2>&1 ``` ```bash # scripts/leads.sh:107-113 API_BASE=$(jq -r '.sources.moltbook.api_base' "$CONFIG" 2>/dev/null || echo "") API_KEY_ENV=$(jq -r '.sources.moltbook.api_key_env' "$CONFIG" 2>/dev/null || echo "MOLTBOOK_API_KEY") API_KEY="${!API_KEY_ENV:-}" if [ -n "$API_KEY" ] && [ -n "$CONV_ID" ] && [ "$CONV_ID" != "null" ]; then curl -s -f -X POST "$API_BASE/agents/dm/requests/$CONV_ID/approve" \ -H "Authorization: Bearer $API_KEY" > /dev/null 2>&1 && echo " ✓ DM request approved via API" || echo " ⚠ API approve failed (will retry next qualify cycle)" fi ``` ```json // config.example.json:50-51 "api_key_env": "MOLTBOOK_API_KEY", "api_base": "https://www.moltbook.com/api/v1" ``` ### Technical Analysis The API origin and the name of the environment variable used as its cr ...[truncated 2212 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/qualify.sh:128
Finding

Dry-run mode modifies persistent production state

Content
View full analysis
"$SEEN_POSTS.tmp" && mv "$SEEN_POSTS.tmp" "$SEEN_POSTS" ``` It also writes mock leads into the normal lead database: ```bash # scripts/sweep.sh:505-508 jq --arg key "moltbook:$author_name" --argjson lead "$lead_entry" \ '.leads[$key] = $lead' "$LEADS_FILE" > "$LEADS_FILE.tmp" && mv "$LEADS_FILE.tmp" "$LEADS_FILE" NEW_LEADS=$((NEW_LEADS + 1)) ``` `qualify.sh --dry-run` changes an existing lead's state: ```bash # scripts/qualify.sh:128-133 if [ "$DRY_RUN" = true ]; then # Dry run: simulate approval for first lead only if [ "$APPROVED" -eq 0 ]; then echo " ✓ $agent_name DM approved → QUALIFYING (simulated)" update_lead_state "$key" "QUALIFYING" APPROVED=$((APPROVED + 1)) ``` It records a question as asked even when no DM is sent: ```bash # scripts/qualify.sh:212-228 if [ "$DRY_RUN" = true ]; then echo " (dry run: would send via DM)" else if [ -n "$conv_id" ] && [ "$conv_id" != "null" ]; then curl -s -f -X POST "$API_BASE/agents/dm/conversations/$conv_id/send" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d "$(jq -n --arg msg "$next_question" '{message:$msg}')" > /dev/null 2>&1 fi fi # Update qualifying data new_asked=$((questions_asked + 1)) NOW=$(date -u +"%Y-%m-%dT%H:%M:%SZ") jq --arg key "$key" --argjson asked "$new_asked" --arg now "$NOW" \ '.leads[$key].qualifyingData = {"questionsAsked": $asked, "responses": []} | .leads[$key].lastUpdated = $now' \ "$LEADS_FILE" ...[truncated 1831 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/setup.sh:11
Finding

Sensitive lead data is created without explicitly restrictive permissions

Content
View full analysis
"$TRAWL_DIR/$file" elif [ "$file" = "conversations.json" ]; then echo '{"conversations":{}}' > "$TRAWL_DIR/$file" elif [ "$file" = "sweep-log.json" ]; then echo '{"sweeps":[]}' > "$TRAWL_DIR/$file" elif [ "$file" = "seen-posts.json" ]; then echo '{"posts":{}}' > "$TRAWL_DIR/$file" fi echo "✓ Created $file" else echo "• $file already exists (skipped)" fi done ``` ### Technical Analysis The setup script creates the data directory and files without setting a restrictive `umask` or applying explicit modes. Resulting permissions therefore depend on the invoking process's environment. The lead database and generated report can contain owner names, social handles, biographies, business interests, inbound message previews, lead decisions, scores, and conversation identifiers. Although the API key remains in a separate secrets file, this locally stored business and personal data may be sensitive. On a shared system with a permissive umask, these files may be readable by other local users. The repeated use of predictable `.tmp` paths elsewhere also warrants symlink and ownership checks when replacing files. ### Attack Path 1. The user runs `setup.sh` un ...[truncated 809 chars]
Remediation
View remediation
/dev/null || true ``` 3. Verify that the directory and existing files are owned by the current user before reading or replacing them. 4. Reject symbolic links for configuration, state, report, and temporary output files. 5. Prefer temporary files created with `mktemp` inside the protected directory, followed by an atomic rename. 6. Document that the directory contains potentially sensitive business and personal data and should not be shared. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/report.sh:50
Finding

Untrusted filter values are interpolated into jq programs

Content
View full analysis
/dev/null || cat COUNT=$(jq "[$FILTER] | length" "$LEADS_FILE") ``` ### Technical Analysis Category and state values are inserted directly into jq source code inside quoted string literals. An input containing a quote and additional jq syntax can terminate the intended string and alter the jq expression. This is not shell command injection because the expanded value remains an argument passed to `jq`; shell metacharacters inside the variable are not reparsed by the shell. It is nevertheless code injection into jq's expression language. An injected jq program can change filters, expose additional records, cons ...[truncated 1473 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (40)

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/moltbook-api.md (reported line 30)May include surrounding context.

DM System

text
GET  /agents/dm/check              — Quick activity poll
POST /agents/dm/request            — Send chat request {to, message}
GET  /agents/dm/requests           — View pending inbound
POST /agents/dm/requests/{id}/approve
POST /agents/dm/requests/{id}/reject  (optional: {block: true})

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/leads.sh (reported line 159)May include surrounding context.

sh
echo '{"posts":{}}' > "$TRAWL_DIR/seen-posts.json" 2>/dev/null || true
    echo '{"conversations":{}}' > "$TRAWL_DIR/conversations.json" 2>/dev/null || true
    echo '{"sweeps":[]}' > "$TRAWL_DIR/sweep-log.json" 2>/dev/null || true
    rm -f "$TRAWL_DIR/last-sweep-report.json"
    echo "✓ All data reset"
    ;;

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

Referencing $HOME/.clawdbot/secrets.env is a concrete credential-access mechanism into another application's secret material. Even though the script extracts only MOLTBOOK_API_KEY, that still constitutes unauthorized lateral use of credentials and weakens separation between tools. Because this skill autonomously interacts with a social network API, the imported token can be used immediately for account actions and data access.

Content

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

sh
done

# Load secrets (defensive: extract only required vars, no arbitrary execution)
SECRETS_FILE="$HOME/.clawdbot/secrets.env"
if [ -f "$SECRETS_FILE" ]; then
  MOLTBOOK_API_KEY="${MOLTBOOK_API_KEY:-$(grep -E '^MOLTBOOK_API_KEY=' "$SECRETS_FILE" 2>/dev/null | cut -d'=' -f2- | tr -d '"'"'" || true)}"
  export MOLTBOOK_API_KEY

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

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

md
done

# Load secrets (defensive: extract only required vars, no arbitrary execution)
SECRETS_FILE="$HOME/.clawdbot/secrets.env"
if [ -f "$SECRETS_FILE" ]; then
  MOLTBOOK_API_KEY="${MOLTBOOK_API_KEY:-$(grep -E '^MOLTBOOK_API_KEY=' "$SECRETS_FILE" 2>/dev/null | cut -d'=' -f2- | tr -d '"'"'" || true)}"
  export MOLTBOOK_API_KEY

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/leads.sh (reported line 101)May include surrounding context.

sh
done

# Load secrets (defensive: extract only required vars, no arbitrary execution)
SECRETS_FILE="$HOME/.clawdbot/secrets.env"
if [ -f "$SECRETS_FILE" ]; then
  MOLTBOOK_API_KEY="${MOLTBOOK_API_KEY:-$(grep -E '^MOLTBOOK_API_KEY=' "$SECRETS_FILE" 2>/dev/null | cut -d'=' -f2- | tr -d '"'"'" || true)}"
  export MOLTBOOK_API_KEY

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/setup.sh (reported line 43)May include surrounding context.

sh
done

# Load secrets (defensive: extract only required vars, no arbitrary execution)
SECRETS_FILE="$HOME/.clawdbot/secrets.env"
if [ -f "$SECRETS_FILE" ]; then
  MOLTBOOK_API_KEY="${MOLTBOOK_API_KEY:-$(grep -E '^MOLTBOOK_API_KEY=' "$SECRETS_FILE" 2>/dev/null | cut -d'=' -f2- | tr -d '"'"'" || true)}"
  export MOLTBOOK_API_KEY

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/setup.sh (reported line 44)May include surrounding context.

sh
done

# Load secrets (defensive: extract only required vars, no arbitrary execution)
SECRETS_FILE="$HOME/.clawdbot/secrets.env"
if [ -f "$SECRETS_FILE" ]; then
  MOLTBOOK_API_KEY="${MOLTBOOK_API_KEY:-$(grep -E '^MOLTBOOK_API_KEY=' "$SECRETS_FILE" 2>/dev/null | cut -d'=' -f2- | tr -d '"'"'" || true)}"
  export MOLTBOOK_API_KEY

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/setup.sh (reported line 45)May include surrounding context.

sh
done

# Load secrets (defensive: extract only required vars, no arbitrary execution)
SECRETS_FILE="$HOME/.clawdbot/secrets.env"
if [ -f "$SECRETS_FILE" ]; then
  MOLTBOOK_API_KEY="${MOLTBOOK_API_KEY:-$(grep -E '^MOLTBOOK_API_KEY=' "$SECRETS_FILE" 2>/dev/null | cut -d'=' -f2- | tr -d '"'"'" || true)}"
  export MOLTBOOK_API_KEY

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/setup.sh (reported line 47)May include surrounding context.

sh
done

# Load secrets (defensive: extract only required vars, no arbitrary execution)
SECRETS_FILE="$HOME/.clawdbot/secrets.env"
if [ -f "$SECRETS_FILE" ]; then
  MOLTBOOK_API_KEY="${MOLTBOOK_API_KEY:-$(grep -E '^MOLTBOOK_API_KEY=' "$SECRETS_FILE" 2>/dev/null | cut -d'=' -f2- | tr -d '"'"'" || true)}"
  export MOLTBOOK_API_KEY

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/setup.sh (reported line 48)May include surrounding context.

sh
done

# Load secrets (defensive: extract only required vars, no arbitrary execution)
SECRETS_FILE="$HOME/.clawdbot/secrets.env"
if [ -f "$SECRETS_FILE" ]; then
  MOLTBOOK_API_KEY="${MOLTBOOK_API_KEY:-$(grep -E '^MOLTBOOK_API_KEY=' "$SECRETS_FILE" 2>/dev/null | cut -d'=' -f2- | tr -d '"'"'" || true)}"
  export MOLTBOOK_API_KEY

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/setup.sh (reported line 51)May include surrounding context.

sh
done

# Load secrets (defensive: extract only required vars, no arbitrary execution)
SECRETS_FILE="$HOME/.clawdbot/secrets.env"
if [ -f "$SECRETS_FILE" ]; then
  MOLTBOOK_API_KEY="${MOLTBOOK_API_KEY:-$(grep -E '^MOLTBOOK_API_KEY=' "$SECRETS_FILE" 2>/dev/null | cut -d'=' -f2- | tr -d '"'"'" || true)}"
  export MOLTBOOK_API_KEY

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/setup.sh (reported line 58)May include surrounding context.

sh
done

# Load secrets (defensive: extract only required vars, no arbitrary execution)
SECRETS_FILE="$HOME/.clawdbot/secrets.env"
if [ -f "$SECRETS_FILE" ]; then
  MOLTBOOK_API_KEY="${MOLTBOOK_API_KEY:-$(grep -E '^MOLTBOOK_API_KEY=' "$SECRETS_FILE" 2>/dev/null | cut -d'=' -f2- | tr -d '"'"'" || true)}"
  export MOLTBOOK_API_KEY

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

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

sh
done

# Load secrets (defensive: extract only required vars, no arbitrary execution)
SECRETS_FILE="$HOME/.clawdbot/secrets.env"
if [ -f "$SECRETS_FILE" ]; then
  MOLTBOOK_API_KEY="${MOLTBOOK_API_KEY:-$(grep -E '^MOLTBOOK_API_KEY=' "$SECRETS_FILE" 2>/dev/null | cut -d'=' -f2- | tr -d '"'"'" || true)}"
  export MOLTBOOK_API_KEY

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/sweep.sh (reported line 56)May include surrounding context.

sh
done

# Load secrets (defensive: extract only required vars, no arbitrary execution)
SECRETS_FILE="$HOME/.clawdbot/secrets.env"
if [ -f "$SECRETS_FILE" ]; then
  MOLTBOOK_API_KEY="${MOLTBOOK_API_KEY:-$(grep -E '^MOLTBOOK_API_KEY=' "$SECRETS_FILE" 2>/dev/null | cut -d'=' -f2- | tr -d '"'"'" || true)}"
  export MOLTBOOK_API_KEY

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill advertises and operationalizes shell scripts plus outbound network activity, but the manifest does not declare an explicit tool scope such as allowed tools or permissions. That mismatch weakens sandboxing and user consent because an agent may invoke shell/network capabilities more broadly than the skill metadata communicates.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill performs autonomous lead discovery, outbound DMs, inbound DM handling, and stores conversation and profile data, yet it provides no explicit privacy or user-data warning. This creates a real risk of undisclosed collection, processing, and outreach using personal or business profile data, especially because the workflow is designed to run unattended.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
94% confidence
Finding

The documented auto_approve_inbound option enables the agent to automatically accept inbound DM requests and proceed with qualification logic without human review. In this context, that is risky because it allows autonomous engagement with untrusted external parties, increasing exposure to spam, prompt-injection content, social engineering, and unintended disclosures.

Content

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

md
- **signals** — What you're hunting for (semantic queries + categories)
- **sources.moltbook** — MoltBook settings (submolts, enabled flag)
- **scoring** — Confidence thresholds for discovery and qualification
- **qualify** — DM strategy, intro template, qualifying questions, `auto_approve_inbound`
- **reporting** — Channel, frequency, format

Signals have `category` labels for multi-profile hunting (e.g., "consulting", "sales", "recruiting").

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
95% confidence
Finding

The later inbound-handling section explicitly instructs users they can set auto_approve_inbound: true to auto-accept all inbound requests. In a skill centered on agent-to-agent messaging, this materially increases the danger by turning unsolicited external contact into automatic conversational access, which can be abused for manipulation or data harvesting.

Content

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

md
- Creates lead as INBOUND_PENDING
- Reports to you for approval
- `leads.sh decide <key> --pursue` approves the DM and starts qualifying
- Or set `auto_approve_inbound: true` in config to auto-accept all

## Reports

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest-style JSON defines a signal query of "looking for AI consultant or automation help," which includes the broad phrase "automation help." Without narrower scope, exclusions, or context constraints, this could match ordinary conversation and cause unintended skill activation.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The query "your industry vertical or niche keywords" is a placeholder rather than a real, specific trigger definition. Because it does not enumerate actual keywords or boundaries, the activation conditions are unclear and likely to be inconsistently or overly broadly implemented.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This interface explicitly supports outbound DMs and public commenting to third-party accounts, but the documentation includes no guardrails around user consent, account impact, rate limits, approval workflows, or anti-spam controls. In the context of an autonomous lead-generation skill that 'qualifies leads via DM conversations' while operating unattended, this omission materially increases the risk of unauthorized outreach, spammy behavior, platform-policy violations, and reputational harm to the user's external account.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The header comment and usage block describe a lead database management utility, implying operations on lead records. The reset implementation contradicts that framing by wiping conversations, seen posts, and sweep logs, which are distinct trawl subsystems rather than just lead database contents.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script performs persistent writes to the leads database for update, decide, and archive operations by rewriting leads.json, but these commands do not prompt for confirmation or provide an upfront warning before altering user data. Because these are direct state changes to a lead database, some user-facing disclosure is expected unless the destructive behavior is clearly limited to an obviously destructive command like reset.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The file is documented and positioned as 'Manage lead database' with usage focused on listing, getting, updating, deciding, archiving, and stats for leads. However, the implemented reset action deletes not only leads but also seen posts, conversations, sweep logs, and the last sweep report, which exceeds the described lead-management behavior.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script reads a bearer token from another tool's secrets directory ($HOME/.clawdbot/secrets.env), creating cross-tool credential access that exceeds least-privilege and can silently reuse credentials the user did not intend this skill to consume. In the context of an autonomous lead-generation skill that performs network actions, this is especially risky because the imported credential can immediately be used to query or message external services without explicit user consent.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.