From 72bc52b2fd17b40031df5c01efc207476716a0f2 Mon Sep 17 00:00:00 2001 From: Sotiris Dragonas <36576941+BazookaMusic@users.noreply.github.com> Date: Thu, 18 Jun 2026 16:30:29 +0300 Subject: [PATCH] Python: promote prompt injection queries from experimental to production Mirror the JavaScript layout from PR #21953: - Move SystemPromptInjection.ql / UserPromptInjection.ql to src/Security/CWE-1427 - Move customizations, query and framework libs to python/ql/lib - Move the AIPrompt concept to the production Concepts.qll - Drop the experimental tag; py/system-prompt-injection (high precision) now joins the code-scanning, security-extended and security-and-quality suites, while py/user-prompt-injection (low precision) stays out of the default suites - Move query tests to python/ql/test/query-tests/Security Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../query-suite/not_included_in_qls.expected | 3 +-- .../python-code-scanning.qls.expected | 1 + .../python-security-and-quality.qls.expected | 1 + .../python-security-extended.qls.expected | 1 + python/ql/lib/semmle/python/Concepts.qll | 25 +++++++++++++++++++ .../semmle/python/frameworks/Anthropic.qll | 0 .../semmle/python/frameworks/GoogleGenAI.qll | 0 .../semmle/python/frameworks/OpenAI.qll | 0 .../semmle/python/frameworks/OpenRouter.qll | 0 .../SystemPromptInjectionCustomizations.qll | 9 +++---- .../dataflow/SystemPromptInjectionQuery.qll | 0 .../UserPromptInjectionCustomizations.qll | 9 +++---- .../dataflow/UserPromptInjectionQuery.qll | 0 .../CWE-1427/SystemPromptInjection.qhelp | 0 .../CWE-1427/SystemPromptInjection.ql | 3 +-- .../CWE-1427/UserPromptInjection.qhelp | 0 .../Security/CWE-1427/UserPromptInjection.ql | 3 +-- .../CWE-1427/examples/prompt-injection.py | 0 .../examples/prompt-injection_fixed.py | 0 .../prompt-injection_fixed_user_role.py | 0 .../examples/tool-description-injection.py | 0 .../tool-description-injection_fixed.py | 0 .../examples/user-prompt-injection.py | 0 .../examples/user-prompt-injection_fixed.py | 0 .../2026-06-18-prompt-injection-queries.md | 2 +- .../experimental/semmle/python/Concepts.qll | 25 ------------------- .../experimental/semmle/python/Frameworks.qll | 1 - .../SystemPromptInjection.expected | 0 .../SystemPromptInjection.qlref | 2 +- .../agent_test.py | 0 .../anthropic_test.py | 0 .../gemini_test.py | 0 .../langchain_test.py | 0 .../openai_test.py | 0 .../openrouter_test.py | 0 .../UserPromptInjection.expected | 0 .../UserPromptInjection.qlref | 2 +- .../agent_test.py | 0 .../anthropic_test.py | 0 .../gemini_test.py | 0 .../langchain_test.py | 0 .../openai_test.py | 0 .../openrouter_test.py | 0 43 files changed, 42 insertions(+), 45 deletions(-) rename python/ql/{src/experimental => lib}/semmle/python/frameworks/Anthropic.qll (100%) rename python/ql/{src/experimental => lib}/semmle/python/frameworks/GoogleGenAI.qll (100%) rename python/ql/{src/experimental => lib}/semmle/python/frameworks/OpenAI.qll (100%) rename python/ql/{src/experimental => lib}/semmle/python/frameworks/OpenRouter.qll (100%) rename python/ql/{src/experimental => lib}/semmle/python/security/dataflow/SystemPromptInjectionCustomizations.qll (90%) rename python/ql/{src/experimental => lib}/semmle/python/security/dataflow/SystemPromptInjectionQuery.qll (100%) rename python/ql/{src/experimental => lib}/semmle/python/security/dataflow/UserPromptInjectionCustomizations.qll (87%) rename python/ql/{src/experimental => lib}/semmle/python/security/dataflow/UserPromptInjectionQuery.qll (100%) rename python/ql/src/{experimental => }/Security/CWE-1427/SystemPromptInjection.qhelp (100%) rename python/ql/src/{experimental => }/Security/CWE-1427/SystemPromptInjection.ql (87%) rename python/ql/src/{experimental => }/Security/CWE-1427/UserPromptInjection.qhelp (100%) rename python/ql/src/{experimental => }/Security/CWE-1427/UserPromptInjection.ql (87%) rename python/ql/src/{experimental => }/Security/CWE-1427/examples/prompt-injection.py (100%) rename python/ql/src/{experimental => }/Security/CWE-1427/examples/prompt-injection_fixed.py (100%) rename python/ql/src/{experimental => }/Security/CWE-1427/examples/prompt-injection_fixed_user_role.py (100%) rename python/ql/src/{experimental => }/Security/CWE-1427/examples/tool-description-injection.py (100%) rename python/ql/src/{experimental => }/Security/CWE-1427/examples/tool-description-injection_fixed.py (100%) rename python/ql/src/{experimental => }/Security/CWE-1427/examples/user-prompt-injection.py (100%) rename python/ql/src/{experimental => }/Security/CWE-1427/examples/user-prompt-injection_fixed.py (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-1427-SystemPromptInjection/SystemPromptInjection.expected (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-1427-SystemPromptInjection/SystemPromptInjection.qlref (60%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-1427-SystemPromptInjection/agent_test.py (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-1427-SystemPromptInjection/anthropic_test.py (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-1427-SystemPromptInjection/gemini_test.py (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-1427-SystemPromptInjection/langchain_test.py (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-1427-SystemPromptInjection/openai_test.py (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-1427-SystemPromptInjection/openrouter_test.py (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-1427-UserPromptInjection/UserPromptInjection.expected (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-1427-UserPromptInjection/UserPromptInjection.qlref (60%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-1427-UserPromptInjection/agent_test.py (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-1427-UserPromptInjection/anthropic_test.py (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-1427-UserPromptInjection/gemini_test.py (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-1427-UserPromptInjection/langchain_test.py (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-1427-UserPromptInjection/openai_test.py (100%) rename python/ql/test/{experimental => }/query-tests/Security/CWE-1427-UserPromptInjection/openrouter_test.py (100%) diff --git a/python/ql/integration-tests/query-suite/not_included_in_qls.expected b/python/ql/integration-tests/query-suite/not_included_in_qls.expected index fc0846cb16f..03d0c45c73d 100644 --- a/python/ql/integration-tests/query-suite/not_included_in_qls.expected +++ b/python/ql/integration-tests/query-suite/not_included_in_qls.expected @@ -54,6 +54,7 @@ ql/python/ql/src/Metrics/NumberOfStatements.ql ql/python/ql/src/Metrics/TransitiveImports.ql ql/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.ql ql/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql +ql/python/ql/src/Security/CWE-1427/UserPromptInjection.ql ql/python/ql/src/Security/CWE-798/HardcodedCredentials.ql ql/python/ql/src/Statements/C_StyleParentheses.ql ql/python/ql/src/Statements/DocStrings.ql @@ -87,8 +88,6 @@ ql/python/ql/src/experimental/Security/CWE-079/EmailXss.ql ql/python/ql/src/experimental/Security/CWE-091/XsltInjection.ql ql/python/ql/src/experimental/Security/CWE-094/Js2Py.ql ql/python/ql/src/experimental/Security/CWE-1236/CsvInjection.ql -ql/python/ql/src/experimental/Security/CWE-1427/SystemPromptInjection.ql -ql/python/ql/src/experimental/Security/CWE-1427/UserPromptInjection.ql ql/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidation.ql ql/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql ql/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.ql diff --git a/python/ql/integration-tests/query-suite/python-code-scanning.qls.expected b/python/ql/integration-tests/query-suite/python-code-scanning.qls.expected index 90885318d0d..1681a65a326 100644 --- a/python/ql/integration-tests/query-suite/python-code-scanning.qls.expected +++ b/python/ql/integration-tests/query-suite/python-code-scanning.qls.expected @@ -17,6 +17,7 @@ ql/python/ql/src/Security/CWE-1004/NonHttpOnlyCookie.ql ql/python/ql/src/Security/CWE-113/HeaderInjection.ql ql/python/ql/src/Security/CWE-116/BadTagFilter.ql ql/python/ql/src/Security/CWE-1275/SameSiteNoneCookie.ql +ql/python/ql/src/Security/CWE-1427/SystemPromptInjection.ql ql/python/ql/src/Security/CWE-209/StackTraceExposure.ql ql/python/ql/src/Security/CWE-215/FlaskDebug.ql ql/python/ql/src/Security/CWE-285/PamAuthorization.ql diff --git a/python/ql/integration-tests/query-suite/python-security-and-quality.qls.expected b/python/ql/integration-tests/query-suite/python-security-and-quality.qls.expected index 11b75dd0ee3..eddae9a48bd 100644 --- a/python/ql/integration-tests/query-suite/python-security-and-quality.qls.expected +++ b/python/ql/integration-tests/query-suite/python-security-and-quality.qls.expected @@ -111,6 +111,7 @@ ql/python/ql/src/Security/CWE-113/HeaderInjection.ql ql/python/ql/src/Security/CWE-116/BadTagFilter.ql ql/python/ql/src/Security/CWE-117/LogInjection.ql ql/python/ql/src/Security/CWE-1275/SameSiteNoneCookie.ql +ql/python/ql/src/Security/CWE-1427/SystemPromptInjection.ql ql/python/ql/src/Security/CWE-209/StackTraceExposure.ql ql/python/ql/src/Security/CWE-215/FlaskDebug.ql ql/python/ql/src/Security/CWE-285/PamAuthorization.ql diff --git a/python/ql/integration-tests/query-suite/python-security-extended.qls.expected b/python/ql/integration-tests/query-suite/python-security-extended.qls.expected index d677e65c3cf..b1aeef11b81 100644 --- a/python/ql/integration-tests/query-suite/python-security-extended.qls.expected +++ b/python/ql/integration-tests/query-suite/python-security-extended.qls.expected @@ -21,6 +21,7 @@ ql/python/ql/src/Security/CWE-113/HeaderInjection.ql ql/python/ql/src/Security/CWE-116/BadTagFilter.ql ql/python/ql/src/Security/CWE-117/LogInjection.ql ql/python/ql/src/Security/CWE-1275/SameSiteNoneCookie.ql +ql/python/ql/src/Security/CWE-1427/SystemPromptInjection.ql ql/python/ql/src/Security/CWE-209/StackTraceExposure.ql ql/python/ql/src/Security/CWE-215/FlaskDebug.ql ql/python/ql/src/Security/CWE-285/PamAuthorization.ql diff --git a/python/ql/lib/semmle/python/Concepts.qll b/python/ql/lib/semmle/python/Concepts.qll index 76e9f4bd13f..0ad1ef2531e 100644 --- a/python/ql/lib/semmle/python/Concepts.qll +++ b/python/ql/lib/semmle/python/Concepts.qll @@ -1794,3 +1794,28 @@ module Cryptography { import ConceptsShared::Cryptography } + +/** + * A data-flow node that prompts an AI model. + * + * Extend this class to refine existing API models. If you want to model new APIs, + * extend `AIPrompt::Range` instead. + */ +class AIPrompt extends DataFlow::Node instanceof AIPrompt::Range { + /** Gets an input that is used as AI prompt. */ + DataFlow::Node getAPrompt() { result = super.getAPrompt() } +} + +/** Provides a class for modeling new AI prompting mechanisms. */ +module AIPrompt { + /** + * A data-flow node that prompts an AI model. + * + * Extend this class to model new APIs. If you want to refine existing API models, + * extend `AIPrompt` instead. + */ + abstract class Range extends DataFlow::Node { + /** Gets an input that is used as AI prompt. */ + abstract DataFlow::Node getAPrompt(); + } +} diff --git a/python/ql/src/experimental/semmle/python/frameworks/Anthropic.qll b/python/ql/lib/semmle/python/frameworks/Anthropic.qll similarity index 100% rename from python/ql/src/experimental/semmle/python/frameworks/Anthropic.qll rename to python/ql/lib/semmle/python/frameworks/Anthropic.qll diff --git a/python/ql/src/experimental/semmle/python/frameworks/GoogleGenAI.qll b/python/ql/lib/semmle/python/frameworks/GoogleGenAI.qll similarity index 100% rename from python/ql/src/experimental/semmle/python/frameworks/GoogleGenAI.qll rename to python/ql/lib/semmle/python/frameworks/GoogleGenAI.qll diff --git a/python/ql/src/experimental/semmle/python/frameworks/OpenAI.qll b/python/ql/lib/semmle/python/frameworks/OpenAI.qll similarity index 100% rename from python/ql/src/experimental/semmle/python/frameworks/OpenAI.qll rename to python/ql/lib/semmle/python/frameworks/OpenAI.qll diff --git a/python/ql/src/experimental/semmle/python/frameworks/OpenRouter.qll b/python/ql/lib/semmle/python/frameworks/OpenRouter.qll similarity index 100% rename from python/ql/src/experimental/semmle/python/frameworks/OpenRouter.qll rename to python/ql/lib/semmle/python/frameworks/OpenRouter.qll diff --git a/python/ql/src/experimental/semmle/python/security/dataflow/SystemPromptInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/SystemPromptInjectionCustomizations.qll similarity index 90% rename from python/ql/src/experimental/semmle/python/security/dataflow/SystemPromptInjectionCustomizations.qll rename to python/ql/lib/semmle/python/security/dataflow/SystemPromptInjectionCustomizations.qll index 4d1e3e1cb38..42bfc95703b 100644 --- a/python/ql/src/experimental/semmle/python/security/dataflow/SystemPromptInjectionCustomizations.qll +++ b/python/ql/lib/semmle/python/security/dataflow/SystemPromptInjectionCustomizations.qll @@ -7,15 +7,14 @@ import python private import semmle.python.dataflow.new.DataFlow private import semmle.python.Concepts -private import experimental.semmle.python.Concepts private import semmle.python.ApiGraphs private import semmle.python.dataflow.new.RemoteFlowSources private import semmle.python.dataflow.new.BarrierGuards private import semmle.python.frameworks.data.ModelsAsData -private import experimental.semmle.python.frameworks.OpenAI -private import experimental.semmle.python.frameworks.Anthropic -private import experimental.semmle.python.frameworks.GoogleGenAI -private import experimental.semmle.python.frameworks.OpenRouter +private import semmle.python.frameworks.OpenAI +private import semmle.python.frameworks.Anthropic +private import semmle.python.frameworks.GoogleGenAI +private import semmle.python.frameworks.OpenRouter /** * Provides default sources, sinks and sanitizers for detecting diff --git a/python/ql/src/experimental/semmle/python/security/dataflow/SystemPromptInjectionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/SystemPromptInjectionQuery.qll similarity index 100% rename from python/ql/src/experimental/semmle/python/security/dataflow/SystemPromptInjectionQuery.qll rename to python/ql/lib/semmle/python/security/dataflow/SystemPromptInjectionQuery.qll diff --git a/python/ql/src/experimental/semmle/python/security/dataflow/UserPromptInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/UserPromptInjectionCustomizations.qll similarity index 87% rename from python/ql/src/experimental/semmle/python/security/dataflow/UserPromptInjectionCustomizations.qll rename to python/ql/lib/semmle/python/security/dataflow/UserPromptInjectionCustomizations.qll index 8e4f18f2234..a7ac4d030ad 100644 --- a/python/ql/src/experimental/semmle/python/security/dataflow/UserPromptInjectionCustomizations.qll +++ b/python/ql/lib/semmle/python/security/dataflow/UserPromptInjectionCustomizations.qll @@ -7,14 +7,13 @@ import python private import semmle.python.dataflow.new.DataFlow private import semmle.python.Concepts -private import experimental.semmle.python.Concepts private import semmle.python.dataflow.new.RemoteFlowSources private import semmle.python.dataflow.new.BarrierGuards private import semmle.python.frameworks.data.ModelsAsData -private import experimental.semmle.python.frameworks.OpenAI -private import experimental.semmle.python.frameworks.Anthropic -private import experimental.semmle.python.frameworks.GoogleGenAI -private import experimental.semmle.python.frameworks.OpenRouter +private import semmle.python.frameworks.OpenAI +private import semmle.python.frameworks.Anthropic +private import semmle.python.frameworks.GoogleGenAI +private import semmle.python.frameworks.OpenRouter /** * Provides default sources, sinks and sanitizers for detecting diff --git a/python/ql/src/experimental/semmle/python/security/dataflow/UserPromptInjectionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/UserPromptInjectionQuery.qll similarity index 100% rename from python/ql/src/experimental/semmle/python/security/dataflow/UserPromptInjectionQuery.qll rename to python/ql/lib/semmle/python/security/dataflow/UserPromptInjectionQuery.qll diff --git a/python/ql/src/experimental/Security/CWE-1427/SystemPromptInjection.qhelp b/python/ql/src/Security/CWE-1427/SystemPromptInjection.qhelp similarity index 100% rename from python/ql/src/experimental/Security/CWE-1427/SystemPromptInjection.qhelp rename to python/ql/src/Security/CWE-1427/SystemPromptInjection.qhelp diff --git a/python/ql/src/experimental/Security/CWE-1427/SystemPromptInjection.ql b/python/ql/src/Security/CWE-1427/SystemPromptInjection.ql similarity index 87% rename from python/ql/src/experimental/Security/CWE-1427/SystemPromptInjection.ql rename to python/ql/src/Security/CWE-1427/SystemPromptInjection.ql index 963daadd75e..2951ea5dc79 100644 --- a/python/ql/src/experimental/Security/CWE-1427/SystemPromptInjection.ql +++ b/python/ql/src/Security/CWE-1427/SystemPromptInjection.ql @@ -8,12 +8,11 @@ * @precision high * @id py/system-prompt-injection * @tags security - * experimental * external/cwe/cwe-1427 */ import python -import experimental.semmle.python.security.dataflow.SystemPromptInjectionQuery +import semmle.python.security.dataflow.SystemPromptInjectionQuery import SystemPromptInjectionFlow::PathGraph from SystemPromptInjectionFlow::PathNode source, SystemPromptInjectionFlow::PathNode sink diff --git a/python/ql/src/experimental/Security/CWE-1427/UserPromptInjection.qhelp b/python/ql/src/Security/CWE-1427/UserPromptInjection.qhelp similarity index 100% rename from python/ql/src/experimental/Security/CWE-1427/UserPromptInjection.qhelp rename to python/ql/src/Security/CWE-1427/UserPromptInjection.qhelp diff --git a/python/ql/src/experimental/Security/CWE-1427/UserPromptInjection.ql b/python/ql/src/Security/CWE-1427/UserPromptInjection.ql similarity index 87% rename from python/ql/src/experimental/Security/CWE-1427/UserPromptInjection.ql rename to python/ql/src/Security/CWE-1427/UserPromptInjection.ql index 87ad4465ad8..65f8b8dba58 100644 --- a/python/ql/src/experimental/Security/CWE-1427/UserPromptInjection.ql +++ b/python/ql/src/Security/CWE-1427/UserPromptInjection.ql @@ -8,12 +8,11 @@ * @precision low * @id py/user-prompt-injection * @tags security - * experimental * external/cwe/cwe-1427 */ import python -import experimental.semmle.python.security.dataflow.UserPromptInjectionQuery +import semmle.python.security.dataflow.UserPromptInjectionQuery import UserPromptInjectionFlow::PathGraph from UserPromptInjectionFlow::PathNode source, UserPromptInjectionFlow::PathNode sink diff --git a/python/ql/src/experimental/Security/CWE-1427/examples/prompt-injection.py b/python/ql/src/Security/CWE-1427/examples/prompt-injection.py similarity index 100% rename from python/ql/src/experimental/Security/CWE-1427/examples/prompt-injection.py rename to python/ql/src/Security/CWE-1427/examples/prompt-injection.py diff --git a/python/ql/src/experimental/Security/CWE-1427/examples/prompt-injection_fixed.py b/python/ql/src/Security/CWE-1427/examples/prompt-injection_fixed.py similarity index 100% rename from python/ql/src/experimental/Security/CWE-1427/examples/prompt-injection_fixed.py rename to python/ql/src/Security/CWE-1427/examples/prompt-injection_fixed.py diff --git a/python/ql/src/experimental/Security/CWE-1427/examples/prompt-injection_fixed_user_role.py b/python/ql/src/Security/CWE-1427/examples/prompt-injection_fixed_user_role.py similarity index 100% rename from python/ql/src/experimental/Security/CWE-1427/examples/prompt-injection_fixed_user_role.py rename to python/ql/src/Security/CWE-1427/examples/prompt-injection_fixed_user_role.py diff --git a/python/ql/src/experimental/Security/CWE-1427/examples/tool-description-injection.py b/python/ql/src/Security/CWE-1427/examples/tool-description-injection.py similarity index 100% rename from python/ql/src/experimental/Security/CWE-1427/examples/tool-description-injection.py rename to python/ql/src/Security/CWE-1427/examples/tool-description-injection.py diff --git a/python/ql/src/experimental/Security/CWE-1427/examples/tool-description-injection_fixed.py b/python/ql/src/Security/CWE-1427/examples/tool-description-injection_fixed.py similarity index 100% rename from python/ql/src/experimental/Security/CWE-1427/examples/tool-description-injection_fixed.py rename to python/ql/src/Security/CWE-1427/examples/tool-description-injection_fixed.py diff --git a/python/ql/src/experimental/Security/CWE-1427/examples/user-prompt-injection.py b/python/ql/src/Security/CWE-1427/examples/user-prompt-injection.py similarity index 100% rename from python/ql/src/experimental/Security/CWE-1427/examples/user-prompt-injection.py rename to python/ql/src/Security/CWE-1427/examples/user-prompt-injection.py diff --git a/python/ql/src/experimental/Security/CWE-1427/examples/user-prompt-injection_fixed.py b/python/ql/src/Security/CWE-1427/examples/user-prompt-injection_fixed.py similarity index 100% rename from python/ql/src/experimental/Security/CWE-1427/examples/user-prompt-injection_fixed.py rename to python/ql/src/Security/CWE-1427/examples/user-prompt-injection_fixed.py diff --git a/python/ql/src/change-notes/2026-06-18-prompt-injection-queries.md b/python/ql/src/change-notes/2026-06-18-prompt-injection-queries.md index 1c0cfe000dd..9ee0c0f062e 100644 --- a/python/ql/src/change-notes/2026-06-18-prompt-injection-queries.md +++ b/python/ql/src/change-notes/2026-06-18-prompt-injection-queries.md @@ -1,4 +1,4 @@ --- category: newQuery --- -* Replaced the experimental `py/prompt-injection` query with two new experimental queries, `py/system-prompt-injection` and `py/user-prompt-injection`, to distinguish untrusted data flowing into system-level prompts and tool descriptions from data flowing into user-role prompts. The queries model the `openai`, `agents`, `anthropic`, `google-genai`, `openrouter` and `langchain` frameworks. +* Replaced the experimental `py/prompt-injection` query with two new queries, `py/system-prompt-injection` and `py/user-prompt-injection`, to distinguish untrusted data flowing into system-level prompts and tool descriptions from data flowing into user-role prompts. The queries model the `openai`, `agents`, `anthropic`, `google-genai`, `openrouter` and `langchain` frameworks. diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll index 122490fb6d8..0e4bd6441e9 100644 --- a/python/ql/src/experimental/semmle/python/Concepts.qll +++ b/python/ql/src/experimental/semmle/python/Concepts.qll @@ -483,28 +483,3 @@ class EmailSender extends DataFlow::Node instanceof EmailSender::Range { */ DataFlow::Node getABody() { result in [super.getPlainTextBody(), super.getHtmlBody()] } } - -/** - * A data-flow node that prompts an AI model. - * - * Extend this class to refine existing API models. If you want to model new APIs, - * extend `AIPrompt::Range` instead. - */ -class AIPrompt extends DataFlow::Node instanceof AIPrompt::Range { - /** Gets an input that is used as AI prompt. */ - DataFlow::Node getAPrompt() { result = super.getAPrompt() } -} - -/** Provides a class for modeling new AI prompting mechanisms. */ -module AIPrompt { - /** - * A data-flow node that prompts an AI model. - * - * Extend this class to model new APIs. If you want to refine existing API models, - * extend `AIPrompt` instead. - */ - abstract class Range extends DataFlow::Node { - /** Gets an input that is used as AI prompt. */ - abstract DataFlow::Node getAPrompt(); - } -} diff --git a/python/ql/src/experimental/semmle/python/Frameworks.qll b/python/ql/src/experimental/semmle/python/Frameworks.qll index c4a0c7f67da..6c9972e4255 100644 --- a/python/ql/src/experimental/semmle/python/Frameworks.qll +++ b/python/ql/src/experimental/semmle/python/Frameworks.qll @@ -13,7 +13,6 @@ private import experimental.semmle.python.frameworks.Scrapli private import experimental.semmle.python.frameworks.Twisted private import experimental.semmle.python.frameworks.JWT private import experimental.semmle.python.frameworks.Csv -private import experimental.semmle.python.frameworks.OpenAI private import experimental.semmle.python.libraries.PyJWT private import experimental.semmle.python.libraries.Python_JWT private import experimental.semmle.python.libraries.Authlib diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1427-SystemPromptInjection/SystemPromptInjection.expected b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/SystemPromptInjection.expected similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-1427-SystemPromptInjection/SystemPromptInjection.expected rename to python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/SystemPromptInjection.expected diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1427-SystemPromptInjection/SystemPromptInjection.qlref b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/SystemPromptInjection.qlref similarity index 60% rename from python/ql/test/experimental/query-tests/Security/CWE-1427-SystemPromptInjection/SystemPromptInjection.qlref rename to python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/SystemPromptInjection.qlref index 5bb7e7bac97..c2eded8864c 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-1427-SystemPromptInjection/SystemPromptInjection.qlref +++ b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/SystemPromptInjection.qlref @@ -1,4 +1,4 @@ -query: experimental/Security/CWE-1427/SystemPromptInjection.ql +query: Security/CWE-1427/SystemPromptInjection.ql postprocess: - utils/test/PrettyPrintModels.ql - utils/test/InlineExpectationsTestQuery.ql diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1427-SystemPromptInjection/agent_test.py b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/agent_test.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-1427-SystemPromptInjection/agent_test.py rename to python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/agent_test.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1427-SystemPromptInjection/anthropic_test.py b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/anthropic_test.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-1427-SystemPromptInjection/anthropic_test.py rename to python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/anthropic_test.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1427-SystemPromptInjection/gemini_test.py b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/gemini_test.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-1427-SystemPromptInjection/gemini_test.py rename to python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/gemini_test.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1427-SystemPromptInjection/langchain_test.py b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/langchain_test.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-1427-SystemPromptInjection/langchain_test.py rename to python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/langchain_test.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1427-SystemPromptInjection/openai_test.py b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/openai_test.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-1427-SystemPromptInjection/openai_test.py rename to python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/openai_test.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1427-SystemPromptInjection/openrouter_test.py b/python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/openrouter_test.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-1427-SystemPromptInjection/openrouter_test.py rename to python/ql/test/query-tests/Security/CWE-1427-SystemPromptInjection/openrouter_test.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1427-UserPromptInjection/UserPromptInjection.expected b/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/UserPromptInjection.expected similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-1427-UserPromptInjection/UserPromptInjection.expected rename to python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/UserPromptInjection.expected diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1427-UserPromptInjection/UserPromptInjection.qlref b/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/UserPromptInjection.qlref similarity index 60% rename from python/ql/test/experimental/query-tests/Security/CWE-1427-UserPromptInjection/UserPromptInjection.qlref rename to python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/UserPromptInjection.qlref index 0e828598afb..4558bfb4d83 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-1427-UserPromptInjection/UserPromptInjection.qlref +++ b/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/UserPromptInjection.qlref @@ -1,4 +1,4 @@ -query: experimental/Security/CWE-1427/UserPromptInjection.ql +query: Security/CWE-1427/UserPromptInjection.ql postprocess: - utils/test/PrettyPrintModels.ql - utils/test/InlineExpectationsTestQuery.ql diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1427-UserPromptInjection/agent_test.py b/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/agent_test.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-1427-UserPromptInjection/agent_test.py rename to python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/agent_test.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1427-UserPromptInjection/anthropic_test.py b/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/anthropic_test.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-1427-UserPromptInjection/anthropic_test.py rename to python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/anthropic_test.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1427-UserPromptInjection/gemini_test.py b/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/gemini_test.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-1427-UserPromptInjection/gemini_test.py rename to python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/gemini_test.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1427-UserPromptInjection/langchain_test.py b/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/langchain_test.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-1427-UserPromptInjection/langchain_test.py rename to python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/langchain_test.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1427-UserPromptInjection/openai_test.py b/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/openai_test.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-1427-UserPromptInjection/openai_test.py rename to python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/openai_test.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1427-UserPromptInjection/openrouter_test.py b/python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/openrouter_test.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-1427-UserPromptInjection/openrouter_test.py rename to python/ql/test/query-tests/Security/CWE-1427-UserPromptInjection/openrouter_test.py