AI Safety
Input validation, prompt injection detection, and rate limiting — ported from mukoko-weather’s production guards. Every Mukoko app integrating Claude or Shamwari AI must use these utilities.
Install from registry
npx shadcn@latest add https://registry.mukoko.com/api/v1/ui/ai-safetyLive demonstration
Test slug validation, prompt injection detection, and rate limiting interactively.
Slug Validation
Prompt Injection Detection
Rate Limiter
Sliding window rate limiter: 5 requests per 10 seconds. Click rapidly to hit the limit.
Input Validation
API route validation
import {
validateSlug,
validatePromptLength,
sanitizeUserInput,
validateArrayLength,
validateAllowlist,
truncateMessage,
} from "@/lib/ai-safety"
// Slug validation (URL-safe identifiers)
const { valid, sanitized } = validateSlug(params.slug)
if (!valid) {
return Response.json({ error: "Invalid slug" }, { status: 400 })
}
// Message length (2000 char cap from mukoko-weather)
if (!validatePromptLength(body.message, 2000)) {
return Response.json({ error: "Message too long" }, { status: 400 })
}
// Sanitize user input (remove control chars)
const cleanInput = sanitizeUserInput(body.prompt)
// Array limits (20 items max from mukoko-weather)
if (!validateArrayLength(body.activities, 20)) {
return Response.json({ error: "Too many activities" }, { status: 400 })
}
// Tag allowlisting
const knownTags = ["farming", "mining", "travel", "tourism", "sports"]
const { valid: tagsOk, invalid, filtered } = validateAllowlist(body.tags, knownTags)
if (!tagsOk) {
log.warn("Unknown tags filtered", { data: { invalid } })
}
// Truncate chat history (2000 chars per message)
const history = messages.map(m => ({
...m,
content: truncateMessage(m.content, 2000),
})).slice(-10) // max 10 messagesPrompt Injection Detection
Heuristic detection of common prompt injection patterns. Use as one layer in defense-in-depth alongside length limits, rate limiting, and system prompt guardrails. Not a guarantee — determined attackers will find bypasses.
prompt safety check
import { detectPromptInjection } from "@/lib/ai-safety"
// Check user input before sending to Claude
const { safe, flags } = detectPromptInjection(userMessage)
if (!safe) {
logger.warn("Prompt injection attempt", {
data: { flags, inputLength: userMessage.length },
})
return Response.json(
{ error: "Your message was flagged for safety review" },
{ status: 400 }
)
}
// Detection categories:
// - system_override: "ignore previous instructions", "forget everything"
// - role_confusion: "pretend to be", "you are now a"
// - data_exfiltration: "reveal your system prompt", "repeat the text above"
// - delimiter_injection: "```system", "<system>" tagsRate Limiting
In-memory sliding window rate limiter. Production limits from mukoko-weather:
| Endpoint | Limit | Window |
|---|---|---|
/api/py/chat | 20 req | 1 hour |
/api/py/ai/followup | 30 req | 1 hour |
/api/py/explore/search | 15 req | 1 hour |
/api/py/history/analyze | 10 req | 1 hour |
/api/py/locations/add | 5 req | 1 hour |
/api/py/reports (submit) | 5 req | 1 hour |
rate limiting in API routes
import { RateLimiter } from "@/lib/ai-safety"
// Create limiters per endpoint
const chatLimiter = new RateLimiter({ maxRequests: 20, windowMs: 3600_000 })
const searchLimiter = new RateLimiter({ maxRequests: 15, windowMs: 3600_000 })
// In API route handler
export async function POST(request: Request) {
const ip = request.headers.get("x-forwarded-for") ?? "unknown"
const { allowed, remaining, resetMs } = chatLimiter.consume(ip)
if (!allowed) {
return Response.json(
{ error: "Rate limit exceeded" },
{
status: 429,
headers: {
"Retry-After": String(Math.ceil(resetMs / 1000)),
"X-RateLimit-Remaining": "0",
},
}
)
}
// Process request...
}AI integration checklist
- Validate all slugs with validateSlug() before database queries
- Cap message length to 2000 chars (validatePromptLength)
- Sanitize user input (sanitizeUserInput) — remove control characters
- Limit arrays to 20 items (validateArrayLength)
- Validate tags against allowlist (validateAllowlist)
- Check for prompt injection before sending to Claude (detectPromptInjection)
- Rate limit all AI endpoints (RateLimiter)
- Truncate chat history to 10 messages, 2000 chars each
- Use system prompt guardrails — never let user override the system prompt
Last updated on