Skip to content

Commit c444f41

Browse files
committed
1. Enable inline expectations for tests
2. Add annotations for sources 2. Fix a modelling issue in the openai library - missing coverage for a legacy method when moving to MaDs and a mistake in the assistants.create models
1 parent b9025a5 commit c444f41

16 files changed

Lines changed: 157 additions & 171 deletions

javascript/ql/lib/ext/openai.model.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ extensions:
1212
extensible: sinkModel
1313
data:
1414
- ["openai.Client", "Member[responses].Member[create].Argument[0].Member[instructions]", "system-prompt-injection"]
15-
- ["openai.Client", "Member[beta].Member[assistants].Member[create,update].Argument[0].Member[instructions]", "system-prompt-injection"]
15+
- ["openai.Client", "Member[completions].Member[create].Argument[0].Member[prompt]", "system-prompt-injection"]
16+
- ["openai.Client", "Member[beta].Member[assistants].Member[create].Argument[0].Member[instructions]", "system-prompt-injection"]
17+
- ["openai.Client", "Member[beta].Member[assistants].Member[update].Argument[1].Member[instructions]", "system-prompt-injection"]
1618
- ["openai.Client", "Member[beta].Member[threads].Member[runs].Member[create].Argument[1].Member[instructions,additional_instructions]", "system-prompt-injection"]
1719
- ["@openai/agents", "Member[Agent].Argument[0].Member[instructions,handoffDescription]", "system-prompt-injection"]
1820
- ["@openai/guardrails", "Member[Agent].Argument[0].Member[instructions,handoffDescription]", "system-prompt-injection"]

javascript/ql/test/Security/CWE-1427/SystemPromptInjection/SystemPromptInjection.expected

Lines changed: 79 additions & 69 deletions
Large diffs are not rendered by default.
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
Security/CWE-1427/SystemPromptInjection.ql
1+
query: Security/CWE-1427/SystemPromptInjection.ql
2+
postprocess: utils/test/InlineExpectationsTestQuery.ql

javascript/ql/test/Security/CWE-1427/SystemPromptInjection/agents_test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const { z } = require("zod");
55
const app = express();
66

77
app.get("/agents", async (req, res) => {
8-
const persona = req.query.persona;
8+
const persona = req.query.persona; // $ Source
99
const query = req.query.query;
1010

1111
// === Agent constructor: instructions as string ===
@@ -30,8 +30,8 @@ app.get("/agents", async (req, res) => {
3030
const agent3 = new Agent({
3131
name: "AsyncDynamic",
3232
instructions: async (runContext) => {
33-
return "Talk like a " + persona; // $ Alert[js/system-prompt-injection]
34-
},
33+
return "Talk like a " + persona;
34+
}, // $ Alert[js/system-prompt-injection]
3535
});
3636

3737
// === Agent constructor: handoffDescription ===

javascript/ql/test/Security/CWE-1427/SystemPromptInjection/anthropic_test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const app = express();
55
const client = new Anthropic();
66

77
app.get("/test", async (req, res) => {
8-
const persona = req.query.persona;
8+
const persona = req.query.persona; // $ Source
99
const query = req.query.query;
1010

1111
// === messages.create: system as string ===
@@ -138,14 +138,14 @@ app.get("/test", async (req, res) => {
138138
// SHOULD ALERT — tainted data goes into system role; barrier on user role
139139
// must not suppress the system-role taint path.
140140
const messages2 = [
141-
{ role: "system", content: "Talk like a " + persona }, // $ Alert[js/system-prompt-injection]
141+
{ role: "system", content: "Talk like a " + persona },
142142
{ role: "user", content: query },
143143
];
144144
const systemMsg2 = messages2.find((m) => m.role === "system");
145145
const m7 = await client.messages.create({
146146
model: "claude-sonnet-4-20250514",
147147
max_tokens: 1024,
148-
system: systemMsg2.content,
148+
system: systemMsg2.content, // $ Alert[js/system-prompt-injection]
149149
messages: [{ role: "user", content: query }],
150150
});
151151

javascript/ql/test/Security/CWE-1427/SystemPromptInjection/gemini_test.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const app = express();
55
const ai = new GoogleGenAI({ apiKey: "test-key" });
66

77
app.get("/test", async (req, res) => {
8-
const persona = req.query.persona;
8+
const persona = req.query.persona; // $ Source
99
const query = req.query.query;
1010

1111
// === generateContent: systemInstruction ===
@@ -62,18 +62,18 @@ app.get("/test", async (req, res) => {
6262

6363
// === generateImages: prompt ===
6464

65-
// SHOULD ALERT
65+
// SHOULD NOT ALERT - image prompt is a user-prompt-injection sink, not system
6666
const g5 = await ai.models.generateImages({
6767
model: "imagen-3.0-generate-002",
68-
prompt: "Draw a picture of " + persona, // $ Alert[js/system-prompt-injection]
68+
prompt: "Draw a picture of " + persona,
6969
});
7070

7171
// === editImage: prompt ===
7272

73-
// SHOULD ALERT
73+
// SHOULD NOT ALERT - image prompt is a user-prompt-injection sink, not system
7474
const g6 = await ai.models.editImage({
7575
model: "imagen-3.0-capability-001",
76-
prompt: "Edit to look like " + persona, // $ Alert[js/system-prompt-injection]
76+
prompt: "Edit to look like " + persona,
7777
});
7878

7979
// === chats.create: systemInstruction ===
@@ -105,7 +105,7 @@ app.get("/test", async (req, res) => {
105105
systemInstruction: "Talk like a " + persona, // $ Alert[js/system-prompt-injection]
106106
},
107107
callbacks: {
108-
onmessage: (msg) => {},
108+
onmessage: (msg) => { },
109109
},
110110
});
111111

javascript/ql/test/Security/CWE-1427/SystemPromptInjection/langchain_test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const { createAgent } = require("langchain");
66
const app = express();
77

88
app.get("/test", async (req, res) => {
9-
const persona = req.query.persona;
9+
const persona = req.query.persona; // $ Source
1010
const query = req.query.query;
1111

1212
const chatModel = new ChatOpenAI({ model: "gpt-4" });

javascript/ql/test/Security/CWE-1427/SystemPromptInjection/openai_test.js

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const client = new OpenAI();
88
const azureClient = new AzureOpenAI();
99

1010
app.get("/test", async (req, res) => {
11-
const persona = req.query.persona;
11+
const persona = req.query.persona; // $ Source
1212
const query = req.query.query;
1313

1414
// === OpenAI Responses API ===
@@ -120,18 +120,6 @@ app.get("/test", async (req, res) => {
120120
prompt: "Talk like a " + persona, // $ Alert[js/system-prompt-injection]
121121
});
122122

123-
// === Images API ===
124-
125-
// images.generate (SHOULD ALERT)
126-
const i1 = await client.images.generate({
127-
prompt: "Draw a picture of " + persona, // $ Alert[js/system-prompt-injection]
128-
});
129-
130-
// images.edit (SHOULD ALERT)
131-
const i2 = await client.images.edit({
132-
prompt: "Edit to look like " + persona, // $ Alert[js/system-prompt-injection]
133-
});
134-
135123
// === Assistants API (beta) ===
136124

137125
// assistants.create (SHOULD ALERT)
@@ -170,22 +158,6 @@ app.get("/test", async (req, res) => {
170158
content: query, // OK - user role
171159
});
172160

173-
// === Audio API ===
174-
175-
// audio.transcriptions.create (SHOULD ALERT)
176-
const at1 = await client.audio.transcriptions.create({
177-
file: "audio.mp3",
178-
model: "whisper-1",
179-
prompt: "Transcribe about " + persona, // $ Alert[js/system-prompt-injection]
180-
});
181-
182-
// audio.translations.create (SHOULD ALERT)
183-
const atl1 = await client.audio.translations.create({
184-
file: "audio.mp3",
185-
model: "whisper-1",
186-
prompt: "Translate about " + persona, // $ Alert[js/system-prompt-injection]
187-
});
188-
189161
// === Object assigned to variable first ===
190162

191163
// Should still be caught via data flow

javascript/ql/test/Security/CWE-1427/SystemPromptInjection/openrouter_test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const client = new OpenRouter();
99
const namedClient = new OpenRouterNamed();
1010

1111
app.get("/test", async (req, res) => {
12-
const persona = req.query.persona;
12+
const persona = req.query.persona; // $ Source
1313
const query = req.query.query;
1414

1515
// === OpenRouter Client SDK: chat.send ===
@@ -124,7 +124,7 @@ app.get("/test", async (req, res) => {
124124
name: "lookup",
125125
description: "Talk like a " + persona, // $ Alert[js/system-prompt-injection]
126126
inputSchema: {},
127-
execute: async () => {},
127+
execute: async () => { },
128128
});
129129

130130
// input array with user role (SHOULD NOT ALERT)

0 commit comments

Comments
 (0)