getdoorman 1.1.0 → 1.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.
@@ -183,7 +183,7 @@ const rules = [
183
183
  {
184
184
  id: 'INFRA-007',
185
185
  category: 'infrastructure',
186
- severity: 'critical',
186
+ severity: 'high',
187
187
  confidence: 'definite',
188
188
  title: 'Sensitive Host Path Mounted in Docker Compose',
189
189
  check({ files }) {
@@ -245,7 +245,7 @@ const rules = [
245
245
  {
246
246
  id: 'INFRA-009',
247
247
  category: 'infrastructure',
248
- severity: 'critical',
248
+ severity: 'high',
249
249
  confidence: 'definite',
250
250
  title: 'Privileged Mode in Docker Compose',
251
251
  check({ files }) {
@@ -296,7 +296,7 @@ const rules = [
296
296
  },
297
297
 
298
298
  // INFRA-DOCKER-001: Secrets in ENV instruction
299
- { id: 'INFRA-DOCKER-001', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'Secrets in Dockerfile ENV Instruction',
299
+ { id: 'INFRA-DOCKER-001', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'Secrets in Dockerfile ENV Instruction',
300
300
  check({ files }) {
301
301
  const findings = [];
302
302
  for (const [fp, c] of files) {
@@ -315,7 +315,7 @@ const rules = [
315
315
  },
316
316
 
317
317
  // INFRA-DOCKER-002: curl|bash pattern
318
- { id: 'INFRA-DOCKER-002', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'Remote Script Execution in Dockerfile',
318
+ { id: 'INFRA-DOCKER-002', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'Remote Script Execution in Dockerfile',
319
319
  check({ files }) {
320
320
  const findings = [];
321
321
  for (const [fp, c] of files) {
@@ -398,7 +398,7 @@ const rules = [
398
398
  },
399
399
 
400
400
  // INFRA-K8S-003: Secrets in ConfigMap
401
- { id: 'INFRA-K8S-003', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'Secrets in Kubernetes ConfigMap',
401
+ { id: 'INFRA-K8S-003', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'Secrets in Kubernetes ConfigMap',
402
402
  check({ files }) {
403
403
  const findings = [];
404
404
  for (const [fp, c] of files) {
@@ -428,7 +428,7 @@ const rules = [
428
428
  },
429
429
 
430
430
  // INFRA-CLOUD-001: SSH open to all IPs
431
- { id: 'INFRA-CLOUD-001', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'SSH Port Open to Internet',
431
+ { id: 'INFRA-CLOUD-001', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'SSH Port Open to Internet',
432
432
  check({ files }) {
433
433
  const findings = [];
434
434
  for (const [fp, c] of files) {
@@ -444,7 +444,7 @@ const rules = [
444
444
  },
445
445
 
446
446
  // INFRA-CLOUD-002: Database publicly accessible
447
- { id: 'INFRA-CLOUD-002', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'Database Publicly Accessible',
447
+ { id: 'INFRA-CLOUD-002', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'Database Publicly Accessible',
448
448
  check({ files }) {
449
449
  const findings = [];
450
450
  for (const [fp, c] of files) {
@@ -460,7 +460,7 @@ const rules = [
460
460
  },
461
461
 
462
462
  // INFRA-CLOUD-003: Hardcoded creds in Terraform
463
- { id: 'INFRA-CLOUD-003', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'Hardcoded Credentials in Terraform',
463
+ { id: 'INFRA-CLOUD-003', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'Hardcoded Credentials in Terraform',
464
464
  check({ files }) {
465
465
  const findings = [];
466
466
  for (const [fp, c] of files) {
@@ -493,7 +493,7 @@ const rules = [
493
493
  },
494
494
 
495
495
  // INFRA-CLOUD-005: IAM admin policy
496
- { id: 'INFRA-CLOUD-005', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'IAM Policy Grants Full Admin Access',
496
+ { id: 'INFRA-CLOUD-005', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'IAM Policy Grants Full Admin Access',
497
497
  check({ files }) {
498
498
  const findings = [];
499
499
  for (const [fp, c] of files) {
@@ -572,7 +572,7 @@ const rules = [
572
572
  },
573
573
 
574
574
  // INFRA-K8S-010: Privileged container
575
- { id: 'INFRA-K8S-010', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'Kubernetes Privileged Container',
575
+ { id: 'INFRA-K8S-010', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'Kubernetes Privileged Container',
576
576
  check({ files }) {
577
577
  const findings = [];
578
578
  for (const [fp, c] of files) {
@@ -837,7 +837,7 @@ const rules = [
837
837
  },
838
838
 
839
839
  // INFRA-CLOUD-011: RDS instance publicly accessible
840
- { id: 'INFRA-CLOUD-011', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'RDS Instance Publicly Accessible',
840
+ { id: 'INFRA-CLOUD-011', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'RDS Instance Publicly Accessible',
841
841
  check({ files }) {
842
842
  const findings = [];
843
843
  for (const [fp, c] of files) {
@@ -1274,7 +1274,7 @@ const rules = [
1274
1274
  },
1275
1275
  },
1276
1276
  // INFRA-TF-009: terraform.tfvars with secrets committed
1277
- { id: 'INFRA-TF-009', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'Terraform Variables File With Secrets',
1277
+ { id: 'INFRA-TF-009', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'Terraform Variables File With Secrets',
1278
1278
  check({ files }) {
1279
1279
  const findings = [];
1280
1280
  for (const [fp, c] of files) {
@@ -1290,7 +1290,7 @@ const rules = [
1290
1290
  },
1291
1291
  },
1292
1292
  // INFRA-NET-004: Security group ingress from 0.0.0.0 on database port
1293
- { id: 'INFRA-NET-004', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'Database Port Open to Internet',
1293
+ { id: 'INFRA-NET-004', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'Database Port Open to Internet',
1294
1294
  check({ files }) {
1295
1295
  const findings = [];
1296
1296
  for (const [fp, c] of files) {
@@ -1516,7 +1516,7 @@ const rules = [
1516
1516
  },
1517
1517
  },
1518
1518
  // INFRA-NET-006: Security group allows unrestricted database port
1519
- { id: 'INFRA-NET-006', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'Security Group Exposes Database Port Publicly',
1519
+ { id: 'INFRA-NET-006', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'Security Group Exposes Database Port Publicly',
1520
1520
  check({ files }) {
1521
1521
  const findings = [];
1522
1522
  for (const [fp, c] of files) {
@@ -1595,7 +1595,7 @@ const rules = [
1595
1595
  },
1596
1596
  },
1597
1597
  // INFRA-CLOUD-033: IAM role with AdministratorAccess
1598
- { id: 'INFRA-CLOUD-033', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'IAM Role with AdministratorAccess Policy',
1598
+ { id: 'INFRA-CLOUD-033', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'IAM Role with AdministratorAccess Policy',
1599
1599
  check({ files }) {
1600
1600
  const findings = [];
1601
1601
  for (const [fp, c] of files) {
@@ -1758,7 +1758,7 @@ rules.push({
1758
1758
 
1759
1759
  // INFRA-K8S-028: Privileged container
1760
1760
  rules.push({
1761
- id: 'INFRA-K8S-028', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'Kubernetes container running as privileged',
1761
+ id: 'INFRA-K8S-028', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'Kubernetes container running as privileged',
1762
1762
  check({ files }) {
1763
1763
  const findings = [];
1764
1764
  for (const [fp, c] of files) {
@@ -1832,7 +1832,7 @@ rules.push({
1832
1832
 
1833
1833
  // INFRA-DC-027: Secrets in Docker Compose environment
1834
1834
  rules.push({
1835
- id: 'INFRA-DC-027', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'Hardcoded secret in Docker Compose environment section',
1835
+ id: 'INFRA-DC-027', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'Hardcoded secret in Docker Compose environment section',
1836
1836
  check({ files }) {
1837
1837
  const findings = [];
1838
1838
  for (const [fp, c] of files) {
@@ -1897,7 +1897,7 @@ rules.push({
1897
1897
 
1898
1898
  // INFRA-TF-028: Open security group (0.0.0.0/0 ingress)
1899
1899
  rules.push({
1900
- id: 'INFRA-TF-028', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'Terraform security group with unrestricted ingress (0.0.0.0/0)',
1900
+ id: 'INFRA-TF-028', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'Terraform security group with unrestricted ingress (0.0.0.0/0)',
1901
1901
  check({ files }) {
1902
1902
  const findings = [];
1903
1903
  for (const [fp, c] of files) {
@@ -1962,7 +1962,7 @@ rules.push({
1962
1962
 
1963
1963
  // INFRA-K8S-033: Sensitive hostPath mount
1964
1964
  rules.push({
1965
- id: 'INFRA-K8S-033', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'Kubernetes pod mounts sensitive host path',
1965
+ id: 'INFRA-K8S-033', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'Kubernetes pod mounts sensitive host path',
1966
1966
  check({ files }) {
1967
1967
  const findings = [];
1968
1968
  for (const [fp, c] of files) {
@@ -2101,7 +2101,7 @@ rules.push({
2101
2101
 
2102
2102
  // INFRA-TF-036: RDS not in private subnet
2103
2103
  rules.push({
2104
- id: 'INFRA-TF-036', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'RDS instance publicly accessible',
2104
+ id: 'INFRA-TF-036', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'RDS instance publicly accessible',
2105
2105
  check({ files }) {
2106
2106
  const findings = [];
2107
2107
  for (const [fp, c] of files) {
@@ -2178,7 +2178,7 @@ rules.push({
2178
2178
 
2179
2179
  // INFRA-K8S-037: ConfigMap used for secrets
2180
2180
  rules.push({
2181
- id: 'INFRA-K8S-037', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'Kubernetes ConfigMap storing secret values',
2181
+ id: 'INFRA-K8S-037', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'Kubernetes ConfigMap storing secret values',
2182
2182
  check({ files }) {
2183
2183
  const findings = [];
2184
2184
  for (const [fp, c] of files) {
@@ -2212,7 +2212,7 @@ rules.push({
2212
2212
 
2213
2213
  // INFRA-TF-040: AWS account root user access key
2214
2214
  rules.push({
2215
- id: 'INFRA-TF-040', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'AWS root account access key configured',
2215
+ id: 'INFRA-TF-040', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'AWS root account access key configured',
2216
2216
  check({ files }) {
2217
2217
  const findings = [];
2218
2218
  for (const [fp, c] of files) {
@@ -2307,7 +2307,7 @@ rules.push({
2307
2307
 
2308
2308
  // INFRA-K8S-040: Container with all capabilities
2309
2309
  rules.push({
2310
- id: 'INFRA-K8S-040', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'Kubernetes container with all capabilities added',
2310
+ id: 'INFRA-K8S-040', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'Kubernetes container with all capabilities added',
2311
2311
  check({ files }) {
2312
2312
  const findings = [];
2313
2313
  for (const [fp, c] of files) {
@@ -2474,7 +2474,7 @@ rules.push({
2474
2474
 
2475
2475
  // INFRA-K8S-044: Service account with cluster-admin role
2476
2476
  rules.push({
2477
- id: 'INFRA-K8S-044', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'Kubernetes service account bound to cluster-admin role',
2477
+ id: 'INFRA-K8S-044', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'Kubernetes service account bound to cluster-admin role',
2478
2478
  check({ files }) {
2479
2479
  const findings = [];
2480
2480
  for (const [fp, c] of files) {
@@ -2576,7 +2576,7 @@ rules.push({
2576
2576
 
2577
2577
  // INFRA-057: Kubernetes container running as privileged
2578
2578
  rules.push({
2579
- id: 'INFRA-057', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'Kubernetes privileged container',
2579
+ id: 'INFRA-057', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'Kubernetes privileged container',
2580
2580
  check({ files }) {
2581
2581
  const findings = [];
2582
2582
  for (const [fp, c] of files) {
@@ -2692,7 +2692,7 @@ rules.push({
2692
2692
 
2693
2693
  // INFRA-066: Database publicly accessible
2694
2694
  rules.push({
2695
- id: 'INFRA-066', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'RDS instance publicly accessible',
2695
+ id: 'INFRA-066', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'RDS instance publicly accessible',
2696
2696
  check({ files }) {
2697
2697
  const findings = [];
2698
2698
  for (const [fp, c] of files) {
@@ -2717,7 +2717,7 @@ rules.push({
2717
2717
 
2718
2718
  // INFRA-068: Security group with 0.0.0.0/0 SSH
2719
2719
  rules.push({
2720
- id: 'INFRA-068', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'SSH open to the world',
2720
+ id: 'INFRA-068', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'SSH open to the world',
2721
2721
  check({ files }) {
2722
2722
  const findings = [];
2723
2723
  for (const [fp, c] of files) {
@@ -2857,7 +2857,7 @@ rules.push({
2857
2857
 
2858
2858
  // INFRA-079: Docker socket mounted
2859
2859
  rules.push({
2860
- id: 'INFRA-079', category: 'infrastructure', severity: 'critical', confidence: 'definite', title: 'Docker socket mounted in container',
2860
+ id: 'INFRA-079', category: 'infrastructure', severity: 'high', confidence: 'definite', title: 'Docker socket mounted in container',
2861
2861
  check({ files }) {
2862
2862
  const findings = [];
2863
2863
  for (const [fp, c] of files) {
@@ -2350,7 +2350,7 @@ const rules = [
2350
2350
  },
2351
2351
  },
2352
2352
  // PERF-CACHE-010: Redis KEYS command in production
2353
- { id: 'PERF-CACHE-010', category: 'performance', severity: 'critical', confidence: 'definite', title: 'Redis KEYS Command Used in Production',
2353
+ { id: 'PERF-CACHE-010', category: 'performance', severity: 'high', confidence: 'definite', title: 'Redis KEYS Command Used in Production',
2354
2354
  check({ files }) {
2355
2355
  const findings = [];
2356
2356
  for (const [fp, c] of files) {
@@ -683,7 +683,7 @@ const rules = [
683
683
  {
684
684
  id: 'REL-RES-001',
685
685
  category: 'reliability',
686
- severity: 'critical',
686
+ severity: 'high',
687
687
  confidence: 'definite',
688
688
  title: 'Payment API Call Without Idempotency Key',
689
689
  check({ files }) {
@@ -329,6 +329,7 @@ const rules = [
329
329
  for (const [path, content] of files) {
330
330
  if (SKIP_PATH.test(path)) continue;
331
331
  if (!path.endsWith('.env') && !path.match(/\.env\.\w+$/)) continue;
332
+ if (/\.env\.(example|sample|template|defaults|dev\.example)$/i.test(path)) continue;
332
333
  findings.push(...scanLines(content, envKeyPattern, path, this));
333
334
  }
334
335
  return findings;
@@ -309,7 +309,7 @@ const rules = [
309
309
  {
310
310
  id: 'SEC-AUTH-007',
311
311
  category: 'security',
312
- severity: 'critical',
312
+ severity: 'high',
313
313
  confidence: 'suggestion',
314
314
  title: 'API route missing authentication middleware',
315
315
  check({ files }) {
@@ -366,7 +366,7 @@ const rules = [
366
366
  {
367
367
  id: 'SEC-AUTH-008',
368
368
  category: 'security',
369
- severity: 'critical',
369
+ severity: 'high',
370
370
  confidence: 'suggestion',
371
371
  title: 'Admin route missing role/permission check',
372
372
  check({ files }) {
@@ -32,7 +32,7 @@ const rules = [
32
32
 
33
33
  // SEC-CORS-002
34
34
  {
35
- id: 'SEC-CORS-002', category: 'security', severity: 'critical', confidence: 'definite',
35
+ id: 'SEC-CORS-002', category: 'security', severity: 'high', confidence: 'definite',
36
36
  title: 'CORS reflects Origin header',
37
37
  check({ files }) {
38
38
  const findings = [];
@@ -56,7 +56,7 @@ const rules = [
56
56
 
57
57
  // SEC-CORS-003
58
58
  {
59
- id: 'SEC-CORS-003', category: 'security', severity: 'critical', confidence: 'definite',
59
+ id: 'SEC-CORS-003', category: 'security', severity: 'high', confidence: 'definite',
60
60
  title: 'CORS allows credentials with wildcard origin',
61
61
  check({ files }) {
62
62
  const findings = [];
@@ -259,7 +259,7 @@ export default rules;
259
259
 
260
260
  // SEC-CRY-011: Hardcoded encryption key
261
261
  rules.push({
262
- id: 'SEC-CRY-011', category: 'security', severity: 'critical', confidence: 'definite',
262
+ id: 'SEC-CRY-011', category: 'security', severity: 'high', confidence: 'definite',
263
263
  title: 'Hardcoded encryption key or IV',
264
264
  check({ files }) {
265
265
  const findings = [];
@@ -467,7 +467,7 @@ rules.push({
467
467
 
468
468
  // SEC-CRY-021: Hardcoded salt
469
469
  rules.push({
470
- id: 'SEC-CRY-021', category: 'security', severity: 'critical', confidence: 'definite',
470
+ id: 'SEC-CRY-021', category: 'security', severity: 'high', confidence: 'definite',
471
471
  title: 'Hardcoded salt for password hashing',
472
472
  check({ files }) {
473
473
  const findings = [];
@@ -132,7 +132,7 @@ const rules = [
132
132
  {
133
133
  id: 'SEC-CS-006',
134
134
  category: 'security',
135
- severity: 'critical',
135
+ severity: 'high',
136
136
  confidence: 'definite',
137
137
  title: 'Insecure Deserialization: BinaryFormatter',
138
138
  description: 'BinaryFormatter is inherently insecure and can execute arbitrary code during deserialization.',
@@ -603,7 +603,7 @@ const rules = [
603
603
  {
604
604
  id: 'SEC-CS-035',
605
605
  category: 'security',
606
- severity: 'critical',
606
+ severity: 'high',
607
607
  confidence: 'definite',
608
608
  title: 'CORS: Credentials with Any Origin',
609
609
  description: 'AllowCredentials with AllowAnyOrigin is a severe misconfiguration.',
@@ -731,7 +731,7 @@ const rules = [
731
731
  {
732
732
  id: 'SEC-CS-043',
733
733
  category: 'security',
734
- severity: 'critical',
734
+ severity: 'high',
735
735
  confidence: 'definite',
736
736
  title: 'TLS Certificate Validation Disabled',
737
737
  description: 'Disabling certificate validation allows man-in-the-middle attacks.',
@@ -34,7 +34,7 @@ const rules = [
34
34
 
35
35
  // SEC-CSRF-002
36
36
  {
37
- id: 'SEC-CSRF-002', category: 'security', severity: 'critical', confidence: 'definite',
37
+ id: 'SEC-CSRF-002', category: 'security', severity: 'high', confidence: 'definite',
38
38
  title: 'CSRF token not validated on server',
39
39
  check({ files }) {
40
40
  const findings = [];
@@ -95,7 +95,7 @@ const rules = [
95
95
 
96
96
  // SEC-UPL-005
97
97
  {
98
- id: 'SEC-UPL-005', category: 'security', severity: 'critical', confidence: 'definite',
98
+ id: 'SEC-UPL-005', category: 'security', severity: 'high', confidence: 'definite',
99
99
  title: 'Executable file upload allowed',
100
100
  check({ files }) {
101
101
  const findings = [];
@@ -258,7 +258,7 @@ const rules = [
258
258
  {
259
259
  id: 'SEC-GO-014',
260
260
  category: 'security',
261
- severity: 'critical',
261
+ severity: 'high',
262
262
  confidence: 'definite',
263
263
  title: 'Insecure TLS: Certificate Verification Disabled',
264
264
  description: 'Setting InsecureSkipVerify to true disables TLS certificate validation, enabling MITM attacks.',
@@ -450,7 +450,7 @@ const rules = [
450
450
  {
451
451
  id: 'SEC-GO-026',
452
452
  category: 'security',
453
- severity: 'critical',
453
+ severity: 'high',
454
454
  confidence: 'definite',
455
455
  title: 'CORS Allow Credentials with Wildcard Origin',
456
456
  description: 'Allowing credentials with wildcard origin is a severe misconfiguration enabling credential theft.',
@@ -482,7 +482,7 @@ const rules = [
482
482
  {
483
483
  id: 'SEC-GO-028',
484
484
  category: 'security',
485
- severity: 'critical',
485
+ severity: 'high',
486
486
  confidence: 'definite',
487
487
  title: 'JWT None Algorithm Accepted',
488
488
  description: 'Not validating the JWT signing method allows attackers to use the "none" algorithm to forge tokens.',
@@ -59,7 +59,7 @@ const rules = [
59
59
  {
60
60
  id: 'SEC-MISC-001',
61
61
  category: 'security',
62
- severity: 'critical',
62
+ severity: 'high',
63
63
  confidence: 'definite',
64
64
  title: 'Public S3 bucket configuration detected',
65
65
  check({ files }) {
@@ -82,7 +82,7 @@ const rules = [
82
82
  {
83
83
  id: 'SEC-MISC-002',
84
84
  category: 'security',
85
- severity: 'critical',
85
+ severity: 'high',
86
86
  confidence: 'definite',
87
87
  title: 'Database bound to all network interfaces',
88
88
  check({ files }) {
@@ -268,7 +268,7 @@ const rules = [
268
268
  {
269
269
  id: 'SEC-MISC-007',
270
270
  category: 'security',
271
- severity: 'critical',
271
+ severity: 'high',
272
272
  confidence: 'definite',
273
273
  title: 'Permissive database security rules',
274
274
  check({ files }) {
@@ -592,7 +592,7 @@ const rules = [
592
592
  {
593
593
  id: 'SEC-MISC-015',
594
594
  category: 'security',
595
- severity: 'critical',
595
+ severity: 'high',
596
596
  confidence: 'definite',
597
597
  title: 'Overly permissive IAM policy detected',
598
598
  check({ files }) {
@@ -39,7 +39,7 @@ const rules = [
39
39
  {
40
40
  id: 'SEC-JWT-001',
41
41
  category: 'security',
42
- severity: 'critical',
42
+ severity: 'high',
43
43
  confidence: 'definite',
44
44
  title: 'JWT Algorithm "none" Allowed',
45
45
  description:
@@ -108,7 +108,7 @@ const rules = [
108
108
  {
109
109
  id: 'SEC-JWT-004',
110
110
  category: 'security',
111
- severity: 'critical',
111
+ severity: 'high',
112
112
  confidence: 'definite',
113
113
  title: 'Weak JWT Signing Secret',
114
114
  description:
@@ -241,10 +241,13 @@ const rules = [
241
241
  const findings = [];
242
242
  const callbackPattern = /(?:\/callback|\/oauth\/callback|\/auth\/callback)/;
243
243
  const tokenExchange = /(?:getToken|requestToken|exchangeCode|code.*token|grant_type.*authorization_code)/;
244
+ // Check if ANY file in the project validates OAuth state (cross-file check)
245
+ const projectHasStateValidation = [...files.values()].some(c => /(?:state|csrf|nonce).*(?:verify|validate|check|compare|match|===)/i.test(c));
244
246
  for (const [path, content] of files) {
245
247
  if (SKIP_PATH.test(path)) continue;
246
248
  if (!isJS(path)) continue;
247
249
  if (callbackPattern.test(content) && tokenExchange.test(content)) {
250
+ if (projectHasStateValidation) continue; // State is validated somewhere in the project
248
251
  if (!/(?:state|csrf|nonce)/.test(content)) {
249
252
  findings.push({
250
253
  ruleId: this.id,
@@ -39,7 +39,7 @@ const rules = [
39
39
  {
40
40
  id: 'SEC-PP-001',
41
41
  category: 'security',
42
- severity: 'critical',
42
+ severity: 'high',
43
43
  confidence: 'definite',
44
44
  title: 'Direct __proto__ Property Access',
45
45
  description:
@@ -108,7 +108,7 @@ const rules = [
108
108
  {
109
109
  id: 'SEC-PP-004',
110
110
  category: 'security',
111
- severity: 'critical',
111
+ severity: 'high',
112
112
  confidence: 'definite',
113
113
  title: 'Constructor Prototype Access Pattern',
114
114
  description:
@@ -30,7 +30,7 @@ const rules = [
30
30
 
31
31
  // SEC-RL-002
32
32
  {
33
- id: 'SEC-RL-002', category: 'security', severity: 'critical', confidence: 'definite',
33
+ id: 'SEC-RL-002', category: 'security', severity: 'high', confidence: 'definite',
34
34
  title: 'No rate limiting on login endpoint',
35
35
  check({ files, stack }) {
36
36
  const findings = [];
@@ -274,7 +274,7 @@ const rules = [
274
274
  {
275
275
  id: 'SEC-RS-015',
276
276
  category: 'security',
277
- severity: 'critical',
277
+ severity: 'high',
278
278
  confidence: 'definite',
279
279
  title: 'TLS Certificate Validation Disabled',
280
280
  description: 'Disabling TLS certificate validation allows man-in-the-middle attacks.',
@@ -290,7 +290,7 @@ const rules = [
290
290
  {
291
291
  id: 'SEC-RS-016',
292
292
  category: 'security',
293
- severity: 'critical',
293
+ severity: 'high',
294
294
  confidence: 'definite',
295
295
  title: 'TLS Hostname Validation Disabled',
296
296
  description: 'Disabling hostname validation in TLS allows certificate substitution attacks.',
@@ -549,7 +549,7 @@ const rules = [
549
549
  {
550
550
  id: 'SEC-RS-032',
551
551
  category: 'security',
552
- severity: 'critical',
552
+ severity: 'high',
553
553
  confidence: 'definite',
554
554
  title: 'Hardcoded Private Key',
555
555
  description: 'Private keys embedded in source code can be extracted and used to impersonate the service.',
@@ -96,7 +96,7 @@ const rules = [
96
96
  {
97
97
  id: 'SEC-SSRF-003',
98
98
  category: 'security',
99
- severity: 'critical',
99
+ severity: 'high',
100
100
  confidence: 'definite',
101
101
  title: 'Cloud Metadata Endpoint URL in Code',
102
102
  description:
@@ -105,14 +105,18 @@ const rules = [
105
105
  check({ files }) {
106
106
  const findings = [];
107
107
  const pattern = /169\.254\.169\.254|metadata\.google\.internal|metadata\.azure\.com/;
108
- const blocklistContext = /block|deny|forbidden|not.?allowed|invalid|reject|blacklist|safelist|denylist|disallow|banned|BLOCKED/i;
108
+ const safeContext = /block|deny|forbidden|not.?allowed|invalid|reject|blacklist|safelist|denylist|disallow|banned|BLOCKED|isAllowed|validate|security|guard|check|filter|protect/i;
109
109
  for (const [path, content] of files) {
110
110
  if (SKIP_PATH.test(path)) continue;
111
111
  if (isJS(path)) {
112
112
  const lines = content.split('\n');
113
113
  for (let i = 0; i < lines.length; i++) {
114
- if (pattern.test(lines[i]) && !blocklistContext.test(lines[i])) {
115
- findings.push({ ruleId: this.id, category: this.category, severity: this.severity, title: this.title, description: this.description, confidence: this.confidence, file: path, line: i + 1, fix: this.fix });
114
+ if (pattern.test(lines[i])) {
115
+ // Check ±5 lines for security/validation context
116
+ const ctx = lines.slice(Math.max(0, i - 5), i + 5).join(' ');
117
+ if (!safeContext.test(ctx)) {
118
+ findings.push({ ruleId: this.id, category: this.category, severity: this.severity, title: this.title, description: this.description, confidence: this.confidence, file: path, line: i + 1, fix: this.fix });
119
+ }
116
120
  }
117
121
  }
118
122
  }
@@ -40,7 +40,7 @@ const rules = [
40
40
  {
41
41
  id: 'SEC-SCA-001',
42
42
  category: 'security',
43
- severity: 'critical',
43
+ severity: 'high',
44
44
  confidence: 'definite',
45
45
  title: 'Postinstall Script Executes Binary or Shell Command',
46
46
  description:
@@ -77,7 +77,7 @@ const rules = [
77
77
  {
78
78
  id: 'SEC-SCA-002',
79
79
  category: 'security',
80
- severity: 'critical',
80
+ severity: 'high',
81
81
  confidence: 'definite',
82
82
  title: 'Install Hook Downloads and Executes Remote Code',
83
83
  description:
@@ -230,7 +230,7 @@ const rules = [
230
230
  {
231
231
  id: 'SEC-XSS-007',
232
232
  category: 'security',
233
- severity: 'critical',
233
+ severity: 'high',
234
234
  confidence: 'definite',
235
235
  title: 'javascript: protocol in href/src attributes',
236
236
  check({ files }) {
@@ -498,7 +498,7 @@ const rules = [
498
498
  },
499
499
  },
500
500
  // SEC-XSS-013: Server-side reflected XSS via res.send/res.write
501
- { id: 'SEC-XSS-013', category: 'security', severity: 'critical', confidence: 'definite', title: 'Server-Side Reflected XSS via res.send()',
501
+ { id: 'SEC-XSS-013', category: 'security', severity: 'high', confidence: 'definite', title: 'Server-Side Reflected XSS via res.send()',
502
502
  check({ files }) {
503
503
  const findings = [];
504
504
  for (const [fp, c] of files) {