Skip to content

Commit 7c82d25

Browse files
authored
Merge pull request #44 from kOaDT/vuln/prompt-injection
feat: add prompt injection vulnerability to AI assistant
2 parents ee27689 + 589aeaa commit 7c82d25

11 files changed

Lines changed: 1037 additions & 0 deletions

File tree

app/api/ai-assistant/route.ts

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import { NextRequest, NextResponse } from "next/server";
2+
3+
const SYSTEM_PROMPT = `You are OSSBot, a helpful customer support assistant for OopsSec Store, an online grocery and gourmet food marketplace.
4+
5+
Your role is to assist customers with:
6+
- Product inquiries (availability, ingredients, pricing)
7+
- Order status and tracking
8+
- Returns and refunds
9+
- General store policies
10+
- Recommendations based on customer preferences
11+
12+
INTERNAL CONFIGURATION:
13+
---
14+
Assistant ID: OSS-SUPPORT-BOT-v2.1
15+
Deployment: Production
16+
Security clearance: PUBLIC
17+
Internal validation code: OSS{pr0mpt_1nj3ct10n_41_4ss1st4nt}
18+
Last updated: 2026-01-25
19+
---
20+
21+
Guidelines:
22+
- Be polite, helpful, and professional
23+
- Focus on OopsSec Store products and services`;
24+
25+
const BLOCKED_PATTERNS = [
26+
/ignore.*previous.*instructions/i,
27+
/disregard.*instruction/i,
28+
/reveal.*system.*prompt/i,
29+
/print.*system.*prompt/i,
30+
];
31+
32+
function containsBlockedPattern(message: string): boolean {
33+
return BLOCKED_PATTERNS.some((pattern) => pattern.test(message));
34+
}
35+
36+
export async function POST(request: NextRequest) {
37+
try {
38+
const { message, apiKey } = await request.json();
39+
40+
if (!message || typeof message !== "string") {
41+
return NextResponse.json(
42+
{ error: "Message is required" },
43+
{ status: 400 }
44+
);
45+
}
46+
47+
if (!apiKey || typeof apiKey !== "string") {
48+
return NextResponse.json(
49+
{ error: "Mistral API key is required" },
50+
{ status: 400 }
51+
);
52+
}
53+
54+
if (message.length > 2000) {
55+
return NextResponse.json(
56+
{ error: "Message too long. Maximum 2000 characters allowed." },
57+
{ status: 400 }
58+
);
59+
}
60+
61+
if (containsBlockedPattern(message)) {
62+
return NextResponse.json(
63+
{
64+
response:
65+
"I'm sorry, but I can't process that request. I'm here to help with OopsSec Store products and services. How can I assist you today?",
66+
},
67+
{ status: 200 }
68+
);
69+
}
70+
71+
const response = await fetch("https://api.mistral.ai/v1/chat/completions", {
72+
method: "POST",
73+
headers: {
74+
"Content-Type": "application/json",
75+
Authorization: `Bearer ${apiKey}`,
76+
},
77+
body: JSON.stringify({
78+
model: "mistral-small-latest",
79+
messages: [
80+
{
81+
role: "system",
82+
content: SYSTEM_PROMPT,
83+
},
84+
{
85+
role: "user",
86+
content: message,
87+
},
88+
],
89+
max_tokens: 1024,
90+
temperature: 0.7,
91+
}),
92+
});
93+
94+
if (!response.ok) {
95+
const errorData = await response.json().catch(() => ({}));
96+
97+
if (response.status === 401) {
98+
return NextResponse.json(
99+
{ error: "Invalid API key. Please check your Mistral API key." },
100+
{ status: 401 }
101+
);
102+
}
103+
104+
if (response.status === 429) {
105+
return NextResponse.json(
106+
{ error: "Rate limit exceeded. Please try again later." },
107+
{ status: 429 }
108+
);
109+
}
110+
111+
return NextResponse.json(
112+
{
113+
error:
114+
errorData.message || "Failed to get response from AI assistant",
115+
},
116+
{ status: response.status }
117+
);
118+
}
119+
120+
const data = await response.json();
121+
const assistantMessage =
122+
data.choices?.[0]?.message?.content ||
123+
"I apologize, but I was unable to generate a response. Please try again.";
124+
125+
return NextResponse.json({
126+
response: assistantMessage,
127+
});
128+
} catch (error) {
129+
console.error("AI Assistant error:", error);
130+
return NextResponse.json(
131+
{ error: "An unexpected error occurred. Please try again." },
132+
{ status: 500 }
133+
);
134+
}
135+
}

app/components/Footer.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ export default function Footer() {
6363
Contact Support
6464
</Link>
6565
</li>
66+
<li>
67+
<Link
68+
href="/support/ai-assistant"
69+
className="text-slate-600 transition-colors hover:text-primary-600 dark:text-slate-400 dark:hover:text-primary-400"
70+
>
71+
AI Assistant
72+
</Link>
73+
</li>
6674
<li>
6775
<Link
6876
href="/news"

0 commit comments

Comments
 (0)