From e612db2ec96fd364ce25ca932f96bd1ec26c4307 Mon Sep 17 00:00:00 2001
From: BazookaMusic
Date: Thu, 11 Jun 2026 11:28:14 +0200
Subject: [PATCH] Promote user prompt injection query to stable security
Move UserPromptInjection out of experimental into stable JavaScript security locations.
Set js/user-prompt-injection precision to low and remove experimental tagging.
Move supporting dataflow libraries, qhelp/examples, and tests to stable paths and update references.
---
.../security/dataflow}/UserPromptInjectionCustomizations.qll | 0
.../security/dataflow/UserPromptInjectionQuery.qll} | 4 ++--
.../Security/CWE-1427/UserPromptInjection.qhelp | 2 +-
.../Security/CWE-1427/UserPromptInjection.ql | 5 ++---
.../Security/CWE-1427/examples/user-prompt-injection.js | 0
.../CWE-1427/examples/user-prompt-injection_fixed.js | 0
.../UserPromptInjection/UserPromptInjection.expected | 0
.../CWE-1427/UserPromptInjection/UserPromptInjection.qlref | 1 +
.../CWE-1427/UserPromptInjection/anthropic_user_test.js | 0
.../CWE-1427/UserPromptInjection/gemini_user_test.js | 0
.../CWE-1427/UserPromptInjection/langchain_user_test.js | 0
.../CWE-1427/UserPromptInjection/openai_user_test.js | 0
.../CWE-1427/UserPromptInjection/openrouter_user_test.js | 0
.../CWE-1427/UserPromptInjection/UserPromptInjection.qlref | 1 -
14 files changed, 6 insertions(+), 7 deletions(-)
rename javascript/ql/{src/experimental/semmle/javascript/security/PromptInjection => lib/semmle/javascript/security/dataflow}/UserPromptInjectionCustomizations.qll (100%)
rename javascript/ql/{src/experimental/semmle/javascript/security/PromptInjection/UserPromptinjectionQuery.qll => lib/semmle/javascript/security/dataflow/UserPromptInjectionQuery.qll} (86%)
rename javascript/ql/src/{experimental => }/Security/CWE-1427/UserPromptInjection.qhelp (98%)
rename javascript/ql/src/{experimental => }/Security/CWE-1427/UserPromptInjection.ql (83%)
rename javascript/ql/src/{experimental => }/Security/CWE-1427/examples/user-prompt-injection.js (100%)
rename javascript/ql/src/{experimental => }/Security/CWE-1427/examples/user-prompt-injection_fixed.js (100%)
rename javascript/ql/test/{experimental => }/Security/CWE-1427/UserPromptInjection/UserPromptInjection.expected (100%)
create mode 100644 javascript/ql/test/Security/CWE-1427/UserPromptInjection/UserPromptInjection.qlref
rename javascript/ql/test/{experimental => }/Security/CWE-1427/UserPromptInjection/anthropic_user_test.js (100%)
rename javascript/ql/test/{experimental => }/Security/CWE-1427/UserPromptInjection/gemini_user_test.js (100%)
rename javascript/ql/test/{experimental => }/Security/CWE-1427/UserPromptInjection/langchain_user_test.js (100%)
rename javascript/ql/test/{experimental => }/Security/CWE-1427/UserPromptInjection/openai_user_test.js (100%)
rename javascript/ql/test/{experimental => }/Security/CWE-1427/UserPromptInjection/openrouter_user_test.js (100%)
delete mode 100644 javascript/ql/test/experimental/Security/CWE-1427/UserPromptInjection/UserPromptInjection.qlref
diff --git a/javascript/ql/src/experimental/semmle/javascript/security/PromptInjection/UserPromptInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UserPromptInjectionCustomizations.qll
similarity index 100%
rename from javascript/ql/src/experimental/semmle/javascript/security/PromptInjection/UserPromptInjectionCustomizations.qll
rename to javascript/ql/lib/semmle/javascript/security/dataflow/UserPromptInjectionCustomizations.qll
diff --git a/javascript/ql/src/experimental/semmle/javascript/security/PromptInjection/UserPromptinjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UserPromptInjectionQuery.qll
similarity index 86%
rename from javascript/ql/src/experimental/semmle/javascript/security/PromptInjection/UserPromptinjectionQuery.qll
rename to javascript/ql/lib/semmle/javascript/security/dataflow/UserPromptInjectionQuery.qll
index a363a64a15f..21c337433ee 100644
--- a/javascript/ql/src/experimental/semmle/javascript/security/PromptInjection/UserPromptinjectionQuery.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UserPromptInjectionQuery.qll
@@ -2,8 +2,8 @@
* Provides a taint-tracking configuration for detecting "prompt injection" vulnerabilities.
*
* Note, for performance reasons: only import this file if
- * `PromptInjection::Configuration` is needed, otherwise
- * `PromptInjectionCustomizations` should be imported instead.
+ * `UserPromptInjectionFlow::Configuration` is needed, otherwise
+ * `UserPromptInjectionCustomizations` should be imported instead.
*/
private import javascript
diff --git a/javascript/ql/src/experimental/Security/CWE-1427/UserPromptInjection.qhelp b/javascript/ql/src/Security/CWE-1427/UserPromptInjection.qhelp
similarity index 98%
rename from javascript/ql/src/experimental/Security/CWE-1427/UserPromptInjection.qhelp
rename to javascript/ql/src/Security/CWE-1427/UserPromptInjection.qhelp
index fadb6317c90..d1c94867142 100644
--- a/javascript/ql/src/experimental/Security/CWE-1427/UserPromptInjection.qhelp
+++ b/javascript/ql/src/Security/CWE-1427/UserPromptInjection.qhelp
@@ -20,7 +20,7 @@ context, or trigger unintended tool calls.
- Ensure that all data flowing into user-input is intended and necessary for the purpose of the AI system.
- Ensure the system prompt clearly describes the purpose, scope and boundaries of the AI system. Instruct the system to deny input that falls outside these boundaries.
-- If creating a prompt out of multiple user-controlled values, assume that each of them can be malicious. Ensure the range of possible values is restricted and validated.
+
- If creating a prompt out of multiple user-controlled values, assume that each of them can be malicious. Ensure the range of possible values is restricted and validated.
For example, if a prompt includes a question and the intended language to respond in, validate that the language is one of the supported options.
- Consider using guardrails on the input like the OpenAI guardrails library to enforce constraints and prevent malicious content from being processed.
- Apply output filtering to detect and block responses that indicate prompt injection attempts.
diff --git a/javascript/ql/src/experimental/Security/CWE-1427/UserPromptInjection.ql b/javascript/ql/src/Security/CWE-1427/UserPromptInjection.ql
similarity index 83%
rename from javascript/ql/src/experimental/Security/CWE-1427/UserPromptInjection.ql
rename to javascript/ql/src/Security/CWE-1427/UserPromptInjection.ql
index ba71fd66b90..462d6f439ea 100644
--- a/javascript/ql/src/experimental/Security/CWE-1427/UserPromptInjection.ql
+++ b/javascript/ql/src/Security/CWE-1427/UserPromptInjection.ql
@@ -5,15 +5,14 @@
* @kind path-problem
* @problem.severity warning
* @security-severity 5.0
- * @precision medium
+ * @precision low
* @id js/user-prompt-injection
* @tags security
- * experimental
* external/cwe/cwe-1427
*/
import javascript
-import experimental.semmle.javascript.security.PromptInjection.UserPromptinjectionQuery
+import semmle.javascript.security.dataflow.UserPromptInjectionQuery
import UserPromptInjectionFlow::PathGraph
from UserPromptInjectionFlow::PathNode source, UserPromptInjectionFlow::PathNode sink
diff --git a/javascript/ql/src/experimental/Security/CWE-1427/examples/user-prompt-injection.js b/javascript/ql/src/Security/CWE-1427/examples/user-prompt-injection.js
similarity index 100%
rename from javascript/ql/src/experimental/Security/CWE-1427/examples/user-prompt-injection.js
rename to javascript/ql/src/Security/CWE-1427/examples/user-prompt-injection.js
diff --git a/javascript/ql/src/experimental/Security/CWE-1427/examples/user-prompt-injection_fixed.js b/javascript/ql/src/Security/CWE-1427/examples/user-prompt-injection_fixed.js
similarity index 100%
rename from javascript/ql/src/experimental/Security/CWE-1427/examples/user-prompt-injection_fixed.js
rename to javascript/ql/src/Security/CWE-1427/examples/user-prompt-injection_fixed.js
diff --git a/javascript/ql/test/experimental/Security/CWE-1427/UserPromptInjection/UserPromptInjection.expected b/javascript/ql/test/Security/CWE-1427/UserPromptInjection/UserPromptInjection.expected
similarity index 100%
rename from javascript/ql/test/experimental/Security/CWE-1427/UserPromptInjection/UserPromptInjection.expected
rename to javascript/ql/test/Security/CWE-1427/UserPromptInjection/UserPromptInjection.expected
diff --git a/javascript/ql/test/Security/CWE-1427/UserPromptInjection/UserPromptInjection.qlref b/javascript/ql/test/Security/CWE-1427/UserPromptInjection/UserPromptInjection.qlref
new file mode 100644
index 00000000000..e9328ec91b2
--- /dev/null
+++ b/javascript/ql/test/Security/CWE-1427/UserPromptInjection/UserPromptInjection.qlref
@@ -0,0 +1 @@
+Security/CWE-1427/UserPromptInjection.ql
diff --git a/javascript/ql/test/experimental/Security/CWE-1427/UserPromptInjection/anthropic_user_test.js b/javascript/ql/test/Security/CWE-1427/UserPromptInjection/anthropic_user_test.js
similarity index 100%
rename from javascript/ql/test/experimental/Security/CWE-1427/UserPromptInjection/anthropic_user_test.js
rename to javascript/ql/test/Security/CWE-1427/UserPromptInjection/anthropic_user_test.js
diff --git a/javascript/ql/test/experimental/Security/CWE-1427/UserPromptInjection/gemini_user_test.js b/javascript/ql/test/Security/CWE-1427/UserPromptInjection/gemini_user_test.js
similarity index 100%
rename from javascript/ql/test/experimental/Security/CWE-1427/UserPromptInjection/gemini_user_test.js
rename to javascript/ql/test/Security/CWE-1427/UserPromptInjection/gemini_user_test.js
diff --git a/javascript/ql/test/experimental/Security/CWE-1427/UserPromptInjection/langchain_user_test.js b/javascript/ql/test/Security/CWE-1427/UserPromptInjection/langchain_user_test.js
similarity index 100%
rename from javascript/ql/test/experimental/Security/CWE-1427/UserPromptInjection/langchain_user_test.js
rename to javascript/ql/test/Security/CWE-1427/UserPromptInjection/langchain_user_test.js
diff --git a/javascript/ql/test/experimental/Security/CWE-1427/UserPromptInjection/openai_user_test.js b/javascript/ql/test/Security/CWE-1427/UserPromptInjection/openai_user_test.js
similarity index 100%
rename from javascript/ql/test/experimental/Security/CWE-1427/UserPromptInjection/openai_user_test.js
rename to javascript/ql/test/Security/CWE-1427/UserPromptInjection/openai_user_test.js
diff --git a/javascript/ql/test/experimental/Security/CWE-1427/UserPromptInjection/openrouter_user_test.js b/javascript/ql/test/Security/CWE-1427/UserPromptInjection/openrouter_user_test.js
similarity index 100%
rename from javascript/ql/test/experimental/Security/CWE-1427/UserPromptInjection/openrouter_user_test.js
rename to javascript/ql/test/Security/CWE-1427/UserPromptInjection/openrouter_user_test.js
diff --git a/javascript/ql/test/experimental/Security/CWE-1427/UserPromptInjection/UserPromptInjection.qlref b/javascript/ql/test/experimental/Security/CWE-1427/UserPromptInjection/UserPromptInjection.qlref
deleted file mode 100644
index 2e39df2df57..00000000000
--- a/javascript/ql/test/experimental/Security/CWE-1427/UserPromptInjection/UserPromptInjection.qlref
+++ /dev/null
@@ -1 +0,0 @@
-experimental/Security/CWE-1427/UserPromptInjection.ql