T01 · Skill Instruction Hijacking
- Location
scripts/build-cron-payload.sh:49- Finding
Stored Prompt Injection Through User-Controlled Reminder Content
- Content
View full analysis
Vulnerability Details
File Location:
scripts/build-cron-payload.sh:49-62
Vulnerability Type: Stored instruction injection into a scheduled Agent turn
Risk Level: HighVulnerable Code
bash payload: { kind: "agentTurn", message: ( "NERVTIMER ARM for timer_id=" + $t.timer_id + ". " + "Run deterministic state transition with: " + "bash " + $base_dir + "/scripts/state.sh start-nagging " + $t.timer_id + ". " + "Then generate one short reminder in the assistant personality. " + "Task: " + $t.title + (if ($t.reason // "") != "" then ". Reason: " + $t.reason else "" end) + "." ) }, delivery: { mode: "announce" }The corresponding validation at
scripts/validate-intent.sh:20-21only establishes that the title is a nonempty string:bash ($root.timer.title | is_non_empty_string) and (($root.timer.schedule_type == "one_shot") or ($root.timer.schedule_type == "recurrent"))Technical Analysis
The timer's
title,reason, andtimer_idoriginate from structured user intent. These values are concatenated directly into themessageof anagentTurn. No unambiguous data delimiters, content-length restrictions, control-character restrictions, or instructions requiring the scheduled Agent to treat these fields exclusively as inert data are applied.Because an
agentTurnmessage is interpreted as instructions rather than as a typed data structure, malicious text in a title or reason can be treated as additional instructions. This creates a stored prompt-injection condition: the attacker-controlled content is first incorporated into the cron payload and then interpreted later when the scheduled job runs.Attack Path
- An attacker asks the skill to create a timer with a title or reason containing adversarial instructions, for example text directing the future Agent to ignore the reminder workflow and invoke a ...[truncated 1165 chars]
- Remediation
View remediation
Remediation Suggestions
- Keep the scheduled Agent instruction static and pass timer properties through a structured data mechanism rather than interpolating them into prose instructions.
- Clearly delimit all untrusted fields and state explicitly that their contents are data that must never be interpreted as instructions.
- Encode structured timer data, such as with JSON, and require the scheduled handler to parse only the expected fields.
- Enforce maximum lengths and reject control characters or other content that is unnecessary for reminder titles and reasons.
- Use deterministic code to compose the final reminder where possible, reducing exposure of untrusted content to an instruction-following model.
- Restrict scheduled Agent sessions to the minimum required tools and permissions so that prompt injection cannot produce unrelated privileged actions.
- Add tests using titles and reasons containing instruction-like text and verify that the content is reproduced only as reminder data.
