badgr-security-scan 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,143 @@
1
+ # badgr-security-scan
2
+
3
+ Scan code, configs, and agent prompts for obvious security risks — leaked secrets, unsafe defaults, prompt injection, and dangerous tool permissions.
4
+
5
+ ```bash
6
+ npx badgr-security-scan --text "$(cat src/config.ts)"
7
+ ```
8
+
9
+ **Free. No signup required.** Runs entirely on your machine — nothing is sent anywhere.
10
+
11
+ ---
12
+
13
+ ## The problem it solves
14
+
15
+ AI agents and LLM apps have a new class of security risks: leaked API keys in prompts, `exec()` calls in agent tools, and prompt injection phrases that hijack agent behavior. Standard linters don't catch these. `badgr-security-scan` does — in one command, with no setup.
16
+
17
+ ---
18
+
19
+ ## Quick start
20
+
21
+ ```bash
22
+ # Scan a code snippet
23
+ npx badgr-security-scan --text "API_KEY=sk_live_abc123 const client = new OpenAI()"
24
+
25
+ # Scan a file
26
+ npx badgr-security-scan --text "$(cat src/agent.ts)"
27
+
28
+ # Machine-readable JSON (for CI or pre-commit hooks)
29
+ npx badgr-security-scan --text "$(cat src/agent.ts)" --json
30
+
31
+ # Skip prompt injection checks
32
+ npx badgr-security-scan --text "$(cat src/config.ts)" --no-prompt-injection
33
+ ```
34
+
35
+ ---
36
+
37
+ ## CLI flags
38
+
39
+ | Flag | Description |
40
+ |------|-------------|
41
+ | `--text <str>` | Text or code snippet to scan (required) |
42
+ | `--no-prompt-injection` | Skip prompt injection pattern checks |
43
+ | `--json` | Output machine-readable JSON |
44
+
45
+ **Exit codes:** `0` = no blocking risks found, `1` = risks found
46
+
47
+ ---
48
+
49
+ ## What it checks
50
+
51
+ | Category | What it looks for | Example |
52
+ |---|---|---|
53
+ | `secret` | API keys, tokens, or secrets with 16+ char values | `API_KEY=sk_live_abc123456789` |
54
+ | `unsafe-default` | Auth bypasses and TLS disabled | `rejectUnauthorized: false`, `disableAuth` |
55
+ | `dangerous-tool` | Shell execution in agent tool code | `exec()`, `child_process`, `rm -rf` |
56
+ | `prompt-injection` | Phrases that hijack agent behavior | `"Ignore previous instructions"`, `"exfiltrate"` |
57
+
58
+ ---
59
+
60
+ ## Example output
61
+
62
+ ```
63
+ badgr-security-scan
64
+
65
+ ✗ secret API key or token found: API_KEY=sk_live_... (truncated)
66
+ ✗ dangerous-tool exec() call detected — dangerous in agent tool context
67
+ ✓ unsafe-default No unsafe auth defaults found
68
+ ✓ prompt-injection No injection phrases found
69
+
70
+ 2 risks found. Review before deploying.
71
+ ```
72
+
73
+ ```
74
+ badgr-security-scan
75
+
76
+ ✓ secret No leaked secrets found
77
+ ✓ unsafe-default No unsafe auth defaults found
78
+ ✓ dangerous-tool No dangerous tool patterns found
79
+ ✓ prompt-injection No injection phrases found
80
+
81
+ All checks passed.
82
+ ```
83
+
84
+ ---
85
+
86
+ ## TypeScript API
87
+
88
+ ```ts
89
+ import { runSecurityScan } from "badgr-security-scan";
90
+
91
+ const result = runSecurityScan({
92
+ text: sourceCode,
93
+ includePromptInjectionChecks: true, // default: true
94
+ });
95
+
96
+ console.log(result.checks);
97
+ // [
98
+ // { status: "fail", label: "secret", detail: "API key found: API_KEY=sk_live_..." },
99
+ // { status: "pass", label: "unsafe-default", detail: "No unsafe auth defaults found" },
100
+ // ...
101
+ // ]
102
+
103
+ if (!result.checks.every(c => c.status === "pass")) {
104
+ process.exit(1);
105
+ }
106
+ ```
107
+
108
+ **Types:**
109
+
110
+ ```ts
111
+ interface SecurityScanOptions {
112
+ text: string;
113
+ includePromptInjectionChecks?: boolean; // default: true
114
+ }
115
+
116
+ interface SecurityScanResult {
117
+ checks: DiagnosticCheck[];
118
+ report: JsonReport;
119
+ }
120
+ ```
121
+
122
+ ---
123
+
124
+ ## Use in CI / pre-commit
125
+
126
+ **GitHub Actions:**
127
+
128
+ ```yaml
129
+ - name: Security scan
130
+ run: npx badgr-security-scan --text "$(cat src/agent.ts)" --json
131
+ ```
132
+
133
+ **Pre-commit hook (`.husky/pre-commit`):**
134
+
135
+ ```bash
136
+ npx badgr-security-scan --text "$(git diff --cached --unified=0)" --json
137
+ ```
138
+
139
+ ---
140
+
141
+ ## Requirements
142
+
143
+ - Node.js 18+
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env node
2
+ import { createLogger, fireTelemetry } from "badgr-shared";
3
+ import { runSecurityScan } from "./index.js";
4
+ fireTelemetry({ package: "badgr-security-scan" });
5
+ function readArg(name) {
6
+ const index = process.argv.indexOf(name);
7
+ return index >= 0 ? process.argv[index + 1] : undefined;
8
+ }
9
+ if (process.argv.includes("--help") || process.argv.includes("-h")) {
10
+ console.log(`badgr-security-scan — local scan for secrets, unsafe defaults, and prompt injection
11
+
12
+ Usage:
13
+ npx badgr-security-scan --text "API_KEY=sk_test_1234567890abcdef"
14
+ npx badgr-security-scan --text "<code snippet>" --json
15
+
16
+ Flags:
17
+ --text <str> Text or code snippet to scan (required)
18
+ --no-prompt-injection Skip prompt-injection pattern checks
19
+ --json Output machine-readable JSON
20
+
21
+ Checks performed:
22
+ secret Leaked API keys, tokens, or secrets (16+ char values)
23
+ unsafe-default disableAuth, rejectUnauthorized: false, verify: false
24
+ dangerous-tool exec(), rm -rf, child_process in agent tool code
25
+ prompt-injection "ignore previous instructions", exfiltrate phrases
26
+
27
+ Exit codes:
28
+ 0 No blocking risks found
29
+ 1 One or more security checks failed
30
+
31
+ No signup required. Hosted agent policies and approvals are optional.
32
+
33
+ Environment:
34
+ BADGR_TELEMETRY=0 Disable anonymous usage telemetry`);
35
+ process.exit(0);
36
+ }
37
+ const json = process.argv.includes("--json");
38
+ const text = readArg("--text") ?? process.argv.slice(2).filter((a) => a !== "--json").join(" ");
39
+ if (!text.trim()) {
40
+ console.error("Error: --text is required");
41
+ console.error('Usage: npx badgr-security-scan --text "API_KEY=sk_test_abc..."');
42
+ process.exit(2);
43
+ }
44
+ const result = runSecurityScan({
45
+ text,
46
+ includePromptInjectionChecks: !process.argv.includes("--no-prompt-injection"),
47
+ });
48
+ const logger = createLogger(json);
49
+ if (json) {
50
+ logger.report(result.report);
51
+ }
52
+ else {
53
+ logger.line("badgr-security-scan report");
54
+ logger.line("");
55
+ for (const check of result.checks) {
56
+ logger.line(`${check.status === "pass" ? "✓" : "✗"} ${check.message}`);
57
+ }
58
+ logger.line("");
59
+ logger.line(`Status: ${result.report.status}`);
60
+ if (result.report.recommendedActions.length > 0) {
61
+ logger.line("");
62
+ for (const action of result.report.recommendedActions)
63
+ logger.line(` → ${action}`);
64
+ }
65
+ logger.line("");
66
+ logger.line("Optional: connect AI Badgr policies for hosted agent tool approvals.");
67
+ }
68
+ process.exitCode = result.report.status === "failed" ? 1 : 0;
69
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { type DiagnosticCheck, type JsonReport } from "badgr-shared";
2
+ export interface SecurityScanOptions {
3
+ text: string;
4
+ includePromptInjectionChecks?: boolean;
5
+ }
6
+ export interface SecurityScanResult {
7
+ checks: DiagnosticCheck[];
8
+ report: JsonReport;
9
+ }
10
+ export declare function runSecurityScan(options: SecurityScanOptions): SecurityScanResult;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0D,KAAK,eAAe,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAE7H,MAAM,WAAW,mBAAmB;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,4BAA4B,CAAC,EAAE,OAAO,CAAC;CAAE;AAC9F,MAAM,WAAW,kBAAkB;IAAG,MAAM,EAAE,eAAe,EAAE,CAAC;IAAC,MAAM,EAAE,UAAU,CAAC;CAAE;AAEtF,wBAAgB,eAAe,CAAC,OAAO,EAAE,mBAAmB,GAAG,kBAAkB,CAqBhF"}
package/dist/index.js ADDED
@@ -0,0 +1,37 @@
1
+ import { checkToFinding, createReport, reportStatusFromFindings } from "badgr-shared";
2
+ export function runSecurityScan(options) {
3
+ const text = options.text;
4
+ const checks = [];
5
+ checks.push(patternCheck("secret", /(?:api[_-]?key|secret|token)\s*[:=]\s*['\"]?[A-Za-z0-9_\-]{16,}/i, text, "possible leaked secret or token"));
6
+ checks.push(patternCheck("unsafe-default", /allowAll|disableAuth|verify\s*[:=]\s*false|rejectUnauthorized\s*[:=]\s*false/i, text, "unsafe auth or TLS default detected"));
7
+ checks.push(patternCheck("dangerous-tool", /exec\(|shell\(|child_process|rm -rf|writeFile\(/i, text, "dangerous agent tool or shell capability detected"));
8
+ if (options.includePromptInjectionChecks ?? true)
9
+ checks.push(patternCheck("prompt-injection", /ignore previous instructions|exfiltrate|send.*secret|reveal.*system prompt/i, text, "prompt-injection phrase detected"));
10
+ const findings = checks.map((check) => checkToFinding(check, "SECURITY"));
11
+ const status = reportStatusFromFindings(findings);
12
+ return {
13
+ checks,
14
+ report: createReport({
15
+ tool: "security-scan",
16
+ status,
17
+ summary: status === "failed" ? "Security scan found obvious risks" : "Security scan found no obvious blocking risks",
18
+ findings,
19
+ recommendedActions: buildActions(checks),
20
+ nextCommand: "npx @aibadgr/security-scan --json",
21
+ actionUrl: "https://aibadgr.com/agents/connect",
22
+ }),
23
+ };
24
+ }
25
+ function patternCheck(name, pattern, text, message) {
26
+ return pattern.test(text) ? { name, status: "fail", message } : { name, status: "pass", message: `no ${name} pattern detected` };
27
+ }
28
+ function buildActions(checks) {
29
+ const actions = [];
30
+ if (checks.some((check) => check.name === "secret" && check.status === "fail"))
31
+ actions.push("Rotate exposed secrets and remove them from code/config");
32
+ if (checks.some((check) => check.name === "dangerous-tool" && check.status === "fail"))
33
+ actions.push("Add approval gates around dangerous agent tools");
34
+ actions.push("Use AI Badgr policies later to control agent tool access and approvals");
35
+ return actions;
36
+ }
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,wBAAwB,EAAyC,MAAM,cAAc,CAAC;AAK7H,MAAM,UAAU,eAAe,CAAC,OAA4B;IAC1D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC1B,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,kEAAkE,EAAE,IAAI,EAAE,iCAAiC,CAAC,CAAC,CAAC;IACjJ,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,gBAAgB,EAAE,+EAA+E,EAAE,IAAI,EAAE,qCAAqC,CAAC,CAAC,CAAC;IAC1K,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,gBAAgB,EAAE,kDAAkD,EAAE,IAAI,EAAE,mDAAmD,CAAC,CAAC,CAAC;IAC3J,IAAI,OAAO,CAAC,4BAA4B,IAAI,IAAI;QAAE,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,kBAAkB,EAAE,6EAA6E,EAAE,IAAI,EAAE,kCAAkC,CAAC,CAAC,CAAC;IACzN,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;IAC1E,MAAM,MAAM,GAAG,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAClD,OAAO;QACL,MAAM;QACN,MAAM,EAAE,YAAY,CAAC;YACnB,IAAI,EAAE,eAAe;YACrB,MAAM;YACN,OAAO,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,mCAAmC,CAAC,CAAC,CAAC,+CAA+C;YACpH,QAAQ;YACR,kBAAkB,EAAE,YAAY,CAAC,MAAM,CAAC;YACxC,WAAW,EAAE,mCAAmC;YAChD,SAAS,EAAE,oCAAoC;SAChD,CAAC;KACH,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,OAAe,EAAE,IAAY,EAAE,OAAe;IAChF,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,mBAAmB,EAAE,CAAC;AACnI,CAAC;AAED,SAAS,YAAY,CAAC,MAAyB;IAC7C,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC;IACxJ,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,gBAAgB,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;IACxJ,OAAO,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC;IACvF,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "badgr-security-scan",
3
+ "version": "0.1.0",
4
+ "description": "Local-first scan for leaked secrets, unsafe defaults, prompt injection, and dangerous agent tools.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": { "badgr-security-scan": "dist/cli.js" },
9
+ "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" } },
10
+ "files": ["dist", "README.md"],
11
+ "scripts": { "build": "tsc -b", "typecheck": "tsc -b --pretty false", "test": "vitest run" },
12
+ "dependencies": { "badgr-shared": "0.1.1" },
13
+ "engines": { "node": ">=18.0.0" },
14
+ "keywords": ["security", "secrets", "prompt-injection", "agent", "authorization"],
15
+ "license": "MIT"
16
+ }