Skip to Content
PatternsAI Safety

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-safety

Live 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 messages

Prompt 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>" tags

Rate Limiting

In-memory sliding window rate limiter. Production limits from mukoko-weather:

EndpointLimitWindow
/api/py/chat20 req1 hour
/api/py/ai/followup30 req1 hour
/api/py/explore/search15 req1 hour
/api/py/history/analyze10 req1 hour
/api/py/locations/add5 req1 hour
/api/py/reports (submit)5 req1 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