From: maximiliancw Date: Fri, 9 Jan 2026 12:55:01 +0000 (+0100) Subject: Add text extraction utility function X-Git-Url: http://git.99rst.org/?a=commitdiff_plain;h=3ae194b71fea554068de351f3bf09a688d755119;p=sgasser-llm-shield.git Add text extraction utility function --- diff --git a/src/secrets/detect.ts b/src/secrets/detect.ts index 9089655..7a5879c 100644 --- a/src/secrets/detect.ts +++ b/src/secrets/detect.ts @@ -1,4 +1,5 @@ import type { SecretsDetectionConfig } from "../config"; +import type { ChatCompletionRequest } from "../services/llm-client"; export interface SecretsMatch { type: "OPENSSH_PRIVATE_KEY" | "PEM_PRIVATE_KEY"; @@ -17,6 +18,24 @@ export interface SecretsDetectionResult { redactions?: SecretsRedaction[]; } +/** + * Extracts all text content from an OpenAI chat completion request + * + * Concatenates content from all messages (system, user, assistant) for secrets scanning. + * The proxy validation ensures content is always a string, so we can safely access it directly. + * + * Returns concatenated text for secrets scanning. + */ +export function extractTextFromRequest(body: ChatCompletionRequest): string { + return body.messages + .map((message) => message.content) + .filter( + (content): content is string => + typeof content === "string" && content.length > 0 + ) + .join("\n"); +} + /** * Detects secret material (e.g. private keys) in text * @@ -28,16 +47,15 @@ export interface SecretsDetectionResult { */ export function detectSecrets( text: string, - config: SecretsDetectionConfig, + config: SecretsDetectionConfig ): SecretsDetectionResult { if (!config.enabled) { return { detected: false, matches: [] }; } // Apply max_scan_chars limit - const textToScan = config.max_scan_chars > 0 - ? text.slice(0, config.max_scan_chars) - : text; + const textToScan = + config.max_scan_chars > 0 ? text.slice(0, config.max_scan_chars) : text; const matches: SecretsMatch[] = []; const redactions: SecretsRedaction[] = []; @@ -47,7 +65,8 @@ export function detectSecrets( // OpenSSH private key pattern if (entitiesToDetect.has("OPENSSH_PRIVATE_KEY")) { - const opensshPattern = /-----BEGIN OPENSSH PRIVATE KEY-----[\s\S]*?-----END OPENSSH PRIVATE KEY-----/g; + const opensshPattern = + /-----BEGIN OPENSSH PRIVATE KEY-----[\s\S]*?-----END OPENSSH PRIVATE KEY-----/g; const opensshMatches = textToScan.matchAll(opensshPattern); let count = 0; for (const match of opensshMatches) { @@ -71,7 +90,8 @@ export function detectSecrets( const matchedPositions = new Set(); // RSA PRIVATE KEY - const rsaPattern = /-----BEGIN RSA PRIVATE KEY-----[\s\S]*?-----END RSA PRIVATE KEY-----/g; + const rsaPattern = + /-----BEGIN RSA PRIVATE KEY-----[\s\S]*?-----END RSA PRIVATE KEY-----/g; let rsaCount = 0; for (const match of textToScan.matchAll(rsaPattern)) { rsaCount++; @@ -86,7 +106,8 @@ export function detectSecrets( } // PRIVATE KEY (generic) - exclude RSA matches - const privateKeyPattern = /-----BEGIN PRIVATE KEY-----[\s\S]*?-----END PRIVATE KEY-----/g; + const privateKeyPattern = + /-----BEGIN PRIVATE KEY-----[\s\S]*?-----END PRIVATE KEY-----/g; let privateKeyCount = 0; for (const match of textToScan.matchAll(privateKeyPattern)) { if (match.index !== undefined && !matchedPositions.has(match.index)) { @@ -101,7 +122,8 @@ export function detectSecrets( } // ENCRYPTED PRIVATE KEY - const encryptedPattern = /-----BEGIN ENCRYPTED PRIVATE KEY-----[\s\S]*?-----END ENCRYPTED PRIVATE KEY-----/g; + const encryptedPattern = + /-----BEGIN ENCRYPTED PRIVATE KEY-----[\s\S]*?-----END ENCRYPTED PRIVATE KEY-----/g; let encryptedCount = 0; for (const match of textToScan.matchAll(encryptedPattern)) { if (match.index !== undefined && !matchedPositions.has(match.index)) {