Back to skill

Security audit

ShellMail - Email Built for AI Agents

Security checks for vulnerabilities and agentic risk

Overview

The skill is a clearly disclosed ShellMail email client, but it needs review because its script has an avoidable local command-execution risk while handling a full-access mailbox token.

Install only if you are comfortable giving this skill persistent full access to a ShellMail inbox, including OTPs, sending, deletion, and address management. Prefer a separate ShellMail address for agent workflows, review send/delete actions carefully, and consider waiting for fixes to numeric validation of otp --wait and safer token handling before using it in sensitive environments.

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/shellmail.sh:107
Finding

Command Injection Through Unvalidated Bash Arithmetic Expansion

Content
View full analysis
&2)0]' ``` When Bash evaluates the timeout expression, the embedded command substitution may execute before the API request is issued. ### Attack Path 1. An attacker controls or influences the value used for the `otp --wait` option, such as through an untrusted request, copied command, or prompt-injected email content that is incorrectly treated as an instruction. 2. The agent invokes `scripts/shellmail.sh otp --wait` with the crafted arithmetic expression. 3. The value is interpolated into Bash arithmetic expansion without numeric validation. 4. Bash evaluates the malicious expression and executes its embedded command substitution. 5. The command runs with the same operating-system ...[truncated 799 chars]
Remediation
View remediation
&2 exit 1 fi if (( 10#$WAIT > 300 )); then echo "Error: --wait must not exceed 300 seconds" >&2 exit 1 fi PARAMS="${PARAMS}&timeout=$((10#$WAIT * 1000))" shift 2 ;; ``` Additional hardening should include: 1. Check that every option requiring a value has a following argument before accessing `$2`. 2. Apply strict numeric validation to `--limit` as well, even though it is placed into a URL rather than arithmetic expansion. 3. Reject unknown options instead of silently ignoring them. 4. Add regression tests using arithmetic expressions, command substitutions, missing values, negative numbers, and oversized values. 5. Ensure instructions obtained from mailbox contents are always treated as untrusted data and never copied into command arguments without validation. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/shellmail.sh:61
Finding

Full-Access Bearer Token Exposed Through Curl Process Arguments

Content
View full analysis
&2 exit 1 fi echo "Authorization: Bearer $TOKEN" } ``` It is then expanded into the argument list of each authenticated `curl` process. Representative sinks include: ```bash curl -sf "$API_URL/api/mail?${UNREAD}limit=${LIMIT}" -H "$(auth_header)" ``` ```bash curl -sf -X DELETE "$API_URL/api/addresses/me" -H "$(auth_header)" ``` ```bash printf '%s' "$json" | curl -sf -X POST "$API_URL/api/mail/send" \ -H "$(auth_header)" \ -H "Content-Type: application/json" \ -d @- ``` ### Technical Analysis Command substitution expands `$(auth_header)` before `curl` starts. The resulting value, including `Authorization: Bearer `, becomes part of `curl`'s process argument vector. Depending on the operating system, container configuration, process-monitoring software, crash diagnostics, or local account separation, process command lines may be observable through facilities such as process listings or `/proc//cmdline`. Even if exposure exists only for the duration of the request, repeated mailbox operations create repeated opportunities to capture the credential. The token is especially sensitive because the documentation states that it grants access to inbox contents, OTPs, outbound sending, permanent message deletion, and address management. ### Attack Path 1. The skill performs any authenticated ShellMail operation. 2. The shell expands the authorization header and starts `curl` with the bearer token in its argument vector. 3. A local process, monitoring agent, diagnosti ...[truncated 1059 chars]
Remediation
View remediation
&2 return 1 fi curl --config - "$@" <
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • 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 (7)

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/shellmail.sh (reported line 268)May include surrounding context.

sh
done
    [ -z "$BODY" ] && { echo "Error: --body required" >&2; exit 1; }
    # Fetch original email to get recipient and subject
    ORIGINAL=$(curl -sf "$API_URL/api/mail/$(urlencode "$REPLY_ID")" -H "$(auth_header)")
    TO=$(echo "$ORIGINAL" | python3 -c "import sys, json; print(json.loads(sys.stdin.read())['from_addr'])")
    SUBJECT=$(echo "$ORIGINAL" | python3 -c "import sys, json; s=json.loads(sys.stdin.read())['subject']; print(s if s.startswith('Re:') else 'Re: '+s)")
    if command -v jq >/dev/null 2>&1; then

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

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/shellmail.sh (reported line 132)May include surrounding context.

sh
esac
    done
    PARAMS="${PARAMS#&}"
    curl -sf "$API_URL/api/mail/search${PARAMS:+?$PARAMS}" -H "$(auth_header)"
    ;;

  mark-read)

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/shellmail.sh (reported line 193)May include surrounding context.

sh
else
      json=$(python3 -c "import sys, json; print(json.dumps({'local': sys.argv[1], 'recovery_email': sys.argv[2]}))" "$1" "$2")
    fi
    printf '%s' "$json" | curl -sf -X POST "$API_URL/api/addresses" \
      -H "Content-Type: application/json" \
      -d @-
    ;;

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/shellmail.sh (reported line 206)May include surrounding context.

sh
else
      json=$(python3 -c "import sys, json; print(json.dumps({'address': sys.argv[1], 'recovery_email': sys.argv[2]}))" "$1" "$2")
    fi
    printf '%s' "$json" | curl -sf -X POST "$API_URL/api/recover" \
      -H "Content-Type: application/json" \
      -d @-
    ;;

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/shellmail.sh (reported line 248)May include surrounding context.

sh
else
      json=$(python3 -c "import sys, json; d={'to': sys.argv[1], 'subject': sys.argv[2], 'body_text': sys.argv[3]}; sys.argv[4] and d.update({'body_html': sys.argv[4]}); print(json.dumps(d))" "$TO" "$SUBJECT" "$BODY" "$HTML")
    fi
    printf '%s' "$json" | curl -sf -X POST "$API_URL/api/mail/send" \
      -H "$(auth_header)" \
      -H "Content-Type: application/json" \
      -d @-

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/shellmail.sh (reported line 277)May include surrounding context.

sh
else
      json=$(python3 -c "import sys, json; d={'to': sys.argv[1], 'subject': sys.argv[2], 'body_text': sys.argv[3]}; sys.argv[4] and d.update({'body_html': sys.argv[4]}); print(json.dumps(d))" "$TO" "$SUBJECT" "$BODY" "$HTML")
    fi
    printf '%s' "$json" | curl -sf -X POST "$API_URL/api/mail/send" \
      -H "$(auth_header)" \
      -H "Content-Type: application/json" \
      -d @-

Static analysis

No suspicious patterns detected.