shipready 1.3.0 → 1.3.2
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/dist/checks/secrets.js +22 -3
- package/dist/scanner.js +9 -1
- package/package.json +1 -1
package/dist/checks/secrets.js
CHANGED
|
@@ -196,16 +196,19 @@ const PATTERNS = [
|
|
|
196
196
|
{
|
|
197
197
|
// Placeholder checks run against the password only (group 1), so
|
|
198
198
|
// documentation hosts like db.example.com don't suppress real leaks.
|
|
199
|
+
// The host (group 2) downgrades localhost URLs to medium confidence.
|
|
199
200
|
kind: "Database URL with password",
|
|
200
|
-
re: /\b(?:postgres(?:ql)?|mysql|mongodb(?:\+srv)?|redis|rediss|amqp):\/\/[^:\s"'@/]+:([^@\s"']+)
|
|
201
|
+
re: /\b(?:postgres(?:ql)?|mysql|mongodb(?:\+srv)?|redis|rediss|amqp):\/\/[^:\s"'@/]+:([^@\s"']+)@([^\s"'/:?]+)/,
|
|
201
202
|
confidence: "high",
|
|
202
203
|
group: 1,
|
|
204
|
+
hostGroup: 2,
|
|
203
205
|
},
|
|
204
206
|
{
|
|
205
207
|
kind: "Basic auth in URL",
|
|
206
|
-
re: /https?:\/\/[^:\s"'/@]{3,}:([^@\s"']{8,})
|
|
208
|
+
re: /https?:\/\/[^:\s"'/@]{3,}:([^@\s"']{8,})@([^\s"'/:?]+)/,
|
|
207
209
|
confidence: "medium",
|
|
208
210
|
group: 1,
|
|
211
|
+
hostGroup: 2,
|
|
209
212
|
minEntropy: 3.0,
|
|
210
213
|
},
|
|
211
214
|
{
|
|
@@ -240,6 +243,13 @@ const PLACEHOLDER_VALUE_RE = /your[-_ ]?|example|sample|placeholder|change[-_ ]?
|
|
|
240
243
|
const PLACEHOLDER_LINE_RE = /\b(?:do not commit|for docs only|shipready-ignore)\b|<[A-Z_][A-Z0-9_ -]*>/i;
|
|
241
244
|
/** Paths whose findings are downgraded to medium confidence. */
|
|
242
245
|
const TEST_PATH_RE = /(^|[/\\])(tests?|__tests__|__mocks__|spec|specs|fixtures?|mocks?|examples?|samples?|docs?)([/\\]|$)|\.(test|spec)\.[a-z]+$/i;
|
|
246
|
+
/**
|
|
247
|
+
* Default/dev passwords that appear in scaffolding templates and docker
|
|
248
|
+
* compose files. A URL credential equal to one of these is not a leak.
|
|
249
|
+
*/
|
|
250
|
+
const COMMON_DEV_PASSWORD_RE = /^(?:password|passwd|pass|root|admin|postgres|mysql|mongo|redis|rabbitmq|secret|test|dev|guest|user|toor|changeit|letmein|qwerty)$/i;
|
|
251
|
+
/** Hosts that indicate a local dev database, not a production leak. */
|
|
252
|
+
const LOCAL_HOST_RE = /^(?:localhost|127\.0\.0\.1|0\.0\.0\.0|\[?::1\]?|host\.docker\.internal|db|database|postgres|mysql|mongo|redis)$/i;
|
|
243
253
|
/** True when a matched value looks like a placeholder or templated string. */
|
|
244
254
|
function isPlaceholderValue(value) {
|
|
245
255
|
if (PLACEHOLDER_VALUE_RE.test(value))
|
|
@@ -293,7 +303,16 @@ export function scanContentForSecrets(content, file, allowlist = []) {
|
|
|
293
303
|
if (allowlist.some((a) => match[0].includes(a) || line.includes(a))) {
|
|
294
304
|
continue;
|
|
295
305
|
}
|
|
296
|
-
|
|
306
|
+
let effective = pattern.confidence;
|
|
307
|
+
if (pattern.hostGroup !== undefined) {
|
|
308
|
+
// Scaffolding defaults like root:password@localhost are not leaks.
|
|
309
|
+
if (COMMON_DEV_PASSWORD_RE.test(value))
|
|
310
|
+
continue;
|
|
311
|
+
const host = match[pattern.hostGroup] ?? "";
|
|
312
|
+
if (LOCAL_HOST_RE.test(host))
|
|
313
|
+
effective = "medium";
|
|
314
|
+
}
|
|
315
|
+
const confidence = isTestPath ? "medium" : effective;
|
|
297
316
|
found.push({
|
|
298
317
|
kind: pattern.kind,
|
|
299
318
|
file,
|
package/dist/scanner.js
CHANGED
|
@@ -34,6 +34,12 @@ export function scanFiles(root, files, secretAllowlist = []) {
|
|
|
34
34
|
const envUsages = [];
|
|
35
35
|
const secrets = [];
|
|
36
36
|
const todos = [];
|
|
37
|
+
/**
|
|
38
|
+
* Directories where console.log and friends are intentional (demo code,
|
|
39
|
+
* benchmarks, scripts). Secrets are still scanned there - a leaked key in
|
|
40
|
+
* an example is just as dangerous - but hygiene noise is skipped.
|
|
41
|
+
*/
|
|
42
|
+
const HYGIENE_EXEMPT_RE = /(?:^|\/)(?:examples?|demos?|benchmarks?|scripts?|playground)\//;
|
|
37
43
|
for (const file of files) {
|
|
38
44
|
const base = path.basename(file);
|
|
39
45
|
// Never flag .env files themselves for secrets/todos; they are expected
|
|
@@ -48,7 +54,9 @@ export function scanFiles(root, files, secretAllowlist = []) {
|
|
|
48
54
|
continue;
|
|
49
55
|
if (isCode) {
|
|
50
56
|
envUsages.push(...extractEnvUsages(content, file));
|
|
51
|
-
|
|
57
|
+
if (!HYGIENE_EXEMPT_RE.test(file)) {
|
|
58
|
+
todos.push(...scanContentForTodos(content, file));
|
|
59
|
+
}
|
|
52
60
|
}
|
|
53
61
|
if (!isEnvFile && base !== ".env.example" && base !== ".env.sample") {
|
|
54
62
|
secrets.push(...scanContentForSecrets(content, file, secretAllowlist));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shipready",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "Pre-flight check for your repo before shipping. Scans AI-coded projects for secrets, env issues, debug leftovers, and generates AI-agent instruction files.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|