From 2eb2d623a6b60947a40359633f63639a8ff26745 Mon Sep 17 00:00:00 2001 From: Sotiris Dragonas <36576941+BazookaMusic@users.noreply.github.com> Date: Thu, 2 Jul 2026 15:59:39 +0200 Subject: [PATCH] Add proper coverage of tools --- .../semmle/python/frameworks/agent.model.yml | 2 + .../python/frameworks/anthropic.model.yml | 3 + .../python/frameworks/google-genai.model.yml | 2 + .../python/frameworks/langchain.model.yml | 6 + .../semmle/python/frameworks/openai.model.yml | 3 + .../python/frameworks/openrouter.model.yml | 6 + .../SystemPromptInjection.expected | 132 +++++++++++++----- .../agent_test.py | 6 +- .../anthropic_test.py | 15 +- .../gemini_test.py | 15 ++ .../langchain_test.py | 34 +++++ .../openai_test.py | 27 ++++ .../openrouter_test.py | 16 ++- .../UserPromptInjection.expected | 36 +++-- .../openrouter_test.py | 18 ++- 15 files changed, 269 insertions(+), 52 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/agent.model.yml b/python/ql/lib/semmle/python/frameworks/agent.model.yml index 34a4da588c4..5b7eb43669d 100644 --- a/python/ql/lib/semmle/python/frameworks/agent.model.yml +++ b/python/ql/lib/semmle/python/frameworks/agent.model.yml @@ -8,6 +8,8 @@ extensions: - ['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 `@function_tool` decorator's explicit description override is a model-facing instruction + - ['agents', 'Member[function_tool].Argument[description_override:]', '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'] - ['agents', 'Member[Runner].Member[run,run_sync,run_streamed].Argument[input:]', '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 eaca7a34551..aca404ba711 100644 --- a/python/ql/lib/semmle/python/frameworks/anthropic.model.yml +++ b/python/ql/lib/semmle/python/frameworks/anthropic.model.yml @@ -10,6 +10,9 @@ 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'] + # A tool description is a model-facing instruction + - ['Anthropic', 'Member[messages].Member[create,stream].Argument[tools:].ListElement.DictionaryElement[description]', 'system-prompt-injection'] + - ['Anthropic', 'Member[beta].Member[messages].Member[create,stream].Argument[tools:].ListElement.DictionaryElement[description]', 'system-prompt-injection'] # The legacy Text Completions API `prompt` is user-level content - ['Anthropic', 'Member[completions].Member[create].Argument[prompt:]', 'user-prompt-injection'] 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 06f43af440e..6e6ddd673e7 100644 --- a/python/ql/lib/semmle/python/frameworks/google-genai.model.yml +++ b/python/ql/lib/semmle/python/frameworks/google-genai.model.yml @@ -9,6 +9,8 @@ extensions: - ['google', 'Member[genai].Member[types].Member[LiveConnectConfig].Argument[system_instruction:]', 'system-prompt-injection'] # Cached content carries a system instruction and user content - ['google', 'Member[genai].Member[types].Member[CreateCachedContentConfig].Argument[system_instruction:]', 'system-prompt-injection'] + # A tool/function declaration description is a model-facing instruction + - ['google', 'Member[genai].Member[types].Member[FunctionDeclaration].Argument[description:]', 'system-prompt-injection'] - ['google', 'Member[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'] diff --git a/python/ql/lib/semmle/python/frameworks/langchain.model.yml b/python/ql/lib/semmle/python/frameworks/langchain.model.yml index 220fd1b75a1..4faf7e68bfb 100644 --- a/python/ql/lib/semmle/python/frameworks/langchain.model.yml +++ b/python/ql/lib/semmle/python/frameworks/langchain.model.yml @@ -27,6 +27,12 @@ extensions: - ['langchain', 'Member[agents].Member[create_agent].Argument[system_prompt:]', 'system-prompt-injection'] # The messages passed to a `create_agent` graph are user-level content. - ['LangChainAgent', 'Member[invoke,stream].Argument[0].DictionaryElement[messages].ListElement.DictionaryElement[content]', 'user-prompt-injection'] + # A tool description is a model-facing instruction. + - ['langchain_core', 'Member[tools].Member[Tool].Argument[2,description:]', 'system-prompt-injection'] + - ['langchain_core', 'Member[tools].Member[Tool].Member[from_function].Argument[2,description:]', 'system-prompt-injection'] + - ['langchain_core', 'Member[tools].Member[StructuredTool].Argument[description:]', 'system-prompt-injection'] + - ['langchain_core', 'Member[tools].Member[StructuredTool].Member[from_function].Argument[description:]', 'system-prompt-injection'] + - ['langchain_core', 'Member[tools].Member[tool].Argument[description:]', 'system-prompt-injection'] - addsTo: pack: codeql/python-all diff --git a/python/ql/lib/semmle/python/frameworks/openai.model.yml b/python/ql/lib/semmle/python/frameworks/openai.model.yml index 48098e14df2..605f06e5417 100644 --- a/python/ql/lib/semmle/python/frameworks/openai.model.yml +++ b/python/ql/lib/semmle/python/frameworks/openai.model.yml @@ -11,6 +11,9 @@ extensions: - ['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'] + # A tool/function description is a model-facing instruction + - ['OpenAI', 'Member[chat].Member[completions].Member[create].Argument[tools:].ListElement.DictionaryElement[function].DictionaryElement[description]', 'system-prompt-injection'] + - ['OpenAI', 'Member[responses].Member[create].Argument[tools:].ListElement.DictionaryElement[description]', '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'] diff --git a/python/ql/lib/semmle/python/frameworks/openrouter.model.yml b/python/ql/lib/semmle/python/frameworks/openrouter.model.yml index 894212131c9..8ed0fbecdba 100644 --- a/python/ql/lib/semmle/python/frameworks/openrouter.model.yml +++ b/python/ql/lib/semmle/python/frameworks/openrouter.model.yml @@ -6,8 +6,14 @@ extensions: # `responses.send` instructions is a system-level prompt; input is user content - ['OpenRouter', 'Member[responses].Member[send].Argument[instructions:]', 'system-prompt-injection'] - ['OpenRouter', 'Member[responses].Member[send].Argument[input:]', 'user-prompt-injection'] + # A tool/function description passed to `chat.send` is a model-facing instruction + - ['OpenRouter', 'Member[chat].Member[send].Argument[tools:].ListElement.DictionaryElement[function].DictionaryElement[description]', 'system-prompt-injection'] # Embeddings input is user-level content - ['OpenRouter', 'Member[embeddings].Member[generate].Argument[input:]', 'user-prompt-injection'] + # Image, video and speech generation prompts are user-level content + - ['OpenRouter', 'Member[images].Member[generate].Argument[prompt:]', 'user-prompt-injection'] + - ['OpenRouter', 'Member[video_generation].Member[generate].Argument[prompt:]', 'user-prompt-injection'] + - ['OpenRouter', 'Member[tts].Member[create_speech].Argument[input:]', '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 10e8525b4d3..3ed202c65ec 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 @@ -1,21 +1,29 @@ #select | 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: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 | +| agent_test.py:19:41:19:73 | ControlFlowNode for BinaryExpr | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | agent_test.py:19:41:19:73 | 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:25:22:25:63 | ControlFlowNode for BinaryExpr | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | agent_test.py:25:22:25: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:26:29:26:53 | ControlFlowNode for BinaryExpr | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | agent_test.py:26:29:26: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:32:26:32:50 | ControlFlowNode for BinaryExpr | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | agent_test.py:32:26:32: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:41:28:41:51 | ControlFlowNode for BinaryExpr | agent_test.py:2:26:2:32 | ControlFlowNode for ImportMember | agent_test.py:41:28:41: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 | | anthropic_test.py:45:16:45:37 | ControlFlowNode for BinaryExpr | anthropic_test.py:2:26:2:32 | ControlFlowNode for ImportMember | anthropic_test.py:45:16:45: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:57:16:57:37 | ControlFlowNode for BinaryExpr | anthropic_test.py:2:26:2:32 | ControlFlowNode for ImportMember | anthropic_test.py:57:16:57: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:63:16:63:37 | ControlFlowNode for BinaryExpr | anthropic_test.py:2:26:2:32 | ControlFlowNode for ImportMember | anthropic_test.py:63:16:63: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:73:32:73:53 | ControlFlowNode for BinaryExpr | anthropic_test.py:2:26:2:32 | ControlFlowNode for ImportMember | anthropic_test.py:73:32:73:53 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | anthropic_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | gemini_test.py:21:33:21:49 | ControlFlowNode for BinaryExpr | gemini_test.py:3:26:3:32 | ControlFlowNode for ImportMember | gemini_test.py:21:33:21:49 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | gemini_test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | | gemini_test.py:35:32:35:53 | ControlFlowNode for BinaryExpr | gemini_test.py:3:26:3:32 | ControlFlowNode for ImportMember | gemini_test.py:35:32:35:53 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | gemini_test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | | gemini_test.py:43:32:43:53 | ControlFlowNode for BinaryExpr | gemini_test.py:3:26:3:32 | ControlFlowNode for ImportMember | gemini_test.py:43:32:43:53 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | gemini_test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | | gemini_test.py:56:32:56:53 | ControlFlowNode for BinaryExpr | gemini_test.py:3:26:3:32 | ControlFlowNode for ImportMember | gemini_test.py:56:32:56:53 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | gemini_test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| gemini_test.py:70:29:70:50 | ControlFlowNode for BinaryExpr | gemini_test.py:3:26:3:32 | ControlFlowNode for ImportMember | gemini_test.py:70:29:70:50 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | gemini_test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | | langchain_test.py:17:35:17:58 | ControlFlowNode for BinaryExpr | langchain_test.py:3:26:3:32 | ControlFlowNode for ImportMember | langchain_test.py:17:35:17:58 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | langchain_test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | | langchain_test.py:30:43:30:66 | ControlFlowNode for BinaryExpr | langchain_test.py:3:26:3:32 | ControlFlowNode for ImportMember | langchain_test.py:30:43:30:66 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | langchain_test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| langchain_test.py:42:9:42:32 | ControlFlowNode for BinaryExpr | langchain_test.py:3:26:3:32 | ControlFlowNode for ImportMember | langchain_test.py:42:9:42:32 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | langchain_test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| langchain_test.py:48:9:48:32 | ControlFlowNode for BinaryExpr | langchain_test.py:3:26:3:32 | ControlFlowNode for ImportMember | langchain_test.py:48:9:48:32 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | langchain_test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| langchain_test.py:53:21:53:44 | ControlFlowNode for BinaryExpr | langchain_test.py:3:26:3:32 | ControlFlowNode for ImportMember | langchain_test.py:53:21:53:44 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | langchain_test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| langchain_test.py:59:21:59:44 | ControlFlowNode for BinaryExpr | langchain_test.py:3:26:3:32 | ControlFlowNode for ImportMember | langchain_test.py:59:21:59:44 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | langchain_test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| langchain_test.py:62:23:62:46 | ControlFlowNode for BinaryExpr | langchain_test.py:3:26:3:32 | ControlFlowNode for ImportMember | langchain_test.py:62:23:62:46 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | langchain_test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | | openai_test.py:17:22:17:46 | ControlFlowNode for BinaryExpr | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openai_test.py:17:22:17: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:22:22:22:46 | ControlFlowNode for BinaryExpr | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openai_test.py:22:22:22: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:26:28:26:51 | ControlFlowNode for BinaryExpr | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openai_test.py:26:28:26:51 | ControlFlowNode for BinaryExpr | This system prompt depends on a $@. | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | @@ -24,21 +32,25 @@ | 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 | +| openai_test.py:94:36:94:59 | ControlFlowNode for BinaryExpr | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openai_test.py:94:36:94:59 | 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:107:32:107:55 | ControlFlowNode for BinaryExpr | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openai_test.py:107:32:107:55 | 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 | +| openrouter_test.py:41:36:41:59 | ControlFlowNode for BinaryExpr | openrouter_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openrouter_test.py:41:36:41:59 | 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: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:5:9:11 | ControlFlowNode for persona | agent_test.py:25:22:25:63 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:13 | +| agent_test.py:9:5:9:11 | ControlFlowNode for persona | agent_test.py:26:29:26:53 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:12 | +| agent_test.py:9:5:9:11 | ControlFlowNode for persona | agent_test.py:32:26:32:50 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:14 | +| agent_test.py:9:5:9:11 | ControlFlowNode for persona | agent_test.py:41:28:41: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:11 | +| agent_test.py:10:5:10:9 | ControlFlowNode for topic | agent_test.py:14:21:14:63 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:15 | +| agent_test.py:10:5:10:9 | ControlFlowNode for topic | agent_test.py:19:41:19:73 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:16 | | 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 | | @@ -50,50 +62,68 @@ edges | anthropic_test.py:11:5:11:11 | ControlFlowNode for persona | anthropic_test.py:45:16:45:37 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:2 | | anthropic_test.py:11:5:11:11 | ControlFlowNode for persona | anthropic_test.py:57:16:57:37 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:1 | | anthropic_test.py:11:5:11:11 | ControlFlowNode for persona | anthropic_test.py:63:16:63:37 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:1 | +| anthropic_test.py:11:5:11:11 | ControlFlowNode for persona | anthropic_test.py:73:32:73:53 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:4 | | anthropic_test.py:11:15:11:21 | ControlFlowNode for request | anthropic_test.py:11:15:11:26 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | anthropic_test.py:11:15:11:26 | ControlFlowNode for Attribute | anthropic_test.py:11:15:11:41 | ControlFlowNode for Attribute() | provenance | dict.get | | anthropic_test.py:11:15:11:41 | ControlFlowNode for Attribute() | anthropic_test.py:11:5:11:11 | ControlFlowNode for persona | provenance | | | gemini_test.py:3:26:3:32 | ControlFlowNode for ImportMember | gemini_test.py:3:26:3:32 | ControlFlowNode for request | provenance | | | gemini_test.py:3:26:3:32 | ControlFlowNode for request | gemini_test.py:11:15:11:21 | ControlFlowNode for request | provenance | | | gemini_test.py:3:26:3:32 | ControlFlowNode for request | gemini_test.py:51:15:51:21 | ControlFlowNode for request | provenance | | +| gemini_test.py:3:26:3:32 | ControlFlowNode for request | gemini_test.py:64:15:64:21 | ControlFlowNode for request | provenance | | | gemini_test.py:11:5:11:11 | ControlFlowNode for persona | gemini_test.py:21:33:21:49 | ControlFlowNode for BinaryExpr | provenance | | -| gemini_test.py:11:5:11:11 | ControlFlowNode for persona | gemini_test.py:35:32:35:53 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:13 | -| gemini_test.py:11:5:11:11 | ControlFlowNode for persona | gemini_test.py:43:32:43:53 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:12 | +| gemini_test.py:11:5:11:11 | ControlFlowNode for persona | gemini_test.py:35:32:35:53 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:19 | +| gemini_test.py:11:5:11:11 | ControlFlowNode for persona | gemini_test.py:43:32:43:53 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:17 | | gemini_test.py:11:15:11:21 | ControlFlowNode for request | gemini_test.py:11:15:11:26 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | gemini_test.py:11:15:11:26 | ControlFlowNode for Attribute | gemini_test.py:11:15:11:41 | ControlFlowNode for Attribute() | provenance | dict.get | | gemini_test.py:11:15:11:41 | ControlFlowNode for Attribute() | gemini_test.py:11:5:11:11 | ControlFlowNode for persona | provenance | | -| gemini_test.py:51:5:51:11 | ControlFlowNode for persona | gemini_test.py:56:32:56:53 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:14 | +| gemini_test.py:51:5:51:11 | ControlFlowNode for persona | gemini_test.py:56:32:56:53 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:20 | | gemini_test.py:51:15:51:21 | ControlFlowNode for request | gemini_test.py:51:15:51:26 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | gemini_test.py:51:15:51:26 | ControlFlowNode for Attribute | gemini_test.py:51:15:51:41 | ControlFlowNode for Attribute() | provenance | dict.get | | gemini_test.py:51:15:51:41 | ControlFlowNode for Attribute() | gemini_test.py:51:5:51:11 | ControlFlowNode for persona | provenance | | +| gemini_test.py:64:5:64:11 | ControlFlowNode for persona | gemini_test.py:70:29:70:50 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:18 | +| gemini_test.py:64:15:64:21 | ControlFlowNode for request | gemini_test.py:64:15:64:26 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | +| gemini_test.py:64:15:64:26 | ControlFlowNode for Attribute | gemini_test.py:64:15:64:41 | ControlFlowNode for Attribute() | provenance | dict.get | +| gemini_test.py:64:15:64:41 | ControlFlowNode for Attribute() | gemini_test.py:64:5:64:11 | ControlFlowNode for persona | 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:15:10:21 | ControlFlowNode for request | provenance | | | langchain_test.py:3:26:3:32 | ControlFlowNode for request | langchain_test.py:28:15:28:21 | ControlFlowNode for request | provenance | | -| langchain_test.py:10:5:10:11 | ControlFlowNode for persona | langchain_test.py:17:35:17:58 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:16 | +| langchain_test.py:3:26:3:32 | ControlFlowNode for request | langchain_test.py:37:15:37:21 | ControlFlowNode for request | provenance | | +| langchain_test.py:10:5:10:11 | ControlFlowNode for persona | langchain_test.py:17:35:17:58 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:22 | | langchain_test.py:10:15:10:21 | ControlFlowNode for request | langchain_test.py:10:15:10:26 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | langchain_test.py:10:15:10:26 | ControlFlowNode for Attribute | langchain_test.py:10:15:10:41 | ControlFlowNode for Attribute() | provenance | dict.get | | langchain_test.py:10:15:10:41 | ControlFlowNode for Attribute() | langchain_test.py:10:5:10:11 | ControlFlowNode for persona | provenance | | -| langchain_test.py:28:5:28:11 | ControlFlowNode for persona | langchain_test.py:30:43:30:66 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:15 | +| langchain_test.py:28:5:28:11 | ControlFlowNode for persona | langchain_test.py:30:43:30:66 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:21 | | langchain_test.py:28:15:28:21 | ControlFlowNode for request | langchain_test.py:28:15:28:26 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | langchain_test.py:28:15:28:26 | ControlFlowNode for Attribute | langchain_test.py:28:15:28:41 | ControlFlowNode for Attribute() | provenance | dict.get | | langchain_test.py:28:15:28:41 | ControlFlowNode for Attribute() | langchain_test.py:28:5:28:11 | ControlFlowNode for persona | provenance | | +| langchain_test.py:37:5:37:11 | ControlFlowNode for persona | langchain_test.py:42:9:42:32 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:25 | +| langchain_test.py:37:5:37:11 | ControlFlowNode for persona | langchain_test.py:48:9:48:32 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:26 | +| langchain_test.py:37:5:37:11 | ControlFlowNode for persona | langchain_test.py:53:21:53:44 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:23 | +| langchain_test.py:37:5:37:11 | ControlFlowNode for persona | langchain_test.py:59:21:59:44 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:24 | +| langchain_test.py:37:5:37:11 | ControlFlowNode for persona | langchain_test.py:62:23:62:46 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:27 | +| langchain_test.py:37:15:37:21 | ControlFlowNode for request | langchain_test.py:37:15:37:26 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | +| langchain_test.py:37:15:37:26 | ControlFlowNode for Attribute | langchain_test.py:37:15:37:41 | ControlFlowNode for Attribute() | provenance | dict.get | +| langchain_test.py:37:15:37:41 | ControlFlowNode for Attribute() | langchain_test.py:37:5:37: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: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:17:22:17:46 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:8 | +| openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:22:22:22:46 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:8 | | 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:73:22:73:46 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:5 | +| openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:77:22:77:46 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:6 | | 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:5:12:11 | ControlFlowNode for persona | openai_test.py:94:36:94:59 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:7 | +| openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:107:32:107:55 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:9 | | 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:7 | +| openrouter_test.py:10:5:10:11 | ControlFlowNode for persona | openrouter_test.py:29:22:29:45 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:11 | +| openrouter_test.py:10:5:10:11 | ControlFlowNode for persona | openrouter_test.py:41:36:41:59 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:10 | | 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 | | @@ -101,19 +131,30 @@ models | 1 | Sink: Anthropic; Member[beta].Member[agents].Member[create,update].Argument[system:]; system-prompt-injection | | 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[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 | -| 12 | Sink: google; Member[genai].Member[types].Member[CreateCachedContentConfig].Argument[system_instruction:]; system-prompt-injection | -| 13 | Sink: google; Member[genai].Member[types].Member[GenerateContentConfig].Argument[system_instruction:]; system-prompt-injection | -| 14 | Sink: google; Member[genai].Member[types].Member[LiveConnectConfig].Argument[system_instruction:]; system-prompt-injection | -| 15 | Sink: langchain; Member[agents].Member[create_agent].Argument[system_prompt:]; system-prompt-injection | -| 16 | Sink: langchain_core; Member[messages].Member[SystemMessage].Argument[content:]; system-prompt-injection | +| 4 | Sink: Anthropic; Member[messages].Member[create,stream].Argument[tools:].ListElement.DictionaryElement[description]; system-prompt-injection | +| 5 | Sink: OpenAI; Member[beta].Member[assistants].Member[create].Argument[instructions:]; system-prompt-injection | +| 6 | Sink: OpenAI; Member[beta].Member[realtime].Member[sessions].Member[create].Argument[instructions:]; system-prompt-injection | +| 7 | Sink: OpenAI; Member[chat].Member[completions].Member[create].Argument[tools:].ListElement.DictionaryElement[function].DictionaryElement[description]; system-prompt-injection | +| 8 | Sink: OpenAI; Member[responses].Member[create].Argument[instructions:]; system-prompt-injection | +| 9 | Sink: OpenAI; Member[responses].Member[create].Argument[tools:].ListElement.DictionaryElement[description]; system-prompt-injection | +| 10 | Sink: OpenRouter; Member[chat].Member[send].Argument[tools:].ListElement.DictionaryElement[function].DictionaryElement[description]; system-prompt-injection | +| 11 | Sink: OpenRouter; Member[responses].Member[send].Argument[instructions:]; system-prompt-injection | +| 12 | Sink: agents; Member[Agent].Argument[handoff_description:]; system-prompt-injection | +| 13 | Sink: agents; Member[Agent].Argument[instructions:]; system-prompt-injection | +| 14 | Sink: agents; Member[Agent].ReturnValue.Member[as_tool].Argument[1,tool_description:]; system-prompt-injection | +| 15 | Sink: agents; Member[FunctionTool].Argument[description:]; system-prompt-injection | +| 16 | Sink: agents; Member[function_tool].Argument[description_override:]; system-prompt-injection | +| 17 | Sink: google; Member[genai].Member[types].Member[CreateCachedContentConfig].Argument[system_instruction:]; system-prompt-injection | +| 18 | Sink: google; Member[genai].Member[types].Member[FunctionDeclaration].Argument[description:]; system-prompt-injection | +| 19 | Sink: google; Member[genai].Member[types].Member[GenerateContentConfig].Argument[system_instruction:]; system-prompt-injection | +| 20 | Sink: google; Member[genai].Member[types].Member[LiveConnectConfig].Argument[system_instruction:]; system-prompt-injection | +| 21 | Sink: langchain; Member[agents].Member[create_agent].Argument[system_prompt:]; system-prompt-injection | +| 22 | Sink: langchain_core; Member[messages].Member[SystemMessage].Argument[content:]; system-prompt-injection | +| 23 | Sink: langchain_core; Member[tools].Member[StructuredTool].Argument[description:]; system-prompt-injection | +| 24 | Sink: langchain_core; Member[tools].Member[StructuredTool].Member[from_function].Argument[description:]; system-prompt-injection | +| 25 | Sink: langchain_core; Member[tools].Member[Tool].Argument[2,description:]; system-prompt-injection | +| 26 | Sink: langchain_core; Member[tools].Member[Tool].Member[from_function].Argument[2,description:]; system-prompt-injection | +| 27 | Sink: langchain_core; Member[tools].Member[tool].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 | @@ -126,10 +167,11 @@ nodes | agent_test.py:10:13:10:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | agent_test.py:10:13:10:37 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | 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: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 | +| agent_test.py:19:41:19:73 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| agent_test.py:25:22:25:63 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| agent_test.py:26:29:26:53 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| agent_test.py:32:26:32:50 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| agent_test.py:41:28:41: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 | @@ -142,6 +184,7 @@ nodes | anthropic_test.py:45:16:45:37 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | anthropic_test.py:57:16:57:37 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | anthropic_test.py:63:16:63:37 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| anthropic_test.py:73:32:73:53 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | gemini_test.py:3:26:3:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | | gemini_test.py:3:26:3:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | gemini_test.py:11:5:11:11 | ControlFlowNode for persona | semmle.label | ControlFlowNode for persona | @@ -156,6 +199,11 @@ nodes | gemini_test.py:51:15:51:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | gemini_test.py:51:15:51:41 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | gemini_test.py:56:32:56:53 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| gemini_test.py:64:5:64:11 | ControlFlowNode for persona | semmle.label | ControlFlowNode for persona | +| gemini_test.py:64:15:64:21 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| gemini_test.py:64:15:64:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| gemini_test.py:64:15:64:41 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| gemini_test.py:70:29:70:50 | 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:11 | ControlFlowNode for persona | semmle.label | ControlFlowNode for persona | @@ -168,6 +216,15 @@ nodes | langchain_test.py:28:15:28:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | langchain_test.py:28:15:28:41 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | langchain_test.py:30:43:30:66 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| langchain_test.py:37:5:37:11 | ControlFlowNode for persona | semmle.label | ControlFlowNode for persona | +| langchain_test.py:37:15:37:21 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| langchain_test.py:37:15:37:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| langchain_test.py:37:15:37:41 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| langchain_test.py:42:9:42:32 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| langchain_test.py:48:9:48:32 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| langchain_test.py:53:21:53:44 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| langchain_test.py:59:21:59:44 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| langchain_test.py:62:23:62:46 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | openai_test.py:2:26:2:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | | openai_test.py:2:26:2:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | openai_test.py:12:5:12:11 | ControlFlowNode for persona | semmle.label | ControlFlowNode for persona | @@ -182,6 +239,8 @@ nodes | 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 | +| openai_test.py:94:36:94:59 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| openai_test.py:107:32:107:55 | 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 | @@ -190,4 +249,5 @@ nodes | openrouter_test.py:10:15:10:41 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | openrouter_test.py:18:28:18:51 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | openrouter_test.py:29:22:29:45 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| openrouter_test.py:41:36:41:59 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | subpaths 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 de4c7f3150f..20846e69fc8 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 @@ -1,4 +1,4 @@ -from agents import Agent, FunctionTool, Runner +from agents import Agent, FunctionTool, Runner, function_tool from flask import Flask, request # $ Source app = Flask(__name__) @@ -16,6 +16,10 @@ def get_input_agent(): on_invoke_tool=lambda ctx, args: "...", ) + @function_tool(description_override="Look up material about " + topic) # $ Alert[py/system-prompt-injection] + def lookup(arg: str) -> str: + return "..." + agent = Agent( name="Assistant", instructions="This prompt is customized for " + persona, # $ Alert[py/system-prompt-injection] diff --git a/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/anthropic_test.py b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/anthropic_test.py index 9763e81bb0d..95eb10c158e 100644 --- a/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/anthropic_test.py +++ b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/anthropic_test.py @@ -63,4 +63,17 @@ async def get_input_anthropic(): system="Talk like " + persona, # $ Alert[py/system-prompt-injection] ) - print(response1, response2, response3) + tool_response = client.messages.create( + model="claude-sonnet-4-20250514", + max_tokens=256, + messages=[{"role": "user", "content": query}], + tools=[ + { + "name": "lookup", + "description": "Talk like " + persona, # $ Alert[py/system-prompt-injection] + "input_schema": {"type": "object", "properties": {}}, + } + ], + ) + + print(response1, response2, response3, tool_response) 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 e1c2219921b..2c991b1fe8e 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 @@ -57,3 +57,18 @@ async def get_input_gemini_live(): ), ) as session: print(session) + + +@app.route("/gemini-tool") +def get_input_gemini_tool(): + persona = request.args.get("persona") + + tool = types.Tool( + function_declarations=[ + types.FunctionDeclaration( + name="lookup", + description="Talk like " + persona, # $ Alert[py/system-prompt-injection] + ) + ] + ) + print(tool) diff --git a/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/langchain_test.py b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/langchain_test.py index baf64eb7b0b..4ab67b388ca 100644 --- a/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/langchain_test.py +++ b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/langchain_test.py @@ -28,3 +28,37 @@ def get_input_langchain_create_agent(): persona = request.args.get("persona") create_agent("gpt-4.1", system_prompt="Talk like a " + persona) # $ Alert[py/system-prompt-injection] + + +@app.route("/langchain-tool") +def get_input_langchain_tool(): + from langchain_core.tools import Tool, StructuredTool, tool + + persona = request.args.get("persona") + + Tool( + "lookup", + lambda x: x, + "Talk like a " + persona, # $ Alert[py/system-prompt-injection] + ) + + Tool.from_function( + lambda x: x, + "lookup", + "Talk like a " + persona, # $ Alert[py/system-prompt-injection] + ) + + StructuredTool( + name="lookup", + description="Talk like a " + persona, # $ Alert[py/system-prompt-injection] + ) + + StructuredTool.from_function( + lambda x: x, + name="lookup", + description="Talk like a " + persona, # $ Alert[py/system-prompt-injection] + ) + + @tool(description="Talk like a " + persona) # $ Alert[py/system-prompt-injection] + def lookup(arg: str) -> str: + return arg 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 a6c69e642cb..e2b64140f50 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 @@ -82,3 +82,30 @@ async def get_input_openai(): role="assistant", content="Always behave like a " + persona, # $ Alert[py/system-prompt-injection] ) + + chat_tool = client.chat.completions.create( + model="gpt-4.1", + messages=[{"role": "user", "content": query}], + tools=[ + { + "type": "function", + "function": { + "name": "lookup", + "description": "Talk like a " + persona, # $ Alert[py/system-prompt-injection] + }, + } + ], + ) + + responses_tool = client.responses.create( + model="gpt-4.1", + input=query, + tools=[ + { + "type": "function", + "name": "lookup", + "description": "Talk like a " + persona, # $ Alert[py/system-prompt-injection] + } + ], + ) + print(message, chat_tool, responses_tool) diff --git a/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/openrouter_test.py b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/openrouter_test.py index 335a5c9672a..6da2e7b9913 100644 --- a/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/openrouter_test.py +++ b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/openrouter_test.py @@ -29,4 +29,18 @@ def get_input_openrouter(): instructions="Talk like a " + persona, # $ Alert[py/system-prompt-injection] input=query, ) - print(completion, response) + + tool_completion = client.chat.send( + model="openai/gpt-4.1", + messages=[{"role": "user", "content": query}], + tools=[ + { + "type": "function", + "function": { + "name": "lookup", + "description": "Talk like a " + persona, # $ Alert[py/system-prompt-injection] + }, + } + ], + ) + print(completion, response, tool_completion) 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 b50b01633c4..364e19dedd4 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 @@ -34,16 +34,19 @@ | 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 | +| openrouter_test.py:39:16:39:20 | ControlFlowNode for query | openrouter_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openrouter_test.py:39:16:39:20 | 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:44:16:44:20 | ControlFlowNode for query | openrouter_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openrouter_test.py:44:16:44:20 | 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:50:15:50:19 | ControlFlowNode for query | openrouter_test.py:2:26:2:32 | ControlFlowNode for ImportMember | openrouter_test.py:50:15:50: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:17 | +| agent_test.py:9:5:9:9 | ControlFlowNode for query | agent_test.py:13:38:13:42 | ControlFlowNode for query | provenance | Sink:MaD:20 | | 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:18 Sink:MaD:18 | +| 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:21 Sink:MaD:21 | | 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 | | @@ -61,7 +64,7 @@ edges | gemini_test.py:11:5:11:9 | ControlFlowNode for query | gemini_test.py:25:33:25:37 | ControlFlowNode for query | provenance | | | gemini_test.py:11:5:11:9 | ControlFlowNode for query | gemini_test.py:33:35:33:58 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:2 | | gemini_test.py:11:5:11:9 | ControlFlowNode for query | gemini_test.py:37:16:37:20 | ControlFlowNode for query | provenance | Sink:MaD:4 | -| gemini_test.py:11:5:11:9 | ControlFlowNode for query | gemini_test.py:43:22:43:26 | ControlFlowNode for query | provenance | Sink:MaD:19 | +| gemini_test.py:11:5:11:9 | ControlFlowNode for query | gemini_test.py:43:22:43:26 | ControlFlowNode for query | provenance | Sink:MaD:22 | | gemini_test.py:11:13:11:19 | ControlFlowNode for request | gemini_test.py:11:13:11:24 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | gemini_test.py:11:13:11:24 | ControlFlowNode for Attribute | gemini_test.py:11:13:11:37 | ControlFlowNode for Attribute() | provenance | dict.get | | gemini_test.py:11:13:11:37 | ControlFlowNode for Attribute() | gemini_test.py:11:5:11:9 | ControlFlowNode for query | provenance | | @@ -76,7 +79,7 @@ edges | langchain_test.py:3:26:3:32 | ControlFlowNode for request | langchain_test.py:32:13:32:19 | ControlFlowNode for request | provenance | | | langchain_test.py:3:26:3:32 | ControlFlowNode for request | langchain_test.py:47:13:47:19 | ControlFlowNode for request | provenance | | | langchain_test.py:3:26:3:32 | ControlFlowNode for request | langchain_test.py:58:13:58:19 | ControlFlowNode for request | provenance | | -| langchain_test.py:10:5:10:9 | ControlFlowNode for query | langchain_test.py:17:34:17:38 | ControlFlowNode for query | provenance | Sink:MaD:20 | +| langchain_test.py:10:5:10:9 | ControlFlowNode for query | langchain_test.py:17:34:17:38 | ControlFlowNode for query | provenance | Sink:MaD:23 | | langchain_test.py:10:5:10:9 | ControlFlowNode for query | langchain_test.py:21:28:21:51 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:8 | | 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 | @@ -89,7 +92,7 @@ edges | langchain_test.py:32:13:32:19 | ControlFlowNode for request | langchain_test.py:32:13:32:24 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | langchain_test.py:32:13:32:24 | ControlFlowNode for Attribute | langchain_test.py:32:13:32:37 | ControlFlowNode for Attribute() | provenance | dict.get | | langchain_test.py:32:13:32:37 | ControlFlowNode for Attribute() | langchain_test.py:32:5:32:9 | ControlFlowNode for query | provenance | | -| langchain_test.py:47:5:47:9 | ControlFlowNode for query | langchain_test.py:50:30:50:34 | ControlFlowNode for query | provenance | Sink:MaD:21 | +| langchain_test.py:47:5:47:9 | ControlFlowNode for query | langchain_test.py:50:30:50:34 | ControlFlowNode for query | provenance | Sink:MaD:24 | | langchain_test.py:47:13:47:19 | ControlFlowNode for request | langchain_test.py:47:13:47:24 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep | | langchain_test.py:47:13:47:24 | ControlFlowNode for Attribute | langchain_test.py:47:13:47:37 | ControlFlowNode for Attribute() | provenance | dict.get | | langchain_test.py:47:13:47:37 | ControlFlowNode for Attribute() | langchain_test.py:47:5:47:9 | ControlFlowNode for query | provenance | | @@ -127,8 +130,11 @@ edges | 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:16 | +| openrouter_test.py:10:5:10:9 | ControlFlowNode for query | openrouter_test.py:29:15:29:19 | ControlFlowNode for query | provenance | Sink:MaD:17 | | openrouter_test.py:10:5:10:9 | ControlFlowNode for query | openrouter_test.py:34:15:34:19 | ControlFlowNode for query | provenance | Sink:MaD:15 | +| openrouter_test.py:10:5:10:9 | ControlFlowNode for query | openrouter_test.py:39:16:39:20 | ControlFlowNode for query | provenance | Sink:MaD:16 | +| openrouter_test.py:10:5:10:9 | ControlFlowNode for query | openrouter_test.py:44:16:44:20 | ControlFlowNode for query | provenance | Sink:MaD:19 | +| openrouter_test.py:10:5:10:9 | ControlFlowNode for query | openrouter_test.py:50:15:50:19 | ControlFlowNode for query | provenance | Sink:MaD:18 | | 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 | | @@ -148,12 +154,15 @@ models | 13 | Sink: OpenAI; Member[responses].Member[create].Argument[input:]; user-prompt-injection | | 14 | Sink: OpenAI; Member[videos].Member[create,create_and_poll,edit,remix,extend].Argument[prompt:]; user-prompt-injection | | 15 | Sink: OpenRouter; Member[embeddings].Member[generate].Argument[input:]; user-prompt-injection | -| 16 | Sink: OpenRouter; Member[responses].Member[send].Argument[input:]; user-prompt-injection | -| 17 | Sink: agents; Member[Runner].Member[run,run_sync,run_streamed].Argument[1]; user-prompt-injection | -| 18 | Sink: agents; Member[Runner].Member[run,run_sync,run_streamed].Argument[input:]; user-prompt-injection | -| 19 | Sink: google; Member[genai].Member[types].Member[CreateCachedContentConfig].Argument[contents:]; user-prompt-injection | -| 20 | Sink: langchain_core; Member[messages].Member[HumanMessage].Argument[content:]; user-prompt-injection | -| 21 | Sink: langchain_core; Member[prompts].Member[PromptTemplate].Instance.Member[format].Argument[any-named]; user-prompt-injection | +| 16 | Sink: OpenRouter; Member[images].Member[generate].Argument[prompt:]; user-prompt-injection | +| 17 | Sink: OpenRouter; Member[responses].Member[send].Argument[input:]; user-prompt-injection | +| 18 | Sink: OpenRouter; Member[tts].Member[create_speech].Argument[input:]; user-prompt-injection | +| 19 | Sink: OpenRouter; Member[video_generation].Member[generate].Argument[prompt:]; user-prompt-injection | +| 20 | Sink: agents; Member[Runner].Member[run,run_sync,run_streamed].Argument[1]; user-prompt-injection | +| 21 | Sink: agents; Member[Runner].Member[run,run_sync,run_streamed].Argument[input:]; user-prompt-injection | +| 22 | Sink: google; Member[genai].Member[types].Member[CreateCachedContentConfig].Argument[contents:]; user-prompt-injection | +| 23 | Sink: langchain_core; Member[messages].Member[HumanMessage].Argument[content:]; user-prompt-injection | +| 24 | Sink: langchain_core; Member[prompts].Member[PromptTemplate].Instance.Member[format].Argument[any-named]; 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 | @@ -253,6 +262,9 @@ nodes | openrouter_test.py:21:28:21:32 | ControlFlowNode for query | semmle.label | ControlFlowNode for query | | openrouter_test.py:29:15:29:19 | ControlFlowNode for query | semmle.label | ControlFlowNode for query | | openrouter_test.py:34:15:34:19 | ControlFlowNode for query | semmle.label | ControlFlowNode for query | +| openrouter_test.py:39:16:39:20 | ControlFlowNode for query | semmle.label | ControlFlowNode for query | +| openrouter_test.py:44:16:44:20 | ControlFlowNode for query | semmle.label | ControlFlowNode for query | +| openrouter_test.py:50:15:50:19 | ControlFlowNode for query | semmle.label | ControlFlowNode for query | subpaths testFailures | agent_test.py:17:15:22:9 | ControlFlowNode for List | Unexpected result: Alert | diff --git a/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/openrouter_test.py b/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/openrouter_test.py index 7f8e881a231..9f5e7797d3c 100644 --- a/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/openrouter_test.py +++ b/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/openrouter_test.py @@ -33,4 +33,20 @@ def get_input_openrouter(): model="openai/text-embedding-3-small", input=query, # $ Alert[py/user-prompt-injection] ) - print(completion, response, embedding) + + image = client.images.generate( + model="openai/dall-e-3", + prompt=query, # $ Alert[py/user-prompt-injection] + ) + + video = client.video_generation.generate( + model="openai/sora-2", + prompt=query, # $ Alert[py/user-prompt-injection] + ) + + speech = client.tts.create_speech( + model="openai/gpt-4o-mini-tts", + voice="alloy", + input=query, # $ Alert[py/user-prompt-injection] + ) + print(completion, response, embedding, image, video, speech)