T01 · Skill Instruction Hijacking
- Location
email.agent.ts:30- Finding
User-Controlled Instructions Are Elevated to a System Message
- Content
View full analysis
Vulnerability Details
File Location:
email.agent.ts, lines 30–39
Vulnerability Type: Prompt injection through privileged instruction placement
Risk Level: Mediumtypescript async sendEmail(dto: SendEmailDto) { const { email, name, subject = '', body = '', instructions = '' } = dto; const result = await this.agent.invoke({ messages: [ { role: "system", content: message.EMAIL_PROMPT(instructions), }, { role: "user", content: message.EMAIL_USER_MESSAGE(email, name, subject, body), }, ], });Technical Analysis
The caller-controlled
dto.instructionsvalue is passed tomessage.EMAIL_PROMPTand the resulting content is assigned the privilegedsystemrole. Consequently, untrusted instructions may be interpreted with greater authority than the email data supplied in theusermessage.An attacker could submit instructions that attempt to override the intended email-composition rules, alter recipients or message content, conceal relevant information from the approver, or induce unintended
EmailToolcalls. The implementation ofmessage.EMAIL_PROMPTwas outside the supplied audit scope, so any internal escaping or delimitation could not be verified.The configured human-in-the-loop middleware requires an approve, edit, or reject decision for
EmailTool, which reduces the likelihood of automatic delivery. It does not eliminate the underlying prompt-injection condition because manipulated output or tool arguments may still be presented to an approving user.Attack Path
- An attacker or untrusted caller provides a crafted value in
dto.instructions. sendEmailpasses that value tomessage.EMAIL_PROMPT.- The generated prompt is assigned the
systemrole. - The model interprets the attacker-controlled text as privileged instructions and may compose altered content or request an unintended `Em ...[truncated 851 chars]
- An attacker or untrusted caller provides a crafted value in
- Remediation
View remediation
Remediation Suggestions
- Use a fixed, application-controlled system prompt. Place caller-provided composition preferences in a clearly delimited user-role message rather than interpolating them into system-role content.
- Treat model-generated tool arguments as untrusted. Validate and authorize the recipient, subject, body, attachments, and other delivery options inside
EmailTool. - Bind the permitted recipient and other security-sensitive fields to validated application data instead of allowing the model to redefine them.
- Apply schema validation, length limits, and control-character filtering to every
SendEmailDtofield. - Display a structured approval view showing the final recipient, subject, body, attachments, and sender identity. Highlight differences between requested and model-generated values.
- Verify with integration tests that
humanInTheLoopMiddlewarereliably intercepts the exact registered tool name and that rejection prevents all delivery side effects. - Ensure authorization and recipient policy checks remain mandatory even when a human approves the request.
