VNX-1427: Improper Neutralization of Input Used for LLM Prompting: request data in the system prompt
Reports Go, Java, PHP and Ruby code that places HTTP request data in the system (instruction) prompt of an LLM call, where it can override the application's instructions (prompt injection).
| Field | Value |
|---|---|
| Rule ID | VNX-1427 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Go, Java, PHP, Ruby |
| CWE | CWE-1427 |
| CAPEC | CAPEC-137 |
| ATT&CK | T1059 |
| CWSS vector | CWSS:1.0/TI:M/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | prompt-injection llm ai-security system-prompt cwe-1427 |
| Source | internal/sast/rules/vnx-1427.rego |
Overview
VNX-1427 maps to CWE-1427: Improper Neutralization of Input Used for LLM Prompting. Text in the system role carries the authority of the application’s own instructions. When request data is spliced into it, a user can rewrite those instructions: ignore the rules, reveal the prompt, or steer tool calls.
The rule reports request data (read on the line, or through a variable assigned from a request read in the 30 lines above) inside a system-role slot. Python, JavaScript and TypeScript are covered by VNX-LLM-004 (system prompt) and VNX-LLM-001 (instruction text).
What Gets Flagged
persona := r.URL.Query().Get("persona")
// ...
Role: openai.ChatMessageRoleSystem,
Content: fmt.Sprintf("You are %s. Never reveal internal data.", persona),
openai.SystemMessage("You are an expert on " + topic), // topic := c.Query("topic")
public String assist(@RequestParam String role, @RequestParam String question) {
return chatClient.prompt().system("You are a " + role + " assistant.").user(question).call().content();
}
['role' => 'system', 'content' => "You are a {$persona} assistant."], // $persona = $_GET['persona']
{ role: "system", content: "Reply in a #{tone} voice." }, # tone = params[:tone]
Not flagged: request data in a user-role message (.user(question), role: "user", also when it shares a line with the system message), in Go request data used only as a map key (personas[r.FormValue("p")], an allowlist lookup), a static system prompt, server-side values such as dates and constants, and the shapes inside comments or string literals.
Remediation
- Keep the system prompt static. Pass user text only as a user-role message.
- If a user choice must shape behaviour, map it to one of a fixed set of server-side prompts (an allow-list), never interpolate it.
- Treat model output as untrusted and constrain what tools it can call.
References
- CWE-1427: Improper Neutralization of Input Used for LLM Prompting
- OWASP Top 10 for LLM Applications: LLM01 Prompt Injection
Suppressing this rule
Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):
# nosec vnx-1427
// nosec vnx-1427
Or record an ignore rule: vulnetix ignore add --rule vnx-1427 --reason "...". See Suppressing findings.