security-mcp 1.1.4 → 1.3.3
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/README.md +341 -1018
- package/defaults/checklists/ai.json +20 -1
- package/defaults/checklists/api.json +35 -1
- package/defaults/checklists/infra.json +34 -1
- package/defaults/checklists/mobile.json +23 -1
- package/defaults/checklists/payments.json +15 -1
- package/defaults/checklists/web.json +11 -1
- package/defaults/cloud-controls/aws.json +10712 -0
- package/defaults/cloud-controls/azure.json +7201 -0
- package/defaults/cloud-controls/gcp.json +4061 -0
- package/defaults/control-catalog.json +24 -0
- package/defaults/security-policy.json +2 -2
- package/dist/ci/pr-gate.js +22 -5
- package/dist/cli/index.js +73 -2
- package/dist/cli/install.js +4 -55
- package/dist/cli/onboarding.js +18 -10
- package/dist/gate/baseline.js +82 -7
- package/dist/gate/catalog.js +10 -2
- package/dist/gate/checks/agentic-instructions.js +515 -0
- package/dist/gate/checks/ai-governance.js +132 -0
- package/dist/gate/checks/ai.js +757 -39
- package/dist/gate/checks/auth-deep.js +920 -216
- package/dist/gate/checks/business-logic.js +751 -0
- package/dist/gate/checks/ci-pipeline.js +399 -4
- package/dist/gate/checks/cloud-controls.js +69 -0
- package/dist/gate/checks/crypto.js +423 -2
- package/dist/gate/checks/data-platform.js +954 -0
- package/dist/gate/checks/dependencies.js +582 -15
- package/dist/gate/checks/docker-deep.js +1236 -0
- package/dist/gate/checks/gitops.js +724 -0
- package/dist/gate/checks/graphql.js +201 -19
- package/dist/gate/checks/iac.js +1230 -0
- package/dist/gate/checks/infra.js +246 -1
- package/dist/gate/checks/injection-deep.js +827 -184
- package/dist/gate/checks/k8s.js +955 -2
- package/dist/gate/checks/mobile-android.js +917 -3
- package/dist/gate/checks/mobile-ios.js +797 -5
- package/dist/gate/checks/required-artifacts.js +194 -0
- package/dist/gate/checks/runtime.js +178 -0
- package/dist/gate/checks/secrets.js +256 -13
- package/dist/gate/checks/supply-chain-deep.js +787 -0
- package/dist/gate/checks/web-nextjs.js +572 -48
- package/dist/gate/cloud-controls/apply.js +115 -0
- package/dist/gate/cloud-controls/bicep.js +36 -0
- package/dist/gate/cloud-controls/cfn.js +125 -0
- package/dist/gate/cloud-controls/detect.js +104 -0
- package/dist/gate/cloud-controls/hcl.js +140 -0
- package/dist/gate/cloud-controls/types.js +87 -0
- package/dist/gate/diff.js +17 -5
- package/dist/gate/evidence.js +8 -1
- package/dist/gate/exceptions.js +202 -9
- package/dist/gate/findings.js +15 -2
- package/dist/gate/policy.js +316 -130
- package/dist/gate/threat-intel.js +6 -0
- package/dist/mcp/audit-chain.js +131 -28
- package/dist/mcp/auth.js +169 -0
- package/dist/mcp/learning.js +129 -4
- package/dist/mcp/model-router.js +161 -24
- package/dist/mcp/orchestration.js +377 -89
- package/dist/mcp/server.js +460 -69
- package/dist/mcp/tool-audit.js +193 -0
- package/dist/repo/fs.js +37 -1
- package/dist/repo/search.js +31 -6
- package/dist/review/store.js +56 -3
- package/dist/tests/run.js +124 -1
- package/package.json +9 -9
- package/skills/_TEMPLATE/SKILL.md +99 -0
- package/skills/advanced-dos-tester/SKILL.md +118 -0
- package/skills/agentic-instruction-auditor/SKILL.md +111 -0
- package/skills/agentic-loop-exploiter/SKILL.md +377 -0
- package/skills/ai-llm-redteam/SKILL.md +113 -0
- package/skills/ai-model-supply-chain-agent/SKILL.md +112 -0
- package/skills/algorithm-implementation-reviewer/SKILL.md +107 -0
- package/skills/android-penetration-tester/SKILL.md +464 -46
- package/skills/anti-replay-tester/SKILL.md +115 -0
- package/skills/appsec-code-auditor/SKILL.md +94 -0
- package/skills/artifact-integrity-analyst/SKILL.md +450 -0
- package/skills/attack-navigator/SKILL.md +476 -8
- package/skills/auth-session-hacker/SKILL.md +111 -0
- package/skills/aws-penetration-tester/SKILL.md +510 -0
- package/skills/azure-penetration-tester/SKILL.md +542 -3
- package/skills/binary-auth-validator/SKILL.md +120 -0
- package/skills/bot-detection-specialist/SKILL.md +118 -0
- package/skills/business-logic-attacker/SKILL.md +240 -0
- package/skills/capec-code-mapper/SKILL.md +93 -0
- package/skills/cert-pin-rotation-specialist/SKILL.md +121 -0
- package/skills/cicd-pipeline-hijacker/SKILL.md +414 -0
- package/skills/ciso-orchestrator/SKILL.md +465 -43
- package/skills/cloud-infra-specialist/SKILL.md +127 -0
- package/skills/compliance-gap-analyst/SKILL.md +431 -0
- package/skills/compliance-grc/SKILL.md +94 -0
- package/skills/compliance-lifecycle-tracker/SKILL.md +93 -0
- package/skills/container-hardening-auditor/SKILL.md +125 -0
- package/skills/credential-stuffing-specialist/SKILL.md +111 -0
- package/skills/crypto-pki-specialist/SKILL.md +96 -0
- package/skills/csa-ccm-mapper/SKILL.md +93 -0
- package/skills/csf2-governance-mapper/SKILL.md +93 -0
- package/skills/data-platform-auditor/SKILL.md +125 -0
- package/skills/deep-link-fuzzer/SKILL.md +118 -0
- package/skills/dependency-confusion-attacker/SKILL.md +424 -0
- package/skills/device-integrity-aggregator/SKILL.md +117 -0
- package/skills/dos-resilience-tester/SKILL.md +106 -0
- package/skills/dread-scorer/SKILL.md +93 -0
- package/skills/egress-policy-enforcer/SKILL.md +108 -0
- package/skills/evidence-collector/SKILL.md +107 -0
- package/skills/file-upload-attacker/SKILL.md +118 -0
- package/skills/gcp-penetration-tester/SKILL.md +510 -2
- package/skills/git-history-secret-scanner/SKILL.md +115 -0
- package/skills/gitops-delivery-auditor/SKILL.md +120 -0
- package/skills/iac-security-auditor/SKILL.md +125 -0
- package/skills/iam-privesc-graph-builder/SKILL.md +161 -0
- package/skills/incident-responder/SKILL.md +120 -0
- package/skills/injection-specialist/SKILL.md +111 -0
- package/skills/ios-security-auditor/SKILL.md +291 -0
- package/skills/json-ambiguity-tester/SKILL.md +145 -0
- package/skills/k8s-container-escaper/SKILL.md +406 -0
- package/skills/key-management-lifecycle-analyst/SKILL.md +107 -0
- package/skills/kill-switch-engineer/SKILL.md +111 -0
- package/skills/linddun-privacy-analyst/SKILL.md +111 -0
- package/skills/logic-race-fuzzer/SKILL.md +452 -0
- package/skills/mobile-api-network-attacker/SKILL.md +430 -0
- package/skills/mobile-binary-hardener/SKILL.md +111 -0
- package/skills/mobile-security-specialist/SKILL.md +94 -0
- package/skills/mobile-webview-auditor/SKILL.md +105 -0
- package/skills/model-extraction-attacker/SKILL.md +228 -0
- package/skills/multipart-abuse-tester/SKILL.md +93 -0
- package/skills/oauth-pkce-specialist/SKILL.md +113 -0
- package/skills/parser-exhaustion-tester/SKILL.md +151 -0
- package/skills/pentest-infra/SKILL.md +107 -0
- package/skills/pentest-social/SKILL.md +210 -0
- package/skills/pentest-team/SKILL.md +96 -0
- package/skills/pentest-web-api/SKILL.md +107 -0
- package/skills/privacy-flow-analyst/SKILL.md +243 -0
- package/skills/prompt-injection-specialist/SKILL.md +403 -0
- package/skills/quantum-migration-planner/SKILL.md +105 -0
- package/skills/rag-poisoning-specialist/SKILL.md +367 -0
- package/skills/registry-mirror-enforcer/SKILL.md +93 -0
- package/skills/rotation-validation-agent/SKILL.md +121 -0
- package/skills/samm-assessor/SKILL.md +94 -0
- package/skills/secrets-mask-bypass-tester/SKILL.md +109 -0
- package/skills/senior-security-engineer/SKILL.md +178 -0
- package/skills/serialization-memory-attacker/SKILL.md +341 -0
- package/skills/session-timeout-tester/SKILL.md +170 -0
- package/skills/slsa-level3-enforcer/SKILL.md +121 -0
- package/skills/slsa-provenance-enforcer/SKILL.md +111 -0
- package/skills/ssrf-detection-validator/SKILL.md +117 -0
- package/skills/step-up-auth-enforcer/SKILL.md +93 -0
- package/skills/stride-pasta-analyst/SKILL.md +429 -0
- package/skills/supply-chain-devsecops/SKILL.md +107 -0
- package/skills/threat-infrastructure-analyst/SKILL.md +93 -0
- package/skills/threat-modeler/SKILL.md +94 -0
- package/skills/tls-certificate-auditor/SKILL.md +582 -18
- package/skills/token-reuse-detector/SKILL.md +104 -0
- package/skills/trike-risk-modeler/SKILL.md +93 -0
- package/skills/unicode-homograph-tester/SKILL.md +93 -0
- package/skills/waf-rule-lifecycle-agent/SKILL.md +106 -0
- package/skills/webhook-security-tester/SKILL.md +111 -0
- package/skills/zero-trust-architect/SKILL.md +118 -0
|
@@ -24,7 +24,7 @@ const IAM_WILDCARD_PATTERN = String.raw `"Action"\s*:\s*"\*"|` + // AWS IAM wild
|
|
|
24
24
|
String.raw `roles/owner|roles/editor|` + // GCP over-privileged built-in roles
|
|
25
25
|
String.raw `allUsers|allAuthenticatedUsers|` + // GCP public IAM
|
|
26
26
|
String.raw `"role"\s*:\s*"roles/owner"|` + // GCP Terraform owner binding
|
|
27
|
-
String.raw
|
|
27
|
+
String.raw `\bContributor\b.*roleDefinitionId|\bOwner\b.*roleDefinitionId`; // Azure Contributor/Owner (word-bounded to avoid matching variable names)
|
|
28
28
|
// Public network exposure — Terraform, K8s, CloudFormation, ARM, CDK
|
|
29
29
|
const PUBLIC_INGRESS_PATTERN = String.raw `0\.0\.0\.0/0|::/0|` +
|
|
30
30
|
String.raw `public\s*=\s*true|` +
|
|
@@ -148,5 +148,250 @@ export async function checkInfra(_) {
|
|
|
148
148
|
]
|
|
149
149
|
});
|
|
150
150
|
}
|
|
151
|
+
// 6–16. Additional cloud-specific checks (all searches run in parallel)
|
|
152
|
+
const [imdsv1Results, lambdaUrlNoAuthResults, ecrNoScanResults, ecsHostNetworkResults, cloudtrailNotMultiregionResults, s3NoAccessLoggingResults, vpcNoFlowLogsResults, assumeRoleResults, externalIdResults, gcpDefaultSaResults, gcpProjectSshResults, gcpExternalIpResults, azurePublicNetworkResults, dbNoDeletionProtectionResults, vpcEndpointResults, awsInfraResults, guarddutyResults, securityHubResults,] = await Promise.all([
|
|
153
|
+
// hop_limit [2-9] misses values >= 10; use \d{2,}|[2-9] to catch all insecure values
|
|
154
|
+
searchRepo({ query: String.raw `http_tokens\s*=\s*"optional"|http_put_response_hop_limit\s*=\s*(?:[2-9]|\d{2,})`, isRegex: true, maxMatches: 200 }),
|
|
155
|
+
searchRepo({ query: String.raw `(?:FunctionUrlAuthType|authorization_type)\s*[=:]\s*"NONE"`, isRegex: true, maxMatches: 200 }),
|
|
156
|
+
searchRepo({ query: String.raw `scan_on_push\s*=\s*false`, isRegex: true, maxMatches: 200 }),
|
|
157
|
+
searchRepo({ query: String.raw `(?:network_mode|networkMode)\s*[=:]\s*"host"`, isRegex: true, maxMatches: 200 }),
|
|
158
|
+
searchRepo({ query: String.raw `is_multi_region_trail\s*=\s*false|"IsMultiRegionTrail"\s*:\s*false`, isRegex: true, maxMatches: 200 }),
|
|
159
|
+
searchRepo({ query: String.raw `"LoggingEnabled"\s*:\s*\{\s*\}|target_bucket\s*=\s*""`, isRegex: true, maxMatches: 200 }),
|
|
160
|
+
// aws_vpc has no enable_flow_log attr; use aws_flow_log resource absence as the signal instead
|
|
161
|
+
searchRepo({ query: String.raw `aws_flow_log`, isRegex: true, maxMatches: 200 }),
|
|
162
|
+
searchRepo({ query: String.raw `"Action"\s*:\s*"sts:AssumeRole"`, isRegex: true, maxMatches: 200 }),
|
|
163
|
+
searchRepo({ query: String.raw `sts:ExternalId`, isRegex: true, maxMatches: 200 }),
|
|
164
|
+
searchRepo({ query: String.raw `-compute@developer\.gserviceaccount\.com`, isRegex: true, maxMatches: 200 }),
|
|
165
|
+
searchRepo({ query: String.raw `"ssh-keys"\s*:`, isRegex: true, maxMatches: 200 }),
|
|
166
|
+
// access_config {} catches only ephemeral IPs; access_config { nat_ip = ... } (static) also exposes external IP
|
|
167
|
+
searchRepo({ query: String.raw `access_config\s*\{`, isRegex: true, maxMatches: 200 }),
|
|
168
|
+
searchRepo({ query: String.raw `public_network_access_enabled\s*=\s*true`, isRegex: true, maxMatches: 200 }),
|
|
169
|
+
searchRepo({ query: String.raw `(?:deletion_protection|enable_deletion_protection)\s*=\s*false`, isRegex: true, maxMatches: 200 }),
|
|
170
|
+
searchRepo({ query: String.raw `aws_vpc_endpoint`, isRegex: true, maxMatches: 200 }),
|
|
171
|
+
searchRepo({ query: String.raw `aws_(?:instance|ecs_service|lambda_function)`, isRegex: true, maxMatches: 200 }),
|
|
172
|
+
searchRepo({ query: String.raw `aws_guardduty_detector`, isRegex: true, maxMatches: 200 }),
|
|
173
|
+
searchRepo({ query: String.raw `aws_securityhub_account`, isRegex: true, maxMatches: 200 }),
|
|
174
|
+
]);
|
|
175
|
+
// 6. IMDSv1 accessible
|
|
176
|
+
if (imdsv1Results.length > 0) {
|
|
177
|
+
findings.push({
|
|
178
|
+
id: "INFRA_IMDSV1_ACCESSIBLE",
|
|
179
|
+
title: "IMDSv1 still accessible on EC2 — SSRF attackers can reach 169.254.169.254 for IAM credentials",
|
|
180
|
+
severity: "CRITICAL",
|
|
181
|
+
evidence: imdsv1Results.slice(0, 20).map((m) => `${m.file}:${m.line}: ${m.preview}`),
|
|
182
|
+
requiredActions: [
|
|
183
|
+
"Set http_tokens = \"required\" on all aws_instance and launch template resources.",
|
|
184
|
+
"Set http_put_response_hop_limit = 1 to prevent hop-based SSRF escalation.",
|
|
185
|
+
"Enforce IMDSv2-only at the AWS account level via EC2 default metadata options."
|
|
186
|
+
]
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
// 7. Lambda URL no auth
|
|
190
|
+
if (lambdaUrlNoAuthResults.length > 0) {
|
|
191
|
+
findings.push({
|
|
192
|
+
id: "INFRA_LAMBDA_URL_NO_AUTH",
|
|
193
|
+
title: "Lambda function URL with no authentication — publicly invocable by anyone",
|
|
194
|
+
severity: "CRITICAL",
|
|
195
|
+
evidence: lambdaUrlNoAuthResults.slice(0, 20).map((m) => `${m.file}:${m.line}: ${m.preview}`),
|
|
196
|
+
requiredActions: [
|
|
197
|
+
"Set authorization_type = \"AWS_IAM\" on all aws_lambda_function_url resources.",
|
|
198
|
+
"Use a CloudFront distribution with signed URLs or an API Gateway with IAM/Cognito auth as an alternative.",
|
|
199
|
+
"If public invocation is intentional, add CORS restrictions and rate limiting."
|
|
200
|
+
]
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
// 8. ECR scan on push disabled
|
|
204
|
+
if (ecrNoScanResults.length > 0) {
|
|
205
|
+
findings.push({
|
|
206
|
+
id: "INFRA_ECR_NO_SCAN",
|
|
207
|
+
title: "ECR scan-on-push disabled — container images deployed without CVE scanning",
|
|
208
|
+
severity: "HIGH",
|
|
209
|
+
evidence: ecrNoScanResults.slice(0, 20).map((m) => `${m.file}:${m.line}: ${m.preview}`),
|
|
210
|
+
requiredActions: [
|
|
211
|
+
"Set scan_on_push = true on all aws_ecr_repository resources.",
|
|
212
|
+
"Enable ECR Enhanced Scanning (Inspector-based) for continuous vulnerability monitoring.",
|
|
213
|
+
"Gate deployments on zero critical/high CVEs using CI checks against ECR scan results."
|
|
214
|
+
]
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
// 9. ECS host network
|
|
218
|
+
if (ecsHostNetworkResults.length > 0) {
|
|
219
|
+
findings.push({
|
|
220
|
+
id: "INFRA_ECS_HOST_NETWORK",
|
|
221
|
+
title: "ECS task using host network mode — bypasses container network isolation",
|
|
222
|
+
severity: "HIGH",
|
|
223
|
+
evidence: ecsHostNetworkResults.slice(0, 20).map((m) => `${m.file}:${m.line}: ${m.preview}`),
|
|
224
|
+
requiredActions: [
|
|
225
|
+
"Use network_mode = \"awsvpc\" for Fargate or bridge mode for EC2 ECS tasks.",
|
|
226
|
+
"Host networking exposes all host ports to the container — remove unless strictly required.",
|
|
227
|
+
"Apply security groups at the task level when using awsvpc mode."
|
|
228
|
+
]
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
// 10. CloudTrail not multi-region
|
|
232
|
+
if (cloudtrailNotMultiregionResults.length > 0) {
|
|
233
|
+
findings.push({
|
|
234
|
+
id: "INFRA_CLOUDTRAIL_NOT_MULTIREGION",
|
|
235
|
+
title: "CloudTrail is not multi-region — attacker actions in secondary regions go unlogged",
|
|
236
|
+
severity: "HIGH",
|
|
237
|
+
evidence: cloudtrailNotMultiregionResults.slice(0, 20).map((m) => `${m.file}:${m.line}: ${m.preview}`),
|
|
238
|
+
requiredActions: [
|
|
239
|
+
"Set is_multi_region_trail = true on all aws_cloudtrail resources.",
|
|
240
|
+
"Enable CloudTrail in all opted-in regions including global service events.",
|
|
241
|
+
"Send CloudTrail logs to a dedicated, cross-account S3 bucket with MFA delete enabled."
|
|
242
|
+
]
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
// 11. S3 server access logging disabled
|
|
246
|
+
if (s3NoAccessLoggingResults.length > 0) {
|
|
247
|
+
findings.push({
|
|
248
|
+
id: "INFRA_S3_NO_ACCESS_LOGGING",
|
|
249
|
+
title: "S3 server access logging not enabled — exfiltration events undetectable post-incident",
|
|
250
|
+
severity: "MEDIUM",
|
|
251
|
+
evidence: s3NoAccessLoggingResults.slice(0, 20).map((m) => `${m.file}:${m.line}: ${m.preview}`),
|
|
252
|
+
requiredActions: [
|
|
253
|
+
"Configure server access logging on all S3 buckets by specifying a target_bucket.",
|
|
254
|
+
"Use AWS CloudTrail data events as a supplementary audit trail for S3 object-level operations.",
|
|
255
|
+
"Retain access logs for at least 90 days and ship to a SIEM for alerting."
|
|
256
|
+
]
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
// 12. VPC flow logs missing (absence check: AWS infra present but no aws_flow_log resource found)
|
|
260
|
+
if (awsInfraResults.length > 0 && vpcNoFlowLogsResults.length === 0) {
|
|
261
|
+
findings.push({
|
|
262
|
+
id: "INFRA_VPC_NO_FLOW_LOGS",
|
|
263
|
+
title: "No aws_flow_log resource found — VPC network traffic is unlogged, lateral movement and exfiltration undetectable",
|
|
264
|
+
severity: "MEDIUM",
|
|
265
|
+
requiredActions: [
|
|
266
|
+
"Add an aws_flow_log resource for each VPC and ship logs to CloudWatch Logs or S3.",
|
|
267
|
+
"Set flow log aggregation interval to 1 minute for near-real-time detection.",
|
|
268
|
+
"Create CloudWatch metric filters and alarms for rejected traffic spikes."
|
|
269
|
+
]
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
// 13. Cross-account trust without ExternalId
|
|
273
|
+
if (assumeRoleResults.length > 0 && externalIdResults.length === 0) {
|
|
274
|
+
findings.push({
|
|
275
|
+
id: "INFRA_CROSS_ACCOUNT_NO_EXTERNAL_ID",
|
|
276
|
+
title: "Cross-account IAM trust without sts:ExternalId condition — confused deputy attack possible",
|
|
277
|
+
severity: "HIGH",
|
|
278
|
+
evidence: assumeRoleResults.slice(0, 20).map((m) => `${m.file}:${m.line}: ${m.preview}`),
|
|
279
|
+
requiredActions: [
|
|
280
|
+
"Add a Condition block with sts:ExternalId to all cross-account AssumeRole trust policies.",
|
|
281
|
+
"Use a unique, unguessable ExternalId per third-party relationship and rotate periodically.",
|
|
282
|
+
"Audit all cross-account role trusts with AWS IAM Access Analyzer."
|
|
283
|
+
]
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
// 14. GCP default service account
|
|
287
|
+
if (gcpDefaultSaResults.length > 0) {
|
|
288
|
+
findings.push({
|
|
289
|
+
id: "INFRA_GCP_DEFAULT_SERVICE_ACCOUNT",
|
|
290
|
+
title: "GCP instance uses default Compute Engine service account — broad project-level API permissions",
|
|
291
|
+
severity: "HIGH",
|
|
292
|
+
evidence: gcpDefaultSaResults.slice(0, 20).map((m) => `${m.file}:${m.line}: ${m.preview}`),
|
|
293
|
+
requiredActions: [
|
|
294
|
+
"Create a dedicated, least-privilege service account for each GCP compute resource.",
|
|
295
|
+
"Disable the default Compute Engine service account or remove the Editor role binding.",
|
|
296
|
+
"Use Workload Identity Federation instead of service account keys where possible."
|
|
297
|
+
]
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
// 15. GCP project-level SSH keys
|
|
301
|
+
if (gcpProjectSshResults.length > 0) {
|
|
302
|
+
findings.push({
|
|
303
|
+
id: "INFRA_GCP_PROJECT_SSH_KEYS",
|
|
304
|
+
title: "GCP project-level SSH keys set — single key compromise grants access to all instances",
|
|
305
|
+
severity: "MEDIUM",
|
|
306
|
+
evidence: gcpProjectSshResults.slice(0, 20).map((m) => `${m.file}:${m.line}: ${m.preview}`),
|
|
307
|
+
requiredActions: [
|
|
308
|
+
"Remove project-level SSH keys from project metadata and use instance-level keys only.",
|
|
309
|
+
"Prefer OS Login over metadata-based SSH keys for centralized IAM-controlled access.",
|
|
310
|
+
"Rotate any existing project-level SSH keys immediately and audit which instances they reached."
|
|
311
|
+
]
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
// 16. GCP compute external IP
|
|
315
|
+
if (gcpExternalIpResults.length > 0) {
|
|
316
|
+
findings.push({
|
|
317
|
+
id: "INFRA_GCP_EXTERNAL_IP",
|
|
318
|
+
title: "GCP compute instance has external IP — directly internet-reachable without load balancer",
|
|
319
|
+
severity: "MEDIUM",
|
|
320
|
+
evidence: gcpExternalIpResults.slice(0, 20).map((m) => `${m.file}:${m.line}: ${m.preview}`),
|
|
321
|
+
requiredActions: [
|
|
322
|
+
"Remove access_config blocks from google_compute_instance resources to disable external IPs.",
|
|
323
|
+
"Route traffic through a GCP Cloud Load Balancer or Cloud NAT instead of direct external IPs.",
|
|
324
|
+
"Use Identity-Aware Proxy (IAP) for admin access rather than exposing SSH/RDP externally."
|
|
325
|
+
]
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
// 17. Azure public network access
|
|
329
|
+
if (azurePublicNetworkResults.length > 0) {
|
|
330
|
+
findings.push({
|
|
331
|
+
id: "INFRA_AZURE_PUBLIC_NETWORK_ACCESS",
|
|
332
|
+
title: "Azure managed service with public_network_access_enabled=true — reachable from internet",
|
|
333
|
+
severity: "HIGH",
|
|
334
|
+
evidence: azurePublicNetworkResults.slice(0, 20).map((m) => `${m.file}:${m.line}: ${m.preview}`),
|
|
335
|
+
requiredActions: [
|
|
336
|
+
"Set public_network_access_enabled = false on all Azure managed services.",
|
|
337
|
+
"Use Private Endpoints and Private DNS Zones for internal connectivity.",
|
|
338
|
+
"Apply Azure Firewall or NSG rules to restrict any legitimately public-facing services."
|
|
339
|
+
]
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
// 18. Database deletion protection disabled
|
|
343
|
+
if (dbNoDeletionProtectionResults.length > 0) {
|
|
344
|
+
findings.push({
|
|
345
|
+
id: "INFRA_DB_NO_DELETION_PROTECTION",
|
|
346
|
+
title: "Database resource missing deletion protection — single terraform apply can permanently destroy prod DB",
|
|
347
|
+
severity: "HIGH",
|
|
348
|
+
evidence: dbNoDeletionProtectionResults.slice(0, 20).map((m) => `${m.file}:${m.line}: ${m.preview}`),
|
|
349
|
+
requiredActions: [
|
|
350
|
+
"Set deletion_protection = true on all aws_db_instance, aws_rds_cluster, and equivalent resources.",
|
|
351
|
+
"Enable automated backups with a retention window of at least 7 days.",
|
|
352
|
+
"Use Terraform prevent_destroy lifecycle rules as an additional safeguard."
|
|
353
|
+
]
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
// 19. Missing VPC endpoint for S3/ECR
|
|
357
|
+
if (awsInfraResults.length > 0 && vpcEndpointResults.length === 0) {
|
|
358
|
+
findings.push({
|
|
359
|
+
id: "INFRA_NO_VPC_ENDPOINT",
|
|
360
|
+
title: "No VPC endpoint found for AWS services — traffic routes over public internet",
|
|
361
|
+
severity: "MEDIUM",
|
|
362
|
+
evidence: awsInfraResults.slice(0, 20).map((m) => `${m.file}:${m.line}: ${m.preview}`),
|
|
363
|
+
requiredActions: [
|
|
364
|
+
"Create aws_vpc_endpoint resources for S3, ECR (api + dkr), and other frequently used AWS services.",
|
|
365
|
+
"Use Gateway endpoints for S3/DynamoDB (free) and Interface endpoints for other services.",
|
|
366
|
+
"Set the VPC endpoint policy to restrict access to specific S3 buckets or ECR repositories."
|
|
367
|
+
]
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
// 20. GuardDuty not enabled
|
|
371
|
+
if (awsInfraResults.length > 0 && guarddutyResults.length === 0) {
|
|
372
|
+
findings.push({
|
|
373
|
+
id: "INFRA_GUARDDUTY_MISSING",
|
|
374
|
+
title: "No GuardDuty detector resource found — threat detection (credential misuse, crypto-mining) disabled",
|
|
375
|
+
severity: "HIGH",
|
|
376
|
+
requiredActions: [
|
|
377
|
+
"Add an aws_guardduty_detector resource with enable = true to your Terraform.",
|
|
378
|
+
"Enable GuardDuty in all AWS regions and aggregate findings into a delegated admin account.",
|
|
379
|
+
"Subscribe to GuardDuty findings via EventBridge and route high-severity alerts to your on-call channel."
|
|
380
|
+
]
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
// 21. Security Hub not enabled
|
|
384
|
+
if (awsInfraResults.length > 0 && securityHubResults.length === 0) {
|
|
385
|
+
findings.push({
|
|
386
|
+
id: "INFRA_SECURITY_HUB_MISSING",
|
|
387
|
+
title: "AWS Security Hub not enabled — findings from GuardDuty/Inspector/Macie not centrally aggregated",
|
|
388
|
+
severity: "MEDIUM",
|
|
389
|
+
requiredActions: [
|
|
390
|
+
"Add an aws_securityhub_account resource to your Terraform.",
|
|
391
|
+
"Enable the AWS Foundational Security Best Practices and CIS AWS Foundations standards.",
|
|
392
|
+
"Aggregate Security Hub findings across regions and accounts into a central delegated admin."
|
|
393
|
+
]
|
|
394
|
+
});
|
|
395
|
+
}
|
|
151
396
|
return findings;
|
|
152
397
|
}
|