bastion-scan 0.1.2 → 0.1.3

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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +117 -12
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -48,7 +48,7 @@ npx bastion-scan scan --generate-configs
48
48
  | Check | What it does |
49
49
  |-------|-------------|
50
50
  | `.gitignore` coverage | Makes sure `.env`, `node_modules`, and keys are excluded |
51
- | Hardcoded secrets | Looks for API keys from OpenAI, Stripe, AWS, and others |
51
+ | Hardcoded secrets | API keys from OpenAI, Anthropic, GitHub, Stripe, AWS, Google, Slack, and more |
52
52
  | Dependency audit | Wraps `npm audit` and maps findings to severity levels |
53
53
  | `.env.example` | Checks that a template exists with safe placeholder values |
54
54
  | `security.txt` | Validates RFC 9116 Contact + Expires fields |
package/dist/index.js CHANGED
@@ -196,40 +196,145 @@ var SCANNABLE_EXTENSIONS = /* @__PURE__ */ new Set([
196
196
  ]);
197
197
  var IGNORED_DIRS = /* @__PURE__ */ new Set(["node_modules", "dist", "build", ".git", "tests", "__tests__", "test", "fixtures"]);
198
198
  var SECRET_PATTERNS = [
199
+ // ── OpenAI ──────────────────────────────────────────────────────────────
199
200
  {
200
- name: "OpenAI API key",
201
- regex: /sk-[A-Za-z0-9]{20,}/,
202
- description: "OpenAI API key detected"
201
+ name: "OpenAI API key (project)",
202
+ regex: /sk-proj-[a-zA-Z0-9_-]{20,}/,
203
+ description: "OpenAI project API key detected",
204
+ severity: "critical"
203
205
  },
206
+ {
207
+ name: "OpenAI API key (service account)",
208
+ regex: /sk-svcacct-[a-zA-Z0-9_-]{20,}/,
209
+ description: "OpenAI service account key detected",
210
+ severity: "critical"
211
+ },
212
+ {
213
+ name: "OpenAI API key (legacy)",
214
+ regex: /sk-[a-zA-Z0-9]{20,}/,
215
+ description: "OpenAI API key detected",
216
+ severity: "critical"
217
+ },
218
+ // ── Anthropic ───────────────────────────────────────────────────────────
219
+ {
220
+ name: "Anthropic API key",
221
+ regex: /sk-ant-api[0-9]{2}-[a-zA-Z0-9_-]{40,}/,
222
+ description: "Anthropic API key detected",
223
+ severity: "critical"
224
+ },
225
+ {
226
+ name: "Anthropic admin key",
227
+ regex: /sk-ant-admin[0-9]{2}-[a-zA-Z0-9_-]{40,}/,
228
+ description: "Anthropic admin API key detected",
229
+ severity: "critical"
230
+ },
231
+ // ── GitHub ──────────────────────────────────────────────────────────────
232
+ {
233
+ name: "GitHub PAT (classic)",
234
+ regex: /ghp_[a-zA-Z0-9]{36}/,
235
+ description: "GitHub personal access token (classic) detected",
236
+ severity: "critical"
237
+ },
238
+ {
239
+ name: "GitHub OAuth token",
240
+ regex: /gho_[a-zA-Z0-9]{36}/,
241
+ description: "GitHub OAuth access token detected",
242
+ severity: "critical"
243
+ },
244
+ {
245
+ name: "GitHub PAT (fine-grained)",
246
+ regex: /github_pat_[a-zA-Z0-9_]{82}/,
247
+ description: "GitHub fine-grained personal access token detected",
248
+ severity: "critical"
249
+ },
250
+ {
251
+ name: "GitHub app token",
252
+ regex: /ghs_[a-zA-Z0-9]{36}/,
253
+ description: "GitHub app installation token detected",
254
+ severity: "critical"
255
+ },
256
+ {
257
+ name: "GitHub refresh token",
258
+ regex: /ghr_[a-zA-Z0-9]{36}/,
259
+ description: "GitHub refresh token detected",
260
+ severity: "critical"
261
+ },
262
+ // ── Stripe ──────────────────────────────────────────────────────────────
204
263
  {
205
264
  name: "Stripe secret key",
206
- regex: /sk_live_[A-Za-z0-9]{20,}/,
207
- description: "Stripe secret key detected"
265
+ regex: /sk_live_[a-zA-Z0-9]{24,}/,
266
+ description: "Stripe secret key detected",
267
+ severity: "critical"
208
268
  },
209
269
  {
210
270
  name: "Stripe publishable key",
211
- regex: /pk_live_[A-Za-z0-9]{20,}/,
212
- description: "Stripe publishable live key detected"
271
+ regex: /pk_live_[a-zA-Z0-9]{20,}/,
272
+ description: "Stripe publishable live key detected",
273
+ severity: "critical"
274
+ },
275
+ {
276
+ name: "Stripe restricted key",
277
+ regex: /rk_live_[a-zA-Z0-9]{24,}/,
278
+ description: "Stripe restricted API key detected",
279
+ severity: "critical"
213
280
  },
281
+ {
282
+ name: "Stripe test key",
283
+ regex: /sk_test_[a-zA-Z0-9]{24,}/,
284
+ description: "Stripe test secret key detected",
285
+ severity: "high"
286
+ },
287
+ // ── AWS ─────────────────────────────────────────────────────────────────
214
288
  {
215
289
  name: "AWS access key",
216
290
  regex: /AKIA[0-9A-Z]{16}/,
217
- description: "AWS access key ID detected"
291
+ description: "AWS access key ID detected",
292
+ severity: "critical"
293
+ },
294
+ // ── Google ──────────────────────────────────────────────────────────────
295
+ {
296
+ name: "Google API key",
297
+ regex: /AIza[a-zA-Z0-9_-]{35}/,
298
+ description: "Google API key detected",
299
+ severity: "critical"
218
300
  },
301
+ // ── Slack ───────────────────────────────────────────────────────────────
302
+ {
303
+ name: "Slack bot token",
304
+ regex: /xoxb-[0-9]{10,13}-[0-9]{10,13}-[a-zA-Z0-9]{24,}/,
305
+ description: "Slack bot token detected",
306
+ severity: "critical"
307
+ },
308
+ {
309
+ name: "Slack user token",
310
+ regex: /xoxp-[0-9]{10,13}-[0-9]{10,13}-[0-9]{10,13}-[a-zA-Z0-9]{32}/,
311
+ description: "Slack user token detected",
312
+ severity: "critical"
313
+ },
314
+ {
315
+ name: "Slack webhook URL",
316
+ regex: /https:\/\/hooks\.slack\.com\/services\/T[a-zA-Z0-9]{8,12}\/B[a-zA-Z0-9]{8,12}\/[a-zA-Z0-9]{24}/,
317
+ description: "Slack incoming webhook URL detected",
318
+ severity: "high"
319
+ },
320
+ // ── Generic ─────────────────────────────────────────────────────────────
219
321
  {
220
322
  name: "Generic API key assignment",
221
323
  regex: /(?:api[_-]?key|apikey|api[_-]?secret)\s*[:=]\s*['"][A-Za-z0-9_\-/.]{8,}['"]/i,
222
- description: "Hardcoded API key assignment detected"
324
+ description: "Hardcoded API key assignment detected",
325
+ severity: "critical"
223
326
  },
224
327
  {
225
328
  name: "Bearer token",
226
329
  regex: /['"]Bearer\s+[A-Za-z0-9_\-/.+]{20,}['"]/,
227
- description: "Hardcoded Bearer token detected"
330
+ description: "Hardcoded Bearer token detected",
331
+ severity: "critical"
228
332
  },
229
333
  {
230
334
  name: "Database connection string",
231
335
  regex: /(?:mongodb(?:\+srv)?|postgres(?:ql)?|mysql|redis):\/\/[^:]+:[^@\s]+@/i,
232
- description: "Database connection string with embedded password detected"
336
+ description: "Database connection string with embedded password detected",
337
+ severity: "critical"
233
338
  }
234
339
  ];
235
340
  var AI_PROMPT = "I found a hardcoded secret in my source code. Help me move it to an environment variable. Show me: (1) how to add it to .env, (2) how to read it with process.env or the equivalent for my framework, (3) how to add the key name to .env.example with a placeholder value, and (4) how to validate at startup that the variable is set.";
@@ -265,7 +370,7 @@ function scanContent(content, relativePath) {
265
370
  id: "secrets",
266
371
  name: `Hardcoded secret: ${pattern.name}`,
267
372
  status: "fail",
268
- severity: "critical",
373
+ severity: pattern.severity,
269
374
  category: "Secrets",
270
375
  location: `${relativePath}:${i + 1}`,
271
376
  description: pattern.description,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bastion-scan",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Privacy-first security checker for web projects. 15 checks, zero data uploaded, actionable fixes.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -37,7 +37,7 @@
37
37
  "dev": "tsup --watch"
38
38
  },
39
39
  "dependencies": {
40
- "bastion-shared": "^0.1.2",
40
+ "bastion-shared": "^0.1.3",
41
41
  "chalk": "^5.6.2",
42
42
  "commander": "^14.0.3",
43
43
  "ora": "^9.3.0"