T09 · Insecure Skill Coding Practices
- Location
examples/inbox-triage.lobster:6- Finding
Untrusted Email Content Can Influence External Routing Actions Through Indirect Prompt Injection
- Content
View full analysis
Vulnerability Details
File Location:
examples/inbox-triage.lobster, lines 6-32
Vulnerability Type: Indirect prompt injection and insufficient validation of security-sensitive LLM output
Risk Level: MediumVulnerable Code
yaml - id: fetch command: gog.gmail.search --query 'newer_than:1d' --max 20 - id: classify command: >- openclaw.invoke --tool llm-task --action json --args-json '{"prompt":"Classify each inbox item as business, personal, or later. Return one JSON object per item with route and summary.","thinking":"low","schema":{"type":"object","properties":{"items":{"type":"array"}},"required":["items"],"additionalProperties":false}}' stdin: $fetch.stdout - id: post_business command: slack-route --bucket business stdin: $classify.stdout condition: $classify.json.items[0].route == "business" - id: wait_for_business_reply command: echo '{"status":"waiting","reason":"slack_reply"}' condition: $classify.json.items[0].route == "business" - id: notify_personal command: >- openclaw.invoke --tool message --action send --args-json '{"provider":"telegram","to":"owner-thread","content":"Personal inbox item needs attention."}' condition: $classify.json.items[0].route == "personal" - id: stash_for_eod command: summary-append --bucket eod stdin: $classify.stdout condition: $classify.json.items[0].route == "later"Technical Analysis
The workflow retrieves externally controlled email content and passes the complete result directly to an LLM through
stdin. Email senders can therefore place prompt-like instructions in message subjects or bodies that attempt to override the classification request.The declared response schema only requires
itemsto be an array. It does not define the structure of each array element or constrainrouteto the permitted valuesbusiness,personal, andlater. The workflow then trusts `$classif ...[truncated 1923 chars]- Remediation
View remediation
Remediation Suggestions
- Treat all fetched email fields as untrusted data and clearly delimit them from system instructions supplied to the model.
- Define a strict item schema with required properties, bounded string lengths, and an enum such as
["business", "personal", "later"]. - Reject malformed output, unknown routes, empty arrays, and responses containing unexpected properties before evaluating conditions.
- Associate each classification result with an immutable message identifier and process each item independently rather than relying only on
items[0]. - Forward only the minimum fields required for the selected message. Do not pass the complete classifier response to external routing commands.
- Require explicit owner approval before transmitting mailbox-derived content to Slack or another external destination.
- Apply destination allowlists and least-privilege credentials to all messaging integrations.
- Add tests containing adversarial email text to verify that embedded instructions cannot alter workflow policy.
