secret-blast-radius 0.1.0 → 0.2.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/src/iocs.json ADDED
@@ -0,0 +1,251 @@
1
+ {
2
+ "updated": "2026-10-22",
3
+ "packages": [
4
+ {
5
+ "ecosystem": "npm",
6
+ "name": "tensorlake",
7
+ "versions": [
8
+ "0.5.144"
9
+ ],
10
+ "campaign": "mini-shai-hulud",
11
+ "incident": "tensorlake",
12
+ "safe": "0.5.143 or 0.5.145+",
13
+ "ref": "https://github.com/tensorlakeai/tensorlake/security/advisories/GHSA-8g63-53c9-65j2"
14
+ },
15
+ {
16
+ "ecosystem": "npm",
17
+ "name": "tensorlake-native-darwin-arm64",
18
+ "versions": [
19
+ "0.5.144"
20
+ ],
21
+ "campaign": "mini-shai-hulud",
22
+ "incident": "tensorlake",
23
+ "safe": "0.5.143",
24
+ "ref": "https://github.com/tensorlakeai/tensorlake/security/advisories/GHSA-8g63-53c9-65j2"
25
+ },
26
+ {
27
+ "ecosystem": "npm",
28
+ "name": "tensorlake-native-linux-arm64-gnu",
29
+ "versions": [
30
+ "0.5.144"
31
+ ],
32
+ "campaign": "mini-shai-hulud",
33
+ "incident": "tensorlake",
34
+ "safe": "0.5.143",
35
+ "ref": "https://github.com/tensorlakeai/tensorlake/security/advisories/GHSA-8g63-53c9-65j2"
36
+ },
37
+ {
38
+ "ecosystem": "npm",
39
+ "name": "tensorlake-native-linux-arm64-musl",
40
+ "versions": [
41
+ "0.5.144"
42
+ ],
43
+ "campaign": "mini-shai-hulud",
44
+ "incident": "tensorlake",
45
+ "safe": "0.5.143",
46
+ "ref": "https://github.com/tensorlakeai/tensorlake/security/advisories/GHSA-8g63-53c9-65j2"
47
+ },
48
+ {
49
+ "ecosystem": "npm",
50
+ "name": "tensorlake-native-linux-x64-gnu",
51
+ "versions": [
52
+ "0.5.144"
53
+ ],
54
+ "campaign": "mini-shai-hulud",
55
+ "incident": "tensorlake",
56
+ "safe": "0.5.143",
57
+ "ref": "https://github.com/tensorlakeai/tensorlake/security/advisories/GHSA-8g63-53c9-65j2"
58
+ },
59
+ {
60
+ "ecosystem": "npm",
61
+ "name": "tensorlake-native-linux-x64-musl",
62
+ "versions": [
63
+ "0.5.144"
64
+ ],
65
+ "campaign": "mini-shai-hulud",
66
+ "incident": "tensorlake",
67
+ "safe": "0.5.143",
68
+ "ref": "https://github.com/tensorlakeai/tensorlake/security/advisories/GHSA-8g63-53c9-65j2"
69
+ },
70
+ {
71
+ "ecosystem": "npm",
72
+ "name": "tensorlake-native-win32-x64",
73
+ "versions": [
74
+ "0.5.144"
75
+ ],
76
+ "campaign": "mini-shai-hulud",
77
+ "incident": "tensorlake",
78
+ "safe": "0.5.143",
79
+ "ref": "https://github.com/tensorlakeai/tensorlake/security/advisories/GHSA-8g63-53c9-65j2"
80
+ },
81
+ {
82
+ "ecosystem": "npm",
83
+ "name": "@subql/common",
84
+ "versions": [
85
+ "5.8.3"
86
+ ],
87
+ "campaign": "subql",
88
+ "incident": "subql",
89
+ "safe": "5.8.2",
90
+ "ref": "https://osv.dev/vulnerability/MAL-2026-17571"
91
+ },
92
+ {
93
+ "ecosystem": "npm",
94
+ "name": "@7nohe/openapi-react-query-codegen",
95
+ "versions": [
96
+ "0.0.0-365d4eb738d3146583431948d3ba6e27a32556be",
97
+ "0.0.0-ec7876d6c917dad516ba69bbfafc948b834bf0ab",
98
+ "0.5.4",
99
+ "0.5.5",
100
+ "1.6.3",
101
+ "1.6.4",
102
+ "2.2.1",
103
+ "2.2.2",
104
+ "3.0.3",
105
+ "3.0.4"
106
+ ],
107
+ "campaign": "mini-shai-hulud",
108
+ "incident": "shai-hulud",
109
+ "safe": "0.5.3 / 1.6.2 / 2.2.0 / 3.0.2",
110
+ "ref": "https://socket.dev/blog/openapi-react-query-codegen-npm-compromise"
111
+ },
112
+ {
113
+ "ecosystem": "npm",
114
+ "name": "keyv",
115
+ "versions": [
116
+ "6.0.0"
117
+ ],
118
+ "campaign": "mini-shai-hulud",
119
+ "incident": "shai-hulud",
120
+ "safe": "5.6.0",
121
+ "ref": "https://www.sonatype.com/blog/mini-shai-hulud-npm-attack-more-than-2200-components-impacted"
122
+ },
123
+ {
124
+ "ecosystem": "npm",
125
+ "name": "cacheable",
126
+ "versions": [
127
+ "2.5.1"
128
+ ],
129
+ "campaign": "mini-shai-hulud",
130
+ "incident": "shai-hulud",
131
+ "safe": "2.5.0",
132
+ "ref": "https://www.sonatype.com/blog/mini-shai-hulud-npm-attack-more-than-2200-components-impacted"
133
+ },
134
+ {
135
+ "ecosystem": "npm",
136
+ "name": "cacheable-request",
137
+ "versions": [
138
+ "13.0.20"
139
+ ],
140
+ "campaign": "mini-shai-hulud",
141
+ "incident": "shai-hulud",
142
+ "safe": "13.0.19",
143
+ "ref": "https://www.sonatype.com/blog/mini-shai-hulud-npm-attack-more-than-2200-components-impacted"
144
+ },
145
+ {
146
+ "ecosystem": "npm",
147
+ "name": "cache-manager",
148
+ "versions": [
149
+ "7.2.10"
150
+ ],
151
+ "campaign": "mini-shai-hulud",
152
+ "incident": "shai-hulud",
153
+ "safe": "7.2.9",
154
+ "ref": "https://www.sonatype.com/blog/mini-shai-hulud-npm-attack-more-than-2200-components-impacted"
155
+ },
156
+ {
157
+ "ecosystem": "npm",
158
+ "name": "flat-cache",
159
+ "versions": [
160
+ "6.1.24"
161
+ ],
162
+ "campaign": "mini-shai-hulud",
163
+ "incident": "shai-hulud",
164
+ "safe": "6.1.23",
165
+ "ref": "https://www.sonatype.com/blog/mini-shai-hulud-npm-attack-more-than-2200-components-impacted"
166
+ },
167
+ {
168
+ "ecosystem": "npm",
169
+ "name": "file-entry-cache",
170
+ "versions": [
171
+ "11.1.6"
172
+ ],
173
+ "campaign": "mini-shai-hulud",
174
+ "incident": "shai-hulud",
175
+ "safe": "11.1.5",
176
+ "ref": "https://www.sonatype.com/blog/mini-shai-hulud-npm-attack-more-than-2200-components-impacted"
177
+ },
178
+ {
179
+ "ecosystem": "npm",
180
+ "name": "@cacheable/utils",
181
+ "versions": [
182
+ "2.5.1"
183
+ ],
184
+ "campaign": "mini-shai-hulud",
185
+ "incident": "shai-hulud",
186
+ "safe": "the release before the listed version (see advisory)",
187
+ "ref": "https://www.sonatype.com/blog/mini-shai-hulud-npm-attack-more-than-2200-components-impacted"
188
+ },
189
+ {
190
+ "ecosystem": "npm",
191
+ "name": "@cacheable/memory",
192
+ "versions": [
193
+ "2.2.1"
194
+ ],
195
+ "campaign": "mini-shai-hulud",
196
+ "incident": "shai-hulud",
197
+ "safe": "the release before the listed version (see advisory)",
198
+ "ref": "https://www.sonatype.com/blog/mini-shai-hulud-npm-attack-more-than-2200-components-impacted"
199
+ },
200
+ {
201
+ "ecosystem": "npm",
202
+ "name": "@cacheable/node-cache",
203
+ "versions": [
204
+ "3.1.2"
205
+ ],
206
+ "campaign": "mini-shai-hulud",
207
+ "incident": "shai-hulud",
208
+ "safe": "the release before the listed version (see advisory)",
209
+ "ref": "https://www.sonatype.com/blog/mini-shai-hulud-npm-attack-more-than-2200-components-impacted"
210
+ },
211
+ {
212
+ "ecosystem": "npm",
213
+ "name": "@cacheable/net",
214
+ "versions": [
215
+ "2.1.1"
216
+ ],
217
+ "campaign": "mini-shai-hulud",
218
+ "incident": "shai-hulud",
219
+ "safe": "the release before the listed version (see advisory)",
220
+ "ref": "https://www.sonatype.com/blog/mini-shai-hulud-npm-attack-more-than-2200-components-impacted"
221
+ }
222
+ ],
223
+ "markers": {
224
+ "ips": [
225
+ "193.32.204.199"
226
+ ],
227
+ "domains": [
228
+ "iseekaigogo.com",
229
+ "ci-artifacts.dev",
230
+ "npm-cache.com",
231
+ "my-github.com"
232
+ ],
233
+ "files": [
234
+ "/tmp/tmp.ts018051808.lock"
235
+ ],
236
+ "cron": [
237
+ "#ghc2",
238
+ "193.32.204.199"
239
+ ],
240
+ "processes": [
241
+ "manifest-cache.js --warm",
242
+ "gh-token-monitor"
243
+ ],
244
+ "branches": [
245
+ "dependabot/github_actions/format/setup-formatter"
246
+ ],
247
+ "optionalDependencies": [
248
+ "@opensearch/setup"
249
+ ]
250
+ }
251
+ }
package/src/sarif.js ADDED
@@ -0,0 +1,37 @@
1
+ const LEVEL = { critical: 'error', high: 'error', medium: 'warning', low: 'note' };
2
+ const SCORE = { critical: '9.5', high: '7.5', medium: '5.0', low: '2.0' };
3
+
4
+ import { relative, isAbsolute } from 'node:path';
5
+
6
+ function repoRelative(result, loc) {
7
+ const abs = loc.startsWith('~') ? result.home + loc.slice(1) : loc;
8
+ if (!isAbsolute(abs)) return null;
9
+ for (const p of result.projects) {
10
+ const r = relative(p, abs);
11
+ if (r && !r.startsWith('..') && !isAbsolute(r)) return r.replace(/\\/g, '/');
12
+ }
13
+ return null;
14
+ }
15
+
16
+ export function toSarif(result, version) {
17
+ const rules = new Map();
18
+ for (const f of result.findings) if (!rules.has(f.id)) rules.set(f.id, f);
19
+ return {
20
+ $schema: 'https://json.schemastore.org/sarif-2.1.0.json',
21
+ version: '2.1.0',
22
+ runs: [{
23
+ tool: { driver: { name: 'secret-blast-radius', version, informationUri: 'https://github.com/Krrishkumar125/secret-blast-radius',
24
+ rules: [...rules.values()].map((f) => ({ id: f.id, name: f.id.replace(/[^a-z0-9]+/gi, '_'), shortDescription: { text: f.id }, properties: { 'security-severity': SCORE[f.severity], tags: ['security', f.category] } })) } },
25
+ results: result.findings.map((f) => {
26
+ // Only repo-relative paths are meaningful to code scanning; home-dir findings are reported without a file.
27
+ const uri = repoRelative(result, f.location);
28
+ return {
29
+ ruleId: f.id, level: LEVEL[f.severity],
30
+ message: { text: `${f.title}. ${f.detail}` },
31
+ ...(uri ? { locations: [{ physicalLocation: { artifactLocation: { uri, uriBaseId: '%SRCROOT%' } } }] } : {}),
32
+ partialFingerprints: { primary: `${f.id}:${f.location}:${f.fingerprint || f.title}` },
33
+ };
34
+ }),
35
+ }],
36
+ };
37
+ }
package/src/scanners.js CHANGED
@@ -61,6 +61,17 @@ export function scanNpmrc(ctx) {
61
61
  return out;
62
62
  }
63
63
 
64
+ export function scanPypirc(ctx) {
65
+ const f = join(ctx.home, '.pypirc');
66
+ const t = readText(f);
67
+ if (!t) return [];
68
+ return [...t.matchAll(/^\s*password\s*[=:]\s*(\S+)/gm)].filter((m) => !isReference(m[1])).map((m) => ({
69
+ id: 'pypi.plaintext-token', category: 'npm', severity: m[1].startsWith('pypi-') ? 'critical' : 'high',
70
+ title: 'Plaintext PyPI credential in ~/.pypirc', location: tilde(ctx, f), fingerprint: fingerprint(m[1]),
71
+ detail: 'Lets a stealer publish to your PyPI projects. Revoke at pypi.org/manage/account/token and use trusted publishing.',
72
+ }));
73
+ }
74
+
64
75
  /* ---------------- 2. GitHub ---------------- */
65
76
  export function scanGitHub(ctx) {
66
77
  const out = [];
@@ -287,6 +298,10 @@ export function scanAiConfigs(ctx) {
287
298
  }
288
299
  }
289
300
  }
301
+ for (const [rel, label] of [['.claude/.credentials.json', 'Claude Code login'], ['.gemini/oauth_creds.json', 'Gemini CLI OAuth tokens']]) {
302
+ const f = join(ctx.home, ...rel.split('/'));
303
+ if (readText(f)) out.push({ id: 'ai.cli-login', category: 'ai', severity: 'medium', title: `${label} stored in a file`, location: tilde(ctx, f), detail: 'Read verbatim by the GhostAction fake-font stealer. Sign out and back in to rotate if this machine is exposed.' });
304
+ }
290
305
  // Codex CLI auth file stores an API key / refresh token.
291
306
  for (const f of [join(ctx.home, '.codex', 'auth.json')]) {
292
307
  const t = readText(f);
@@ -362,7 +377,7 @@ export function scanDotenv(ctx) {
362
377
  for (const root of ctx.projects) {
363
378
  for (const f of walk(root, { maxDepth: ctx.depth, skip: SKIP_DIRS })) {
364
379
  const base = f.split(/[\\/]/).pop();
365
- if (!/^\.env(\..+)?$/.test(base) || /\.(example|sample|template|dist|defaults)$/i.test(base)) continue;
380
+ if (!/^\.env(\..+)?$/.test(base) || /\.(example|sample|template|dist|defaults|demo)$/i.test(base)) continue;
366
381
  const text = readText(f);
367
382
  if (!text) continue;
368
383
  const secrets = parseDotenv(text).filter(([k, v]) => isSecretPair(k, v));
@@ -406,7 +421,7 @@ export function scanHardening(ctx) {
406
421
 
407
422
  export const SCANNERS = {
408
423
  persistence: scanPersistence,
409
- npm: scanNpmrc,
424
+ npm: (ctx) => [...scanNpmrc(ctx), ...scanPypirc(ctx)],
410
425
  github: scanGitHub,
411
426
  cloud: scanCloud,
412
427
  kubernetes: scanKubeDocker,