Error responses from AI routes frequently contain more information than developers intend. Some AI SDK versions include the full request payload—including the messages array with the system prompt—in error objects. A catch block that returns error.response.data or JSON.stringify(error) exposes the system prompt to any user who triggers a failed request. CWE-209 covers this class of error-based information disclosure directly. OWASP LLM01:2025 treats system prompt exposure as a primary attack enabler regardless of the disclosure path—an error-triggered leak is just as useful for reconnaissance as a direct leak in the success path.
Medium because triggering the error condition requires either luck or intentional probing, making it harder to exploit opportunistically than a direct system prompt exposure in the success path.
Log the full error detail server-side; return a generic, client-safe message. Treat this identically to how you handle database errors—full details in logs, nothing sensitive in the response.
// src/app/api/chat/route.ts
try {
const completion = await openai.chat.completions.create({
messages, // system prompt lives here — must not reach the client
model: 'gpt-4o'
})
return Response.json({
message: completion.choices[0]?.message?.content
})
} catch (error) {
// Full detail goes to server logs only
console.error('[AI route] completion error:', error)
// Generic message goes to the client — no prompt content, no SDK error details
return Response.json(
{ error: 'Unable to process your request. Please try again.' },
{ status: 500 }
)
}
Also audit any error-monitoring integrations (Sentry, Datadog): ensure the messages array is scrubbed from error payloads before they are shipped to third-party logging services.
ID: ai-prompt-injection.system-prompt-protection.no-prompt-in-errors
Severity: medium
What to look for: Count all error handling paths in LLM integration code. For each, examine error handling in AI-related API routes. Check whether error responses include the original request payload (which may contain the system prompt), the AI provider's error details (which sometimes echo the request), or any debugging information that would reveal prompt construction. Look for catch blocks that return the full error object or the messages array.
Pass criteria: Error responses from AI routes return generic, user-safe messages ("Something went wrong with the AI request") without echoing back the prompt, messages array, or provider-specific error details that include request content — 0% of error responses should contain raw prompt text or LLM configuration details. Report: "X error paths found, 0 expose prompt content."
Fail criteria: Error responses include the original messages array, the system prompt content, or provider error details that echo the request.
Skip (N/A) when: No AI provider integration detected.
Detail on fail: "Catch block in POST /api/chat returns the full error object including the original messages array used in the failed request" or "AI provider error response (which echoes the system prompt) is returned directly to the client"
Remediation: Treat AI request errors like database errors — log the full detail internally, return a generic message externally:
try {
const completion = await openai.chat.completions.create({ messages, model })
return Response.json({ message: completion.choices[0]?.message?.content })
} catch (error) {
console.error('AI completion error:', error) // full detail in server logs
return Response.json(
{ error: 'Unable to process your request. Please try again.' },
{ status: 500 }
)
}