fix(#27): address security issues in intent classification

- Add input sanitization to prevent LLM prompt injection
  (escapes quotes, backslashes, replaces newlines)
- Add MaxLength(500) validation to DTO to prevent DoS
- Add entity validation to filter malicious LLM responses
- Add confidence validation to clamp values to 0.0-1.0
- Make LLM model configurable via INTENT_CLASSIFICATION_MODEL env var
- Add 12 new security tests (total: 72 tests, from 60)

Security fixes identified by code review:
- CVE-mitigated: Prompt injection via unescaped user input
- CVE-mitigated: Unvalidated entity data from LLM response
- CVE-mitigated: Missing input length validation

Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
2026-01-31 16:50:32 -06:00
co-authored by Claude Opus 4.5
parent fd93be6032
commit f2b25079d9
3 changed files with 412 additions and 8 deletions
@@ -1,12 +1,18 @@
import { IsString, MinLength, IsOptional, IsBoolean } from "class-validator";
import { IsString, MinLength, MaxLength, IsOptional, IsBoolean } from "class-validator";
import type { IntentType, ExtractedEntity } from "../interfaces";
/** Maximum query length to prevent DoS and excessive LLM costs */
export const MAX_QUERY_LENGTH = 500;
/**
* DTO for intent classification request
*/
export class ClassifyIntentDto {
@IsString()
@MinLength(1, { message: "query must not be empty" })
@MaxLength(MAX_QUERY_LENGTH, {
message: `query must not exceed ${String(MAX_QUERY_LENGTH)} characters`,
})
query!: string;
@IsOptional()