diff --git a/python/ql/lib/semmle/python/frameworks/OpenAI.qll b/python/ql/lib/semmle/python/frameworks/OpenAI.qll index 94a7f0123a7..b56c868ba8f 100644 --- a/python/ql/lib/semmle/python/frameworks/OpenAI.qll +++ b/python/ql/lib/semmle/python/frameworks/OpenAI.qll @@ -103,6 +103,18 @@ module OpenAI { result = msg.getSubscript("content").getASubscript().getSubscript("text") } + /** Gets the `beta.threads.messages.create` call (Assistants API thread messages). */ + private API::Node threadMessageCreate() { + result = + classRef().getMember("beta").getMember("threads").getMember("messages").getMember("create") + } + + /** Holds if the `role` keyword of thread-message `call` is a privileged (assistant) role. */ + private predicate threadRoleIsAssistant(API::Node call) { + call.getKeywordParameter("role").getAValueReachingSink().asExpr().(StringLiteral).getText() = + "assistant" + } + /** * Gets role-filtered system/developer/assistant message content sinks that * MaD cannot express. @@ -111,6 +123,10 @@ module OpenAI { exists(API::Node msg | msg = [chatMessage(), responsesMessage()] and isSystemOrDevMessage(msg) | result = messageContent(msg) ) + or + exists(API::Node call | call = threadMessageCreate() and threadRoleIsAssistant(call) | + result = call.getKeywordParameter("content") + ) } /** @@ -124,6 +140,10 @@ module OpenAI { result = messageContent(msg) ) or + exists(API::Node call | call = threadMessageCreate() and not threadRoleIsAssistant(call) | + result = call.getKeywordParameter("content") + ) + or // realtime conversation items, role cannot be statically resolved in general result = classRef() diff --git a/python/ql/lib/semmle/python/frameworks/agent.model.yml b/python/ql/lib/semmle/python/frameworks/agent.model.yml index d358cf4fcba..34a4da588c4 100644 --- a/python/ql/lib/semmle/python/frameworks/agent.model.yml +++ b/python/ql/lib/semmle/python/frameworks/agent.model.yml @@ -6,6 +6,7 @@ extensions: # Agent instructions, handoff descriptions and tool descriptions are system-level prompts - ['agents', 'Member[Agent].Argument[instructions:]', 'system-prompt-injection'] - ['agents', 'Member[Agent].Argument[handoff_description:]', 'system-prompt-injection'] + - ['agents', 'Member[Agent].ReturnValue.Member[as_tool].Argument[1,tool_description:]', 'system-prompt-injection'] - ['agents', 'Member[FunctionTool].Argument[description:]', 'system-prompt-injection'] # The input passed to a run is user-level content - ['agents', 'Member[Runner].Member[run,run_sync,run_streamed].Argument[1]', 'user-prompt-injection'] diff --git a/python/ql/lib/semmle/python/frameworks/anthropic.model.yml b/python/ql/lib/semmle/python/frameworks/anthropic.model.yml index 4d9dbc794a7..eaca7a34551 100644 --- a/python/ql/lib/semmle/python/frameworks/anthropic.model.yml +++ b/python/ql/lib/semmle/python/frameworks/anthropic.model.yml @@ -10,6 +10,8 @@ extensions: - ['Anthropic', 'Member[beta].Member[messages].Member[create,stream].Argument[system:].ListElement.DictionaryElement[text]', 'system-prompt-injection'] # The managed agents `system` field is a system-level prompt - ['Anthropic', 'Member[beta].Member[agents].Member[create,update].Argument[system:]', 'system-prompt-injection'] + # The legacy Text Completions API `prompt` is user-level content + - ['Anthropic', 'Member[completions].Member[create].Argument[prompt:]', 'user-prompt-injection'] - addsTo: pack: codeql/python-all diff --git a/python/ql/lib/semmle/python/frameworks/google-genai.model.yml b/python/ql/lib/semmle/python/frameworks/google-genai.model.yml index bd5ec9862e0..bdbb7ca85aa 100644 --- a/python/ql/lib/semmle/python/frameworks/google-genai.model.yml +++ b/python/ql/lib/semmle/python/frameworks/google-genai.model.yml @@ -5,6 +5,9 @@ extensions: data: # `system_instruction` on the generation config is a system-level prompt - ['google.genai', 'Member[types].Member[GenerateContentConfig].Argument[system_instruction:]', 'system-prompt-injection'] + # Cached content carries a system instruction and user content + - ['google.genai', 'Member[types].Member[CreateCachedContentConfig].Argument[system_instruction:]', 'system-prompt-injection'] + - ['google.genai', 'Member[types].Member[CreateCachedContentConfig].Argument[contents:]', 'user-prompt-injection'] # User-level content - ['GoogleGenAI', 'Member[models].Member[generate_content,generate_content_stream].Argument[contents:]', 'user-prompt-injection'] - ['GoogleGenAI', 'Member[models].Member[generate_images,generate_videos,edit_image].Argument[prompt:]', 'user-prompt-injection'] diff --git a/python/ql/lib/semmle/python/frameworks/openai.model.yml b/python/ql/lib/semmle/python/frameworks/openai.model.yml index 40c38858896..48098e14df2 100644 --- a/python/ql/lib/semmle/python/frameworks/openai.model.yml +++ b/python/ql/lib/semmle/python/frameworks/openai.model.yml @@ -9,11 +9,15 @@ extensions: - ['OpenAI', 'Member[beta].Member[assistants].Member[update].Argument[instructions:]', 'system-prompt-injection'] - ['OpenAI', 'Member[beta].Member[threads].Member[runs].Member[create].Argument[instructions:]', 'system-prompt-injection'] - ['OpenAI', 'Member[beta].Member[threads].Member[runs].Member[create].Argument[additional_instructions:]', 'system-prompt-injection'] + # The default system instructions for a realtime session + - ['OpenAI', 'Member[beta].Member[realtime].Member[sessions].Member[create].Argument[instructions:]', 'system-prompt-injection'] # User-level prompts - ['OpenAI', 'Member[responses].Member[create].Argument[input:]', 'user-prompt-injection'] - ['OpenAI', 'Member[completions].Member[create].Argument[prompt:]', 'user-prompt-injection'] - ['OpenAI', 'Member[images].Member[generate,edit].Argument[prompt:]', 'user-prompt-injection'] - ['OpenAI', 'Member[audio].Member[transcriptions,translations].Member[create].Argument[prompt:]', 'user-prompt-injection'] + # Sora video generation prompts are user-level content + - ['OpenAI', 'Member[videos].Member[create,create_and_poll,edit,remix,extend].Argument[prompt:]', 'user-prompt-injection'] - addsTo: pack: codeql/python-all diff --git a/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/SystemPromptInjection.expected b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/SystemPromptInjection.expected index 618aa1192d6..efae5073767 100644 --- a/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/SystemPromptInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/SystemPromptInjection.expected @@ -2,7 +2,8 @@ | agent_test.py:14:21:14:63 | ControlFlowNode for BinaryExpr | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | agent_test.py:14:21:14:63 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | agent_test.py:21:22:21:63 | ControlFlowNode for BinaryExpr | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | agent_test.py:21:22:21:63 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | agent_test.py:22:29:22:53 | ControlFlowNode for BinaryExpr | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | agent_test.py:22:29:22:53 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | -| agent_test.py:31:28:31:51 | ControlFlowNode for BinaryExpr | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | agent_test.py:31:28:31:51 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | +| agent_test.py:28:26:28:50 | ControlFlowNode for BinaryExpr | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | agent_test.py:28:26:28:50 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | +| agent_test.py:37:28:37:51 | ControlFlowNode for BinaryExpr | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | agent_test.py:37:28:37:51 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | anthropic_test.py:17:16:17:37 | ControlFlowNode for BinaryExpr | anthropic_test.py:2:26:2:32 | ControlFlowNode for ImportMember | anthropic_test.py:17:16:17:37 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | anthropic_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | anthropic_test.py:21:28:21:44 | ControlFlowNode for BinaryExpr | anthropic_test.py:2:26:2:32 | ControlFlowNode for ImportMember | anthropic_test.py:21:28:21:44 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | anthropic_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | anthropic_test.py:33:16:33:37 | ControlFlowNode for BinaryExpr | anthropic_test.py:2:26:2:32 | ControlFlowNode for ImportMember | anthropic_test.py:33:16:33:37 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | anthropic_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | @@ -15,20 +16,23 @@ | openai_test.py:44:28:44:51 | ControlFlowNode for BinaryExpr | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openai_test.py:44:28:44:51 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | openai_test.py:61:28:61:51 | ControlFlowNode for BinaryExpr | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openai_test.py:61:28:61:51 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | openai_test.py:73:22:73:46 | ControlFlowNode for BinaryExpr | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openai_test.py:73:22:73:46 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | +| openai_test.py:77:22:77:46 | ControlFlowNode for BinaryExpr | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openai_test.py:77:22:77:46 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | +| openai_test.py:83:17:83:49 | ControlFlowNode for BinaryExpr | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openai_test.py:83:17:83:49 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | openrouter_test.py:18:28:18:51 | ControlFlowNode for BinaryExpr | openrouter_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openrouter_test.py:18:28:18:51 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | openrouter_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | openrouter_test.py:29:22:29:45 | ControlFlowNode for BinaryExpr | openrouter_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openrouter_test.py:29:22:29:45 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | openrouter_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | edges | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | agent_test.py:2:26:2:32 | ControlFlowNode for request | provenance | | | agent_test.py:2:26:2:32 | ControlFlowNode for request | agent_test.py:9:15:9:21 | ControlFlowNode for request | provenance | | | agent_test.py:2:26:2:32 | ControlFlowNode for request | agent_test.py:10:13:10:19 | ControlFlowNode for request | provenance | | -| agent_test.py:9:5:9:11 | ControlFlowNode for persona | agent_test.py:21:22:21:63 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:8 | -| agent_test.py:9:5:9:11 | ControlFlowNode for persona | agent_test.py:22:29:22:53 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:7 | -| agent_test.py:9:5:9:11 | ControlFlowNode for persona | agent_test.py:31:28:31:51 | ControlFlowNode for BinaryExpr | provenance | | +| agent_test.py:9:5:9:11 | ControlFlowNode for persona | agent_test.py:21:22:21:63 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:9 | +| agent_test.py:9:5:9:11 | ControlFlowNode for persona | agent_test.py:22:29:22:53 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:8 | +| agent_test.py:9:5:9:11 | ControlFlowNode for persona | agent_test.py:28:26:28:50 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:10 | +| agent_test.py:9:5:9:11 | ControlFlowNode for persona | agent_test.py:37:28:37:51 | ControlFlowNode for BinaryExpr | provenance | | | agent_test.py:9:15:9:21 | ControlFlowNode for request | agent_test.py:9:15:9:26 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | agent_test.py:9:15:9:21 | ControlFlowNode for request | agent_test.py:10:13:10:24 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | agent_test.py:9:15:9:26 | ControlFlowNode for Attribute | agent_test.py:9:15:9:41 | ControlFlowNode for Attribute() | provenance | dict.get | | agent_test.py:9:15:9:41 | ControlFlowNode for Attribute() | agent_test.py:9:5:9:11 | ControlFlowNode for persona | provenance | | -| agent_test.py:10:5:10:9 | ControlFlowNode for topic | agent_test.py:14:21:14:63 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:9 | +| agent_test.py:10:5:10:9 | ControlFlowNode for topic | agent_test.py:14:21:14:63 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:11 | | agent_test.py:10:13:10:19 | ControlFlowNode for request | agent_test.py:10:13:10:24 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | agent_test.py:10:13:10:24 | ControlFlowNode for Attribute | agent_test.py:10:13:10:37 | ControlFlowNode for Attribute() | provenance | dict.get | | agent_test.py:10:13:10:37 | ControlFlowNode for Attribute() | agent_test.py:10:5:10:9 | ControlFlowNode for topic | provenance | | @@ -45,19 +49,21 @@ edges | anthropic_test.py:11:15:11:41 | ControlFlowNode for Attribute() | anthropic_test.py:11:5:11:11 | ControlFlowNode for persona | provenance | | | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openai_test.py:2:26:2:32 | ControlFlowNode for request | provenance | | | openai_test.py:2:26:2:32 | ControlFlowNode for request | openai_test.py:12:15:12:21 | ControlFlowNode for request | provenance | | -| openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:17:22:17:46 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:5 | -| openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:22:22:22:46 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:5 | +| openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:17:22:17:46 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:6 | +| openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:22:22:22:46 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:6 | | openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:26:28:26:51 | ControlFlowNode for BinaryExpr | provenance | | | openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:44:28:44:51 | ControlFlowNode for BinaryExpr | provenance | | | openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:61:28:61:51 | ControlFlowNode for BinaryExpr | provenance | | | openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:73:22:73:46 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:4 | +| openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:77:22:77:46 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:5 | +| openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:83:17:83:49 | ControlFlowNode for BinaryExpr | provenance | | | openai_test.py:12:15:12:21 | ControlFlowNode for request | openai_test.py:12:15:12:26 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | openai_test.py:12:15:12:26 | ControlFlowNode for Attribute | openai_test.py:12:15:12:41 | ControlFlowNode for Attribute() | provenance | dict.get | | openai_test.py:12:15:12:41 | ControlFlowNode for Attribute() | openai_test.py:12:5:12:11 | ControlFlowNode for persona | provenance | | | openrouter_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openrouter_test.py:2:26:2:32 | ControlFlowNode for request | provenance | | | openrouter_test.py:2:26:2:32 | ControlFlowNode for request | openrouter_test.py:10:15:10:21 | ControlFlowNode for request | provenance | | | openrouter_test.py:10:5:10:11 | ControlFlowNode for persona | openrouter_test.py:18:28:18:51 | ControlFlowNode for BinaryExpr | provenance | | -| openrouter_test.py:10:5:10:11 | ControlFlowNode for persona | openrouter_test.py:29:22:29:45 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:6 | +| openrouter_test.py:10:5:10:11 | ControlFlowNode for persona | openrouter_test.py:29:22:29:45 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:7 | | openrouter_test.py:10:15:10:21 | ControlFlowNode for request | openrouter_test.py:10:15:10:26 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | openrouter_test.py:10:15:10:26 | ControlFlowNode for Attribute | openrouter_test.py:10:15:10:41 | ControlFlowNode for Attribute() | provenance | dict.get | | openrouter_test.py:10:15:10:41 | ControlFlowNode for Attribute() | openrouter_test.py:10:5:10:11 | ControlFlowNode for persona | provenance | | @@ -66,11 +72,13 @@ models | 2 | Sink: Anthropic; Member[beta].Member[messages].Member[create,stream].Argument[system:]; system-prompt-injection | | 3 | Sink: Anthropic; Member[messages].Member[create,stream].Argument[system:]; system-prompt-injection | | 4 | Sink: OpenAI; Member[beta].Member[assistants].Member[create].Argument[instructions:]; system-prompt-injection | -| 5 | Sink: OpenAI; Member[responses].Member[create].Argument[instructions:]; system-prompt-injection | -| 6 | Sink: OpenRouter; Member[responses].Member[send].Argument[instructions:]; system-prompt-injection | -| 7 | Sink: agents; Member[Agent].Argument[handoff_description:]; system-prompt-injection | -| 8 | Sink: agents; Member[Agent].Argument[instructions:]; system-prompt-injection | -| 9 | Sink: agents; Member[FunctionTool].Argument[description:]; system-prompt-injection | +| 5 | Sink: OpenAI; Member[beta].Member[realtime].Member[sessions].Member[create].Argument[instructions:]; system-prompt-injection | +| 6 | Sink: OpenAI; Member[responses].Member[create].Argument[instructions:]; system-prompt-injection | +| 7 | Sink: OpenRouter; Member[responses].Member[send].Argument[instructions:]; system-prompt-injection | +| 8 | Sink: agents; Member[Agent].Argument[handoff_description:]; system-prompt-injection | +| 9 | Sink: agents; Member[Agent].Argument[instructions:]; system-prompt-injection | +| 10 | Sink: agents; Member[Agent].ReturnValue.Member[as_tool].Argument[1,tool_description:]; system-prompt-injection | +| 11 | Sink: agents; Member[FunctionTool].Argument[description:]; system-prompt-injection | nodes | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | | agent_test.py:2:26:2:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | @@ -85,7 +93,8 @@ nodes | agent_test.py:14:21:14:63 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | agent_test.py:21:22:21:63 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | agent_test.py:22:29:22:53 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | -| agent_test.py:31:28:31:51 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| agent_test.py:28:26:28:50 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| agent_test.py:37:28:37:51 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | anthropic_test.py:2:26:2:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | | anthropic_test.py:2:26:2:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | anthropic_test.py:11:5:11:11 | ControlFlowNode for persona | semmle.label | ControlFlowNode for persona | @@ -110,6 +119,8 @@ nodes | openai_test.py:44:28:44:51 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | openai_test.py:61:28:61:51 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | openai_test.py:73:22:73:46 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| openai_test.py:77:22:77:46 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| openai_test.py:83:17:83:49 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | openrouter_test.py:2:26:2:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | | openrouter_test.py:2:26:2:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | openrouter_test.py:10:5:10:11 | ControlFlowNode for persona | semmle.label | ControlFlowNode for persona | @@ -123,5 +134,6 @@ testFailures | gemini_test.py:3:35:3:44 | Comment # $ Source | Missing result: Source | | gemini_test.py:21:52:21:88 | Comment # $ Alert[py/system-prompt-injection] | Missing result: Alert[py/system-prompt-injection] | | gemini_test.py:35:57:35:93 | Comment # $ Alert[py/system-prompt-injection] | Missing result: Alert[py/system-prompt-injection] | +| gemini_test.py:43:57:43:93 | Comment # $ Alert[py/system-prompt-injection] | Missing result: Alert[py/system-prompt-injection] | | langchain_test.py:3:35:3:44 | Comment # $ Source | Missing result: Source | | langchain_test.py:17:63:17:99 | Comment # $ Alert[py/system-prompt-injection] | Missing result: Alert[py/system-prompt-injection] | diff --git a/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/agent_test.py b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/agent_test.py index e3e00084a10..de4c7f3150f 100644 --- a/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/agent_test.py +++ b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/agent_test.py @@ -23,6 +23,12 @@ def get_input_agent(): tools=[tool], ) + agent_tool = agent.as_tool( + tool_name="assistant", + tool_description="Delegates to " + persona, # $ Alert[py/system-prompt-injection] + ) + print(agent_tool) + result = Runner.run_sync( agent, [ diff --git a/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/gemini_test.py b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/gemini_test.py index 58da8e5f6ad..8396df3e178 100644 --- a/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/gemini_test.py +++ b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/gemini_test.py @@ -36,3 +36,11 @@ def get_input_gemini(): ), ) print(response1) + + cache = client.caches.create( + model="gemini-2.0-flash", + config=types.CreateCachedContentConfig( + system_instruction="Talk like " + persona, # $ Alert[py/system-prompt-injection] + ), + ) + print(cache) diff --git a/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/openai_test.py b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/openai_test.py index 4f43de78d23..a6c69e642cb 100644 --- a/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/openai_test.py +++ b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/openai_test.py @@ -72,3 +72,13 @@ async def get_input_openai(): model="gpt-4.1", instructions="Talks like a " + persona # $ Alert[py/system-prompt-injection] ) + + session = client.beta.realtime.sessions.create( + instructions="Talks like a " + persona # $ Alert[py/system-prompt-injection] + ) + + message = client.beta.threads.messages.create( + thread_id="thread_123", + role="assistant", + content="Always behave like a " + persona, # $ Alert[py/system-prompt-injection] + ) diff --git a/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/UserPromptInjection.expected b/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/UserPromptInjection.expected index 298a108281e..3926153fe59 100644 --- a/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/UserPromptInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/UserPromptInjection.expected @@ -3,6 +3,7 @@ | agent_test.py:17:15:22:9 | ControlFlowNode for List | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | agent_test.py:17:15:22:9 | ControlFlowNode for List | This prompt construction depends on a $@. | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | agent_test.py:20:28:20:32 | ControlFlowNode for query | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | agent_test.py:20:28:20:32 | ControlFlowNode for query | This prompt construction depends on a $@. | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | anthropic_test.py:20:28:20:32 | ControlFlowNode for query | anthropic_test.py:2:26:2:32 | ControlFlowNode for ImportMember | anthropic_test.py:20:28:20:32 | ControlFlowNode for query | This prompt construction depends on a $@. | anthropic_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | +| anthropic_test.py:29:16:29:55 | ControlFlowNode for BinaryExpr | anthropic_test.py:2:26:2:32 | ControlFlowNode for ImportMember | anthropic_test.py:29:16:29:55 | ControlFlowNode for BinaryExpr | This prompt construction depends on a $@. | anthropic_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | langchain_test.py:21:28:21:51 | ControlFlowNode for BinaryExpr | langchain_test.py:3:26:3:32 | ControlFlowNode for ImportMember | langchain_test.py:21:28:21:51 | ControlFlowNode for BinaryExpr | This prompt construction depends on a $@. | langchain_test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | | openai_test.py:16:15:16:19 | ControlFlowNode for query | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openai_test.py:16:15:16:19 | ControlFlowNode for query | This prompt construction depends on a $@. | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | openai_test.py:20:15:29:9 | ControlFlowNode for List | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openai_test.py:20:15:29:9 | ControlFlowNode for List | This prompt construction depends on a $@. | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | @@ -11,31 +12,34 @@ | openai_test.py:44:28:44:32 | ControlFlowNode for query | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openai_test.py:44:28:44:32 | ControlFlowNode for query | This prompt construction depends on a $@. | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | openai_test.py:51:16:51:36 | ControlFlowNode for BinaryExpr | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openai_test.py:51:16:51:36 | ControlFlowNode for BinaryExpr | This prompt construction depends on a $@. | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | openai_test.py:55:16:55:38 | ControlFlowNode for BinaryExpr | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openai_test.py:55:16:55:38 | ControlFlowNode for BinaryExpr | This prompt construction depends on a $@. | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | +| openai_test.py:60:16:60:36 | ControlFlowNode for BinaryExpr | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openai_test.py:60:16:60:36 | ControlFlowNode for BinaryExpr | This prompt construction depends on a $@. | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | +| openai_test.py:66:17:66:43 | ControlFlowNode for BinaryExpr | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openai_test.py:66:17:66:43 | ControlFlowNode for BinaryExpr | This prompt construction depends on a $@. | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | openrouter_test.py:21:28:21:32 | ControlFlowNode for query | openrouter_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openrouter_test.py:21:28:21:32 | ControlFlowNode for query | This prompt construction depends on a $@. | openrouter_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | openrouter_test.py:29:15:29:19 | ControlFlowNode for query | openrouter_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openrouter_test.py:29:15:29:19 | ControlFlowNode for query | This prompt construction depends on a $@. | openrouter_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | openrouter_test.py:34:15:34:19 | ControlFlowNode for query | openrouter_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openrouter_test.py:34:15:34:19 | ControlFlowNode for query | This prompt construction depends on a $@. | openrouter_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | edges | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | agent_test.py:2:26:2:32 | ControlFlowNode for request | provenance | | | agent_test.py:2:26:2:32 | ControlFlowNode for request | agent_test.py:9:13:9:19 | ControlFlowNode for request | provenance | | -| agent_test.py:9:5:9:9 | ControlFlowNode for query | agent_test.py:13:38:13:42 | ControlFlowNode for query | provenance | Sink:MaD:7 | +| agent_test.py:9:5:9:9 | ControlFlowNode for query | agent_test.py:13:38:13:42 | ControlFlowNode for query | provenance | Sink:MaD:9 | | agent_test.py:9:5:9:9 | ControlFlowNode for query | agent_test.py:20:28:20:32 | ControlFlowNode for query | provenance | | | agent_test.py:9:5:9:9 | ControlFlowNode for query | agent_test.py:20:28:20:32 | ControlFlowNode for query | provenance | | | agent_test.py:9:13:9:19 | ControlFlowNode for request | agent_test.py:9:13:9:24 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | agent_test.py:9:13:9:24 | ControlFlowNode for Attribute | agent_test.py:9:13:9:37 | ControlFlowNode for Attribute() | provenance | dict.get | | agent_test.py:9:13:9:37 | ControlFlowNode for Attribute() | agent_test.py:9:5:9:9 | ControlFlowNode for query | provenance | | -| agent_test.py:18:13:21:13 | ControlFlowNode for Dict [Dictionary element at key content] | agent_test.py:17:15:22:9 | ControlFlowNode for List | provenance | Sink:MaD:8 Sink:MaD:8 | +| agent_test.py:18:13:21:13 | ControlFlowNode for Dict [Dictionary element at key content] | agent_test.py:17:15:22:9 | ControlFlowNode for List | provenance | Sink:MaD:10 Sink:MaD:10 | | agent_test.py:20:28:20:32 | ControlFlowNode for query | agent_test.py:18:13:21:13 | ControlFlowNode for Dict [Dictionary element at key content] | provenance | | | anthropic_test.py:2:26:2:32 | ControlFlowNode for ImportMember | anthropic_test.py:2:26:2:32 | ControlFlowNode for request | provenance | | | anthropic_test.py:2:26:2:32 | ControlFlowNode for request | anthropic_test.py:10:15:10:21 | ControlFlowNode for request | provenance | | | anthropic_test.py:2:26:2:32 | ControlFlowNode for request | anthropic_test.py:11:13:11:19 | ControlFlowNode for request | provenance | | | anthropic_test.py:10:15:10:21 | ControlFlowNode for request | anthropic_test.py:11:13:11:24 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | anthropic_test.py:11:5:11:9 | ControlFlowNode for query | anthropic_test.py:20:28:20:32 | ControlFlowNode for query | provenance | | +| anthropic_test.py:11:5:11:9 | ControlFlowNode for query | anthropic_test.py:29:16:29:55 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:1 | | anthropic_test.py:11:13:11:19 | ControlFlowNode for request | anthropic_test.py:11:13:11:24 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | anthropic_test.py:11:13:11:24 | ControlFlowNode for Attribute | anthropic_test.py:11:13:11:37 | ControlFlowNode for Attribute() | provenance | dict.get | | anthropic_test.py:11:13:11:37 | ControlFlowNode for Attribute() | anthropic_test.py:11:5:11:9 | ControlFlowNode for query | provenance | | | langchain_test.py:3:26:3:32 | ControlFlowNode for ImportMember | langchain_test.py:3:26:3:32 | ControlFlowNode for request | provenance | | | langchain_test.py:3:26:3:32 | ControlFlowNode for request | langchain_test.py:10:13:10:19 | ControlFlowNode for request | provenance | | -| langchain_test.py:10:5:10:9 | ControlFlowNode for query | langchain_test.py:21:28:21:51 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:1 | +| langchain_test.py:10:5:10:9 | ControlFlowNode for query | langchain_test.py:21:28:21:51 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:2 | | langchain_test.py:10:13:10:19 | ControlFlowNode for request | langchain_test.py:10:13:10:24 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | langchain_test.py:10:13:10:24 | ControlFlowNode for Attribute | langchain_test.py:10:13:10:37 | ControlFlowNode for Attribute() | provenance | dict.get | | langchain_test.py:10:13:10:37 | ControlFlowNode for Attribute() | langchain_test.py:10:5:10:9 | ControlFlowNode for query | provenance | | @@ -47,37 +51,41 @@ edges | openai_test.py:10:15:10:21 | ControlFlowNode for request | openai_test.py:11:13:11:24 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | openai_test.py:10:15:10:26 | ControlFlowNode for Attribute | openai_test.py:10:15:10:41 | ControlFlowNode for Attribute() | provenance | dict.get | | openai_test.py:10:15:10:41 | ControlFlowNode for Attribute() | openai_test.py:10:5:10:11 | ControlFlowNode for persona | provenance | | -| openai_test.py:11:5:11:9 | ControlFlowNode for query | openai_test.py:16:15:16:19 | ControlFlowNode for query | provenance | Sink:MaD:4 | +| openai_test.py:11:5:11:9 | ControlFlowNode for query | openai_test.py:16:15:16:19 | ControlFlowNode for query | provenance | Sink:MaD:5 | | openai_test.py:11:5:11:9 | ControlFlowNode for query | openai_test.py:27:28:27:32 | ControlFlowNode for query | provenance | | | openai_test.py:11:5:11:9 | ControlFlowNode for query | openai_test.py:27:28:27:32 | ControlFlowNode for query | provenance | | | openai_test.py:11:5:11:9 | ControlFlowNode for query | openai_test.py:40:28:40:32 | ControlFlowNode for query | provenance | | | openai_test.py:11:5:11:9 | ControlFlowNode for query | openai_test.py:44:28:44:32 | ControlFlowNode for query | provenance | | -| openai_test.py:11:5:11:9 | ControlFlowNode for query | openai_test.py:51:16:51:36 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:2 | -| openai_test.py:11:5:11:9 | ControlFlowNode for query | openai_test.py:55:16:55:38 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:3 | +| openai_test.py:11:5:11:9 | ControlFlowNode for query | openai_test.py:51:16:51:36 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:3 | +| openai_test.py:11:5:11:9 | ControlFlowNode for query | openai_test.py:55:16:55:38 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:4 | +| openai_test.py:11:5:11:9 | ControlFlowNode for query | openai_test.py:60:16:60:36 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:6 | +| openai_test.py:11:5:11:9 | ControlFlowNode for query | openai_test.py:66:17:66:43 | ControlFlowNode for BinaryExpr | provenance | | | openai_test.py:11:13:11:19 | ControlFlowNode for request | openai_test.py:11:13:11:24 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | openai_test.py:11:13:11:24 | ControlFlowNode for Attribute | openai_test.py:11:13:11:37 | ControlFlowNode for Attribute() | provenance | dict.get | | openai_test.py:11:13:11:37 | ControlFlowNode for Attribute() | openai_test.py:11:5:11:9 | ControlFlowNode for query | provenance | | -| openai_test.py:21:13:24:13 | ControlFlowNode for Dict [Dictionary element at key content] | openai_test.py:20:15:29:9 | ControlFlowNode for List | provenance | Sink:MaD:4 Sink:MaD:4 | +| openai_test.py:21:13:24:13 | ControlFlowNode for Dict [Dictionary element at key content] | openai_test.py:20:15:29:9 | ControlFlowNode for List | provenance | Sink:MaD:5 Sink:MaD:5 | | openai_test.py:23:28:23:51 | ControlFlowNode for BinaryExpr | openai_test.py:21:13:24:13 | ControlFlowNode for Dict [Dictionary element at key content] | provenance | | -| openai_test.py:25:13:28:13 | ControlFlowNode for Dict [Dictionary element at key content] | openai_test.py:20:15:29:9 | ControlFlowNode for List | provenance | Sink:MaD:4 Sink:MaD:4 | +| openai_test.py:25:13:28:13 | ControlFlowNode for Dict [Dictionary element at key content] | openai_test.py:20:15:29:9 | ControlFlowNode for List | provenance | Sink:MaD:5 Sink:MaD:5 | | openai_test.py:27:28:27:32 | ControlFlowNode for query | openai_test.py:25:13:28:13 | ControlFlowNode for Dict [Dictionary element at key content] | provenance | | | openrouter_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openrouter_test.py:2:26:2:32 | ControlFlowNode for request | provenance | | | openrouter_test.py:2:26:2:32 | ControlFlowNode for request | openrouter_test.py:10:13:10:19 | ControlFlowNode for request | provenance | | | openrouter_test.py:10:5:10:9 | ControlFlowNode for query | openrouter_test.py:21:28:21:32 | ControlFlowNode for query | provenance | | -| openrouter_test.py:10:5:10:9 | ControlFlowNode for query | openrouter_test.py:29:15:29:19 | ControlFlowNode for query | provenance | Sink:MaD:6 | -| openrouter_test.py:10:5:10:9 | ControlFlowNode for query | openrouter_test.py:34:15:34:19 | ControlFlowNode for query | provenance | Sink:MaD:5 | +| openrouter_test.py:10:5:10:9 | ControlFlowNode for query | openrouter_test.py:29:15:29:19 | ControlFlowNode for query | provenance | Sink:MaD:8 | +| openrouter_test.py:10:5:10:9 | ControlFlowNode for query | openrouter_test.py:34:15:34:19 | ControlFlowNode for query | provenance | Sink:MaD:7 | | openrouter_test.py:10:13:10:19 | ControlFlowNode for request | openrouter_test.py:10:13:10:24 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | openrouter_test.py:10:13:10:24 | ControlFlowNode for Attribute | openrouter_test.py:10:13:10:37 | ControlFlowNode for Attribute() | provenance | dict.get | | openrouter_test.py:10:13:10:37 | ControlFlowNode for Attribute() | openrouter_test.py:10:5:10:9 | ControlFlowNode for query | provenance | | models -| 1 | Sink: LangChainChatModel; Member[invoke,stream,predict,call].Argument[0]; user-prompt-injection | -| 2 | Sink: OpenAI; Member[completions].Member[create].Argument[prompt:]; user-prompt-injection | -| 3 | Sink: OpenAI; Member[images].Member[generate,edit].Argument[prompt:]; user-prompt-injection | -| 4 | Sink: OpenAI; Member[responses].Member[create].Argument[input:]; user-prompt-injection | -| 5 | Sink: OpenRouter; Member[embeddings].Member[generate].Argument[input:]; user-prompt-injection | -| 6 | Sink: OpenRouter; Member[responses].Member[send].Argument[input:]; user-prompt-injection | -| 7 | Sink: agents; Member[Runner].Member[run,run_sync,run_streamed].Argument[1]; user-prompt-injection | -| 8 | Sink: agents; Member[Runner].Member[run,run_sync,run_streamed].Argument[input:]; user-prompt-injection | +| 1 | Sink: Anthropic; Member[completions].Member[create].Argument[prompt:]; user-prompt-injection | +| 2 | Sink: LangChainChatModel; Member[invoke,stream,predict,call].Argument[0]; user-prompt-injection | +| 3 | Sink: OpenAI; Member[completions].Member[create].Argument[prompt:]; user-prompt-injection | +| 4 | Sink: OpenAI; Member[images].Member[generate,edit].Argument[prompt:]; user-prompt-injection | +| 5 | Sink: OpenAI; Member[responses].Member[create].Argument[input:]; user-prompt-injection | +| 6 | Sink: OpenAI; Member[videos].Member[create,create_and_poll,edit,remix,extend].Argument[prompt:]; user-prompt-injection | +| 7 | Sink: OpenRouter; Member[embeddings].Member[generate].Argument[input:]; user-prompt-injection | +| 8 | Sink: OpenRouter; Member[responses].Member[send].Argument[input:]; user-prompt-injection | +| 9 | Sink: agents; Member[Runner].Member[run,run_sync,run_streamed].Argument[1]; user-prompt-injection | +| 10 | Sink: agents; Member[Runner].Member[run,run_sync,run_streamed].Argument[input:]; user-prompt-injection | nodes | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | | agent_test.py:2:26:2:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | @@ -98,6 +106,7 @@ nodes | anthropic_test.py:11:13:11:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | anthropic_test.py:11:13:11:37 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | anthropic_test.py:20:28:20:32 | ControlFlowNode for query | semmle.label | ControlFlowNode for query | +| anthropic_test.py:29:16:29:55 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | langchain_test.py:3:26:3:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | | langchain_test.py:3:26:3:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | langchain_test.py:10:5:10:9 | ControlFlowNode for query | semmle.label | ControlFlowNode for query | @@ -126,6 +135,8 @@ nodes | openai_test.py:44:28:44:32 | ControlFlowNode for query | semmle.label | ControlFlowNode for query | | openai_test.py:51:16:51:36 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | openai_test.py:55:16:55:38 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| openai_test.py:60:16:60:36 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| openai_test.py:66:17:66:43 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | openrouter_test.py:2:26:2:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | | openrouter_test.py:2:26:2:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | openrouter_test.py:10:5:10:9 | ControlFlowNode for query | semmle.label | ControlFlowNode for query | @@ -138,10 +149,11 @@ nodes subpaths testFailures | agent_test.py:17:15:22:9 | ControlFlowNode for List | Unexpected result: Alert | -| gemini_test.py:2:35:2:44 | Comment # $ Source | Missing result: Source | -| gemini_test.py:14:26:14:60 | Comment # $ Alert[py/user-prompt-injection] | Missing result: Alert[py/user-prompt-injection] | -| gemini_test.py:24:40:24:74 | Comment # $ Alert[py/user-prompt-injection] | Missing result: Alert[py/user-prompt-injection] | -| gemini_test.py:32:62:32:96 | Comment # $ Alert[py/user-prompt-injection] | Missing result: Alert[py/user-prompt-injection] | -| gemini_test.py:36:24:36:58 | Comment # $ Alert[py/user-prompt-injection] | Missing result: Alert[py/user-prompt-injection] | +| gemini_test.py:3:35:3:44 | Comment # $ Source | Missing result: Source | +| gemini_test.py:15:26:15:60 | Comment # $ Alert[py/user-prompt-injection] | Missing result: Alert[py/user-prompt-injection] | +| gemini_test.py:25:40:25:74 | Comment # $ Alert[py/user-prompt-injection] | Missing result: Alert[py/user-prompt-injection] | +| gemini_test.py:33:62:33:96 | Comment # $ Alert[py/user-prompt-injection] | Missing result: Alert[py/user-prompt-injection] | +| gemini_test.py:37:24:37:58 | Comment # $ Alert[py/user-prompt-injection] | Missing result: Alert[py/user-prompt-injection] | +| gemini_test.py:43:30:43:64 | Comment # $ Alert[py/user-prompt-injection] | Missing result: Alert[py/user-prompt-injection] | | langchain_test.py:17:43:17:77 | Comment # $ Alert[py/user-prompt-injection] | Missing result: Alert[py/user-prompt-injection] | | openai_test.py:20:15:29:9 | ControlFlowNode for List | Unexpected result: Alert | diff --git a/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/anthropic_test.py b/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/anthropic_test.py index 4f1dd73bc18..00a97f7f931 100644 --- a/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/anthropic_test.py +++ b/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/anthropic_test.py @@ -22,3 +22,10 @@ def get_input_anthropic(): ], ) print(response1) + + response2 = client.completions.create( + model="claude-2.1", + max_tokens_to_sample=256, + prompt="\n\nHuman: " + query + "\n\nAssistant:", # $ Alert[py/user-prompt-injection] + ) + print(response2) diff --git a/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/gemini_test.py b/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/gemini_test.py index a59cca8337c..13a4953e17c 100644 --- a/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/gemini_test.py +++ b/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/gemini_test.py @@ -1,4 +1,5 @@ from google import genai +from google.genai import types from flask import Flask, request # $ Source app = Flask(__name__) @@ -35,4 +36,11 @@ def get_input_gemini(): model="imagen-3.0-capability-001", prompt=query, # $ Alert[py/user-prompt-injection] ) - print(response1, response2, response3, response4) + + cache = client.caches.create( + model="gemini-2.0-flash", + config=types.CreateCachedContentConfig( + contents=query, # $ Alert[py/user-prompt-injection] + ), + ) + print(response1, response2, response3, response4, cache) diff --git a/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/openai_test.py b/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/openai_test.py index f7860e788c4..97b1bc2a702 100644 --- a/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/openai_test.py +++ b/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/openai_test.py @@ -54,3 +54,14 @@ async def get_input_openai(): image = client.images.generate( prompt="A picture of " + query, # $ Alert[py/user-prompt-injection] ) + + video = client.videos.create( + model="sora-2", + prompt="A video of " + query, # $ Alert[py/user-prompt-injection] + ) + + message = client.beta.threads.messages.create( + thread_id="thread_123", + role="user", + content="Please summarize " + query, # $ Alert[py/user-prompt-injection] + )