Risk OS Red Try Stoa

AI001 · STOA-LLM01-PROMPT-EXPOSURE

Untrusted input observed flowing into prompt construction.

Detection

A taint chain from an untrusted source to a prompt sink:

req.body/query/params), input()/sys.stdin, open(...).read(), and retrieval results (retriever.invoke, similarity_search, index.query) — the indirect-injection surface.

(client.messages.create, chat.completions.create, llm.invoke, generateText, …), or a prompt template that reaches such a call.

message) escalates confidence one tier and tags system_role_interpolation.

Vulnerable → remediated

# VULNERABLE — request value interpolated into system instructions
topic = request.get_json()["topic"]
prompt = f"You are a support bot. Answer about {topic}."
client.messages.create(system=prompt, messages=[{"role": "user", "content": "help"}])

# REMEDIATED — untrusted content isolated in the user role, instructions static
client.messages.create(
    system=SYSTEM_PROMPT,  # static constant
    messages=[{"role": "user", "content": f"<topic>{escape_xml(topic)}</topic>"}])

Finding message

A request-derived value flows into prompt construction reaching a model call. No boundary construct was observed on this flow. Content that reaches instruction text can override agent behavior (OWASP LLM01). Consider moving untrusted content into a delimited user-role message and keeping instruction text static. Analysis is intra-file; flows through other files are not visible.

Suppress: # stoa: ignore[AI001] reason