Add text extraction utility function
authormaximiliancw <redacted>
Fri, 9 Jan 2026 12:55:01 +0000 (13:55 +0100)
committermaximiliancw <redacted>
Fri, 9 Jan 2026 12:55:01 +0000 (13:55 +0100)
src/secrets/detect.ts

index 90896550fc261750f4fc748552099284d354f527..7a5879caa70b5ab2793c075c470202276f848472 100644 (file)
@@ -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<number>();
 
     // 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)) {
git clone https://git.99rst.org/PROJECT