Skip to content

[Security] No input validation on AI prompt endpoint - prompt injection and excessive token consumption possible #244

Description

@anshul23102

Problem

The AI microservice passes user input directly to the LLM without validation or sanitization:

func handleAIRequest(w http.ResponseWriter, r *http.Request) {
    var req struct {
        Prompt string `json:"prompt"`
    }
    json.NewDecoder(r.Body).Decode(&req)
    // No length check, no injection detection:
    callLLM(req.Prompt)
}

Two risks:

  1. Token abuse: A prompt of 100,000 tokens (the max context window) costs the service hundreds of dollars per request. After paying a $0.001 micropayment, an attacker triggers a $1 LLM call.
  2. Prompt injection: System prompts or instructions can be overridden by crafted user input like "Ignore all previous instructions and..."

Proposed Fix

const (
    MaxPromptLength = 4000   // characters (~1000 tokens)
    MaxPromptTokens = 1000   // hard token budget
)

var injectionPatterns = []string{
    "ignore all previous instructions",
    "ignore your system prompt",
    "disregard all prior",
    "you are now",
    "new persona",
}

func validatePrompt(prompt string) error {
    if len(prompt) == 0 {
        return fmt.Errorf("prompt cannot be empty")
    }
    if len(prompt) > MaxPromptLength {
        return fmt.Errorf("prompt too long: max %d characters, got %d", MaxPromptLength, len(prompt))
    }
    lower := strings.ToLower(prompt)
    for _, pattern := range injectionPatterns {
        if strings.Contains(lower, pattern) {
            return fmt.Errorf("prompt contains disallowed content")
        }
    }
    return nil
}

func handleAIRequest(w http.ResponseWriter, r *http.Request) {
    var req AIRequest
    json.NewDecoder(r.Body).Decode(&req)

    if err := validatePrompt(req.Prompt); err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    callLLM(req.Prompt, MaxPromptTokens)
}

Acceptance Criteria

  • Prompts longer than 4000 characters rejected with 400 and descriptive error
  • Max token budget enforced on every LLM call (prevents runaway costs)
  • Common prompt injection phrases detected and blocked
  • Rejected prompts logged for abuse monitoring
  • Cost per request bounded and documented in README.md

Metadata

Metadata

Assignees

Labels

bugSomething isn't workinggoPull requests that update go codelevel:intermediateModerate scope requiring project familiarity or cross-file changes.triageNeeds maintainer triage.type:bugA defect or regression in existing behavior.type:securitySecurity, abuse resistance, secret safety, or payment integrity work.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions