From 7bd28e0216ce7dc90a209a4c59b88d7af408b070 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Mon, 18 Nov 2024 05:01:20 +0000 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=F0=9F=94=92=20add=20secret=20hidin?= =?UTF-8?q?g=20in=20user=20inputs=20and=20logs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/chat.ts | 11 +++---- packages/core/src/secrets.ts | 58 ++++++++++++++++++++++++++++++++++++ packages/core/src/trace.ts | 5 ++-- 3 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 packages/core/src/secrets.ts diff --git a/packages/core/src/chat.ts b/packages/core/src/chat.ts index b0877fb6c5..39c6cee5ab 100644 --- a/packages/core/src/chat.ts +++ b/packages/core/src/chat.ts @@ -73,6 +73,7 @@ import { serializeLogProb, topLogprobsToMarkdown, } from "./logprob" +import { hideSecrets } from "./secrets" export function toChatCompletionUserMessage( expanded: string, @@ -967,11 +968,11 @@ export function appendUserMessage( ) { if (!content) return const last = messages.at(-1) as ChatCompletionUserMessageParam - if (last?.role === "user") last.content += "\n" + content + if (last?.role === "user") last.content += "\n" + hideSecrets(content) else messages.push({ role: "user", - content, + content: hideSecrets(content), } as ChatCompletionUserMessageParam) } @@ -981,11 +982,11 @@ export function appendAssistantMessage( ) { if (!content) return const last = messages.at(-1) as ChatCompletionAssistantMessageParam - if (last?.role === "assistant") last.content += "\n" + content + if (last?.role === "assistant") last.content += "\n" + hideSecrets(content) else messages.push({ role: "assistant", - content, + content: hideSecrets(content), } satisfies ChatCompletionAssistantMessageParam) } @@ -1003,7 +1004,7 @@ export function appendSystemMessage( messages.unshift(last) } if (last.content) last.content += SYSTEM_FENCE - last.content += content + last.content += hideSecrets(content) } export function addToolDefinitionsMessage( diff --git a/packages/core/src/secrets.ts b/packages/core/src/secrets.ts new file mode 100644 index 0000000000..8251d1cecf --- /dev/null +++ b/packages/core/src/secrets.ts @@ -0,0 +1,58 @@ +import { TraceOptions } from "./trace" +import { logVerbose } from "./util" + +const secretPatterns: Record = { + "AWS Access Key": /AKIA[0-9A-Z]{16}/g, + "AWS Secret Key": /[0-9a-zA-Z/+]{40}/g, + "GitHub Token": /ghp_[0-9a-zA-Z]{36}/g, + "Slack Token": /xox[baprs]-[0-9a-zA-Z]{10,48}/g, + "Google API Key": /AIza[0-9A-Za-z-_]{35}/g, + "Azure Key": /[0-9a-zA-Z/+]{88}/g, + "Heroku API Key": /[0-9a-fA-F]{32}/g, + "Stripe API Key": /sk_live_[0-9a-zA-Z]{24}/g, + "Google AI Key": /AIza[0-9A-Za-z-_]{35}/g, + "OpenAI Key": /sk-[0-9a-zA-Z]{32}/g, + "Twilio API Key": /SK[0-9a-fA-F]{32}/g, + "SendGrid API Key": /SG\.[0-9A-Za-z\-_]{22}\.[0-9A-Za-z\-_]{43}/g, + "Facebook Access Token": /EAACEdEose0cBA[0-9A-Za-z]+/g, + "Twitter Access Token": /[1-9][0-9]+-[0-9a-zA-Z]{40}/g, + "Twitter Secret Key": /[0-9a-zA-Z]{40}/g, + "GitLab Personal Access Token": /glpat-[0-9a-zA-Z\-_]{20}/g, + "DigitalOcean Token": /[0-9a-fA-F]{64}/g, + "Mailgun API Key": /key-[0-9a-zA-Z]{32}/g, + "Dropbox Access Token": /sl.[0-9a-zA-Z\-_]{43}/g, + "Shopify Access Token": /shpat_[0-9a-fA-F]{32}/g, + "GitHub Personal Access Token": /ghp_[0-9a-zA-Z]{36}/g, + "Generic API Key": /(? Date: Mon, 18 Nov 2024 05:01:35 +0000 Subject: [PATCH 2/3] =?UTF-8?q?fix:=20improve=20secret=20logging=20clarity?= =?UTF-8?q?=20=F0=9F=9B=A0=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/secrets.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/core/src/secrets.ts b/packages/core/src/secrets.ts index 8251d1cecf..bba55a7b30 100644 --- a/packages/core/src/secrets.ts +++ b/packages/core/src/secrets.ts @@ -52,7 +52,9 @@ export function hideSecrets(text: string): string { for (const pattern of Object.entries(secretPatterns)) { let prev = result result = result.replace(pattern[1], "***") - if (prev !== result) logVerbose(`secrets: hidding ${pattern[0]}`) + if (prev !== result) { + logVerbose(`secrets: hidding potential ${pattern[0]} secret`) + } } return result } From cf6b59f09649e6e23ab331abb22406764d9d5319 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Mon, 18 Nov 2024 05:09:05 +0000 Subject: [PATCH 3/3] a few scanners --- packages/core/src/secrets.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/core/src/secrets.ts b/packages/core/src/secrets.ts index bba55a7b30..14230d9985 100644 --- a/packages/core/src/secrets.ts +++ b/packages/core/src/secrets.ts @@ -3,12 +3,10 @@ import { logVerbose } from "./util" const secretPatterns: Record = { "AWS Access Key": /AKIA[0-9A-Z]{16}/g, - "AWS Secret Key": /[0-9a-zA-Z/+]{40}/g, "GitHub Token": /ghp_[0-9a-zA-Z]{36}/g, "Slack Token": /xox[baprs]-[0-9a-zA-Z]{10,48}/g, "Google API Key": /AIza[0-9A-Za-z-_]{35}/g, "Azure Key": /[0-9a-zA-Z/+]{88}/g, - "Heroku API Key": /[0-9a-fA-F]{32}/g, "Stripe API Key": /sk_live_[0-9a-zA-Z]{24}/g, "Google AI Key": /AIza[0-9A-Za-z-_]{35}/g, "OpenAI Key": /sk-[0-9a-zA-Z]{32}/g, @@ -40,7 +38,6 @@ const secretPatterns: Record = { "Database Connection String": /(?:jdbc|odbc):[a-zA-Z0-9@:\/\.\?&=]+/g, "Basic Auth Header": /Basic [a-zA-Z0-9=+\/]+/g, "Bearer Token Header": /Bearer [A-Za-z0-9\-_]+/g, - "Base64 Encoded Secret": /[A-Za-z0-9+/]{40,}(={0,2})/g, "Google OAuth Refresh Token": /1\/[A-Za-z0-9_-]{43}/g, "Kubernetes Secret": /apiVersion:\s+v1[\s\S]+kind:\s+Secret[\s\S]+data:/g, "Firebase Database URL": /https:\/\/[a-z0-9-]+\.firebaseio\.com/g, @@ -54,6 +51,7 @@ export function hideSecrets(text: string): string { result = result.replace(pattern[1], "***") if (prev !== result) { logVerbose(`secrets: hidding potential ${pattern[0]} secret`) + process.stderr.write(pattern[1].exec(prev) + "\n") } } return result