secure-repo 1.0.5 → 1.0.7
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/bin/cli.js +31 -4
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -31,7 +31,7 @@ const DANGER_PATTERNS = [
|
|
|
31
31
|
{ pattern: /sk_live_[a-zA-Z0-9]+/, label: "Stripe live secret key" },
|
|
32
32
|
{ pattern: /sk_test_[a-zA-Z0-9]+/, label: "Stripe test secret key" },
|
|
33
33
|
{ pattern: /eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+/, label: "JWT token" },
|
|
34
|
-
{ pattern: /SUPABASE_SERVICE_ROLE_KEY/, label: "Supabase service role key
|
|
34
|
+
{ pattern: /SUPABASE_SERVICE_ROLE_KEY\s*[:=]\s*['"][^'"]+['"]/, label: "Hardcoded Supabase service role key" },
|
|
35
35
|
{ pattern: /password\s*[:=]\s*['"][^'"]+['"]/, label: "Hardcoded password" },
|
|
36
36
|
{ pattern: /api[_-]?key\s*[:=]\s*['"][^'"]+['"]/, label: "Hardcoded API key" },
|
|
37
37
|
];
|
|
@@ -393,6 +393,19 @@ function audit() {
|
|
|
393
393
|
let issues = 0;
|
|
394
394
|
let warnings = 0;
|
|
395
395
|
let passed = 0;
|
|
396
|
+
let score = 0;
|
|
397
|
+
|
|
398
|
+
// Score weights (total = 100)
|
|
399
|
+
const SCORE_WEIGHTS = {
|
|
400
|
+
policyHigh: 10, // 4 high-severity files × 10 = 40
|
|
401
|
+
policyMedium: 5, // 3 medium-severity files × 5 = 15
|
|
402
|
+
gitignoreEnv: 10, // .env in .gitignore
|
|
403
|
+
noEnvFiles: 10, // no committed .env files
|
|
404
|
+
envExample: 5, // .env.example exists
|
|
405
|
+
noSecrets: 10, // no hardcoded secrets
|
|
406
|
+
noInsecureUrls: 5, // no http:// in env example
|
|
407
|
+
lockFile: 5, // dependency lock file
|
|
408
|
+
};
|
|
396
409
|
|
|
397
410
|
// --- Check for recommended files ---
|
|
398
411
|
console.log(" Policy files:");
|
|
@@ -401,6 +414,7 @@ function audit() {
|
|
|
401
414
|
if (fs.existsSync(filePath)) {
|
|
402
415
|
console.log(` [pass] ${file}`);
|
|
403
416
|
passed++;
|
|
417
|
+
score += severity === "high" ? SCORE_WEIGHTS.policyHigh : SCORE_WEIGHTS.policyMedium;
|
|
404
418
|
} else if (severity === "high") {
|
|
405
419
|
console.log(` [FAIL] ${file} — missing (high priority)`);
|
|
406
420
|
issues++;
|
|
@@ -418,6 +432,7 @@ function audit() {
|
|
|
418
432
|
if (gitignore.includes(".env")) {
|
|
419
433
|
console.log(" [pass] .env is in .gitignore");
|
|
420
434
|
passed++;
|
|
435
|
+
score += SCORE_WEIGHTS.gitignoreEnv;
|
|
421
436
|
} else {
|
|
422
437
|
console.log(" [FAIL] .env is NOT in .gitignore");
|
|
423
438
|
issues++;
|
|
@@ -429,19 +444,25 @@ function audit() {
|
|
|
429
444
|
|
|
430
445
|
// --- Check for committed .env files ---
|
|
431
446
|
const envFiles = [".env", ".env.local", ".env.production"];
|
|
447
|
+
let envFilesFound = 0;
|
|
432
448
|
envFiles.forEach((envFile) => {
|
|
433
449
|
const envPath = path.join(targetDir, envFile);
|
|
434
450
|
if (fs.existsSync(envPath)) {
|
|
435
451
|
console.log(` [FAIL] ${envFile} exists in repo — may contain secrets`);
|
|
436
452
|
issues++;
|
|
453
|
+
envFilesFound++;
|
|
437
454
|
}
|
|
438
455
|
});
|
|
456
|
+
if (envFilesFound === 0) {
|
|
457
|
+
score += SCORE_WEIGHTS.noEnvFiles;
|
|
458
|
+
}
|
|
439
459
|
|
|
440
460
|
// --- Check for .env.example ---
|
|
441
461
|
const envExamplePath = path.join(targetDir, ".env.example");
|
|
442
462
|
if (fs.existsSync(envExamplePath)) {
|
|
443
463
|
console.log(" [pass] .env.example exists");
|
|
444
464
|
passed++;
|
|
465
|
+
score += SCORE_WEIGHTS.envExample;
|
|
445
466
|
} else {
|
|
446
467
|
console.log(" [warn] .env.example missing — document required env vars");
|
|
447
468
|
warnings++;
|
|
@@ -487,6 +508,7 @@ function audit() {
|
|
|
487
508
|
if (secretsFound === 0) {
|
|
488
509
|
console.log(" [pass] No obvious secrets found in source files");
|
|
489
510
|
passed++;
|
|
511
|
+
score += SCORE_WEIGHTS.noSecrets;
|
|
490
512
|
}
|
|
491
513
|
|
|
492
514
|
// --- Check for HTTPS enforcement (look for http:// in env example) ---
|
|
@@ -499,6 +521,7 @@ function audit() {
|
|
|
499
521
|
} else {
|
|
500
522
|
console.log(" [pass] No insecure URLs in .env.example");
|
|
501
523
|
passed++;
|
|
524
|
+
score += SCORE_WEIGHTS.noInsecureUrls;
|
|
502
525
|
}
|
|
503
526
|
}
|
|
504
527
|
|
|
@@ -508,15 +531,19 @@ function audit() {
|
|
|
508
531
|
if (hasLockFile) {
|
|
509
532
|
console.log(" [pass] Dependency lock file exists");
|
|
510
533
|
passed++;
|
|
534
|
+
score += SCORE_WEIGHTS.lockFile;
|
|
511
535
|
} else if (fs.existsSync(path.join(targetDir, "package.json"))) {
|
|
512
536
|
console.log(" [warn] No lock file found — pin your dependencies");
|
|
513
537
|
warnings++;
|
|
514
538
|
}
|
|
515
539
|
|
|
540
|
+
// --- Security Score ---
|
|
541
|
+
console.log("\n ════════════════════════════════════");
|
|
542
|
+
console.log(` Security Score: ${score} / 100`);
|
|
543
|
+
console.log(" ════════════════════════════════════");
|
|
544
|
+
|
|
516
545
|
// --- Summary ---
|
|
517
|
-
console.log(
|
|
518
|
-
console.log(` Results: ${passed} passed, ${warnings} warnings, ${issues} issues`);
|
|
519
|
-
console.log(" ────────────────────────────────────");
|
|
546
|
+
console.log(`\n Results: ${passed} passed, ${warnings} warnings, ${issues} issues`);
|
|
520
547
|
|
|
521
548
|
if (issues > 0) {
|
|
522
549
|
console.log(`\n ${issues} issue(s) found. Fix these before shipping.`);
|
package/package.json
CHANGED