Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions nemoclaw/src/security/secret-scanner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import { isMemoryPath, scanForSecrets } from "./secret-scanner.js";
const FAKE = {
nvidia: "nvapi-" + "abcdefghijklmnopqrstuvwxyz",
openai: "sk-" + "abc123def456ghi789jkl012mno",
openaiProject: "sk-proj-" + "abc123_def456-ghi789_jkl012-mno345",
github: "ghp_" + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn",
aws: "AKIA" + "IOSFODNN7EXAMPLE",
slack: "xoxb-" + "123456789-abcdefghij",
slackApp: "xapp-" + "1-A0000-12345-abcdef",
npm: "npm_" + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn",
pemRsa: "-----BEGIN RSA " + "PRIVATE KEY-----\nMIIEpA...",
pemOpenssh: "-----BEGIN OPENSSH " + "PRIVATE KEY-----\nb3Blbn...",
Expand Down Expand Up @@ -40,6 +42,12 @@ describe("scanForSecrets", () => {
expect(matches[0].pattern).toBe("OpenAI API key");
});

it("OpenAI project API key", () => {
const matches = scanForSecrets(`export OPENAI_API_KEY=${FAKE.openaiProject}`);
expect(matches).toHaveLength(1);
expect(matches[0].pattern).toBe("OpenAI API key");
});

it("GitHub personal access token", () => {
const matches = scanForSecrets(`token: ${FAKE.github}`);
expect(matches).toHaveLength(1);
Expand All @@ -58,6 +66,12 @@ describe("scanForSecrets", () => {
expect(matches[0].pattern).toBe("Slack token");
});

it("Slack app token", () => {
const matches = scanForSecrets(`SLACK_APP_TOKEN=${FAKE.slackApp}`);
expect(matches).toHaveLength(1);
expect(matches[0].pattern).toBe("Slack token");
});

it("npm token", () => {
const matches = scanForSecrets(`//registry.npmjs.org/:_authToken=${FAKE.npm}`);
expect(matches).toHaveLength(1);
Expand Down
4 changes: 2 additions & 2 deletions nemoclaw/src/security/secret-scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const SECRET_PATTERNS: SecretPattern[] = [
{ name: "NVIDIA API key", regex: /\bnvapi-[A-Za-z0-9_-]{20,}\b/ },

// OpenAI — exclude sk-ant- (Anthropic) to avoid double-matching
{ name: "OpenAI API key", regex: /\bsk-(?!ant-)[A-Za-z0-9]{20,}\b/ },
{ name: "OpenAI API key", regex: /\bsk-(?!ant-)[A-Za-z0-9_-]{20,}\b/ },

// GitHub
{ name: "GitHub token", regex: /\b(ghp|gho|ghu|ghs|ghr|github_pat)_[A-Za-z0-9]{36,}\b/ },
Expand All @@ -39,7 +39,7 @@ const SECRET_PATTERNS: SecretPattern[] = [
},

// Slack
{ name: "Slack token", regex: /\bxox[bpas]-[A-Za-z0-9-]{10,}\b/ },
{ name: "Slack token", regex: /\b(?:xox[bpas]|xapp)-[A-Za-z0-9-]{10,}\b/ },

// Discord — require contextual prefix to avoid matching JWT/base64 strings
{
Expand Down
Loading