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.
- package/bin/doorman.js +31 -426
- package/bin/getdoorman.js +31 -426
- package/package.json +1 -1
- package/src/rules/bugs/general.js +3 -2
- package/src/rules/compliance/healthcare.js +1 -1
- package/src/rules/compliance/index.js +24 -24
- package/src/rules/data/index.js +26 -26
- package/src/rules/dependencies/index.js +5 -5
- package/src/rules/deployment/index.js +7 -7
- package/src/rules/infrastructure/index.js +28 -28
- package/src/rules/performance/index.js +1 -1
- package/src/rules/reliability/index.js +1 -1
- package/src/rules/security/ai-api.js +1 -0
- package/src/rules/security/auth.js +2 -2
- package/src/rules/security/cors.js +2 -2
- package/src/rules/security/crypto.js +2 -2
- package/src/rules/security/csharp.js +3 -3
- package/src/rules/security/csrf.js +1 -1
- package/src/rules/security/file-upload.js +1 -1
- package/src/rules/security/go.js +3 -3
- package/src/rules/security/misconfiguration.js +4 -4
- package/src/rules/security/oauth-jwt.js +5 -2
- package/src/rules/security/prototype-pollution.js +2 -2
- package/src/rules/security/rate-limiting.js +1 -1
- package/src/rules/security/rust.js +3 -3
- package/src/rules/security/ssrf.js +8 -4
- package/src/rules/security/supply-chain-advanced.js +2 -2
- package/src/rules/security/xss.js +2 -2
- package/src/simple-checks.js +307 -0
- package/src/simple-reporter.js +60 -0
|
@@ -183,7 +183,7 @@ const rules = [
|
|
|
183
183
|
{
|
|
184
184
|
id: 'INFRA-007',
|
|
185
185
|
category: 'infrastructure',
|
|
186
|
-
severity: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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) {
|
|
@@ -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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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 = [];
|
package/src/rules/security/go.js
CHANGED
|
@@ -258,7 +258,7 @@ const rules = [
|
|
|
258
258
|
{
|
|
259
259
|
id: 'SEC-GO-014',
|
|
260
260
|
category: 'security',
|
|
261
|
-
severity: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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
|
|
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])
|
|
115
|
-
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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) {
|