warnings fixes, tests fixes, sprints completions
This commit is contained in:
87
policies/secret-detection.policy.yaml
Normal file
87
policies/secret-detection.policy.yaml
Normal file
@@ -0,0 +1,87 @@
|
||||
# Secret Leak Detection Policy Pack
|
||||
# Sprint: SPRINT_20260104_004_POLICY - Task PSD-010
|
||||
#
|
||||
# This policy pack enforces security gates based on secret leak detection findings.
|
||||
# Uses signals from SecretSignalBinder for policy evaluation.
|
||||
#
|
||||
# Available signals:
|
||||
# secret.has_finding - true if any secret finding exists
|
||||
# secret.count - total number of findings
|
||||
# secret.severity.critical - true if any critical finding exists
|
||||
# secret.severity.high - true if any high severity finding exists
|
||||
# secret.severity.medium - true if any medium severity finding exists
|
||||
# secret.severity.low - true if any low severity finding exists
|
||||
# secret.confidence.high - true if any high confidence finding exists
|
||||
# secret.confidence.medium - true if any medium confidence finding exists
|
||||
# secret.confidence.low - true if any low confidence finding exists
|
||||
# secret.mask.applied - true if masking was applied to all findings
|
||||
# secret.bundle.version - the active bundle version string
|
||||
# secret.bundle.id - the active bundle ID
|
||||
|
||||
name: secret-detection-gates
|
||||
version: 1.0.0
|
||||
description: |
|
||||
Security gates for secret leak detection.
|
||||
Blocks deployments when critical or high-severity secrets are detected.
|
||||
|
||||
rules:
|
||||
# Block on any critical severity secret (private keys, service account keys, etc.)
|
||||
- id: block-critical-secrets
|
||||
description: Block deployment when critical secrets are detected
|
||||
severity: critical
|
||||
when:
|
||||
signal: secret.severity.critical
|
||||
equals: true
|
||||
deny_message: |
|
||||
CRITICAL: Secrets with critical severity detected.
|
||||
Review findings and rotate any exposed credentials before proceeding.
|
||||
Common causes: Private keys, GCP service account keys, Stripe secret keys.
|
||||
|
||||
# Block on high severity secrets with high confidence (real credentials)
|
||||
- id: block-high-confidence-secrets
|
||||
description: Block deployment when high-confidence high-severity secrets are detected
|
||||
severity: high
|
||||
when:
|
||||
all:
|
||||
- signal: secret.severity.high
|
||||
equals: true
|
||||
- signal: secret.confidence.high
|
||||
equals: true
|
||||
deny_message: |
|
||||
HIGH: High-confidence secrets detected with high severity.
|
||||
These are likely real credentials. Review and remediate before deployment.
|
||||
|
||||
# Warn on medium severity secrets (potential API keys, passwords)
|
||||
- id: warn-medium-secrets
|
||||
description: Warn when medium-severity secrets are detected
|
||||
severity: medium
|
||||
when:
|
||||
signal: secret.severity.medium
|
||||
equals: true
|
||||
warn_message: |
|
||||
WARNING: Medium-severity secrets detected.
|
||||
Review findings to confirm they are not false positives.
|
||||
Consider adding legitimate patterns to the exception list.
|
||||
|
||||
# Warn when any secrets are found (informational)
|
||||
- id: info-any-secrets
|
||||
description: Log when any secrets are detected
|
||||
severity: low
|
||||
when:
|
||||
signal: secret.has_finding
|
||||
equals: true
|
||||
info_message: |
|
||||
Secret detection found {{secret.count}} potential secret(s).
|
||||
Review the findings in the scan results.
|
||||
|
||||
# Ensure masking is applied before allowing export
|
||||
- id: require-masking
|
||||
description: Block export if masking was not applied
|
||||
severity: high
|
||||
context: export
|
||||
when:
|
||||
signal: secret.mask.applied
|
||||
equals: false
|
||||
deny_message: |
|
||||
BLOCKED: Secrets must be masked before export.
|
||||
Ensure revelation policy is not set to FullReveal for exports.
|
||||
116
policies/secret-detection.rego
Normal file
116
policies/secret-detection.rego
Normal file
@@ -0,0 +1,116 @@
|
||||
# Secret Detection Policy - OPA Rego
|
||||
# Sprint: SPRINT_20260104_004_POLICY - Task PSD-010
|
||||
#
|
||||
# This Rego policy provides advanced logic for secret detection gates.
|
||||
# Use this for complex organizations that need conditional logic based on
|
||||
# environment, image source, or team ownership.
|
||||
#
|
||||
# Input schema (from ScanResult):
|
||||
# input.secrets.findings[] - Array of SecretFinding objects
|
||||
# input.secrets.bundle.version - Bundle version used for detection
|
||||
# input.secrets.maskApplied - Whether masking was applied
|
||||
# input.image.name - Full image name
|
||||
# input.image.registry - Registry domain
|
||||
# input.environment - Deployment environment (dev/staging/prod)
|
||||
|
||||
package stella.policy.secrets
|
||||
|
||||
import future.keywords.contains
|
||||
import future.keywords.if
|
||||
import future.keywords.in
|
||||
|
||||
default deny := []
|
||||
default warn := []
|
||||
|
||||
# Block any critical secrets in production
|
||||
deny contains msg if {
|
||||
input.environment == "production"
|
||||
finding := input.secrets.findings[_]
|
||||
finding.severity == "critical"
|
||||
msg := sprintf(
|
||||
"BLOCKED: Critical secret '%s' detected in production image %s. Rule: %s",
|
||||
[finding.ruleId, input.image.name, finding.ruleName]
|
||||
)
|
||||
}
|
||||
|
||||
# Block high-severity secrets with high confidence in all environments
|
||||
deny contains msg if {
|
||||
finding := input.secrets.findings[_]
|
||||
finding.severity == "high"
|
||||
finding.confidence == "high"
|
||||
msg := sprintf(
|
||||
"BLOCKED: High-confidence secret '%s' detected in %s. File: %s",
|
||||
[finding.ruleName, input.image.name, finding.filePath]
|
||||
)
|
||||
}
|
||||
|
||||
# Allow low-confidence findings in dev, but block in prod/staging
|
||||
deny contains msg if {
|
||||
input.environment in {"production", "staging"}
|
||||
finding := input.secrets.findings[_]
|
||||
finding.severity in {"high", "critical"}
|
||||
finding.confidence == "low"
|
||||
msg := sprintf(
|
||||
"BLOCKED: Low-confidence secret finding requires review before %s deployment. Rule: %s",
|
||||
[input.environment, finding.ruleName]
|
||||
)
|
||||
}
|
||||
|
||||
# Warn on medium severity secrets in any environment
|
||||
warn contains msg if {
|
||||
finding := input.secrets.findings[_]
|
||||
finding.severity == "medium"
|
||||
msg := sprintf(
|
||||
"WARNING: Medium-severity secret '%s' in %s. Consider adding to exceptions if legitimate.",
|
||||
[finding.ruleName, finding.filePath]
|
||||
)
|
||||
}
|
||||
|
||||
# Warn if secret count exceeds threshold (potential bulk exposure)
|
||||
warn contains msg if {
|
||||
count(input.secrets.findings) > 10
|
||||
msg := sprintf(
|
||||
"WARNING: High number of secrets detected (%d findings). Review for bulk credential exposure.",
|
||||
[count(input.secrets.findings)]
|
||||
)
|
||||
}
|
||||
|
||||
# Block export without masking
|
||||
deny contains msg if {
|
||||
input.context == "export"
|
||||
not input.secrets.maskApplied
|
||||
msg := "BLOCKED: Secrets must be masked before export. Enable masking in revelation policy."
|
||||
}
|
||||
|
||||
# Require bundle signature verification
|
||||
deny contains msg if {
|
||||
input.environment == "production"
|
||||
not input.secrets.bundle.verified
|
||||
msg := sprintf(
|
||||
"BLOCKED: Secret detection bundle '%s' signature verification failed.",
|
||||
[input.secrets.bundle.id]
|
||||
)
|
||||
}
|
||||
|
||||
# Warn on outdated bundle in production
|
||||
warn contains msg if {
|
||||
input.environment == "production"
|
||||
input.secrets.bundle.ageHours > 168 # 7 days
|
||||
msg := sprintf(
|
||||
"WARNING: Secret detection bundle is over 7 days old (version: %s). Update for latest rules.",
|
||||
[input.secrets.bundle.version]
|
||||
)
|
||||
}
|
||||
|
||||
# Allowlist: Skip checks for internal base images
|
||||
skip_secret_checks if {
|
||||
startswith(input.image.registry, "internal.registry.")
|
||||
input.image.isBaseImage
|
||||
}
|
||||
|
||||
# Allowlist: Skip low-severity in dev environment
|
||||
skip_warning[finding.id] if {
|
||||
input.environment == "development"
|
||||
finding := input.secrets.findings[_]
|
||||
finding.severity == "low"
|
||||
}
|
||||
@@ -1,6 +1,118 @@
|
||||
# Starter Day-1 Policy Pack
|
||||
# This is a minimal stub file for build compatibility.
|
||||
# Sprint: SPRINT_20260104_004_POLICY - Task PSD-010
|
||||
#
|
||||
# This is a comprehensive starter policy for day-1 security controls.
|
||||
# It includes gates for vulnerabilities, secret detection, and SBOM quality.
|
||||
|
||||
name: starter-day1
|
||||
version: 1.0.0
|
||||
description: Starter policy pack for day-1 security controls.
|
||||
rules: []
|
||||
description: |
|
||||
Starter policy pack for day-1 security controls.
|
||||
Includes essential gates for vulnerabilities, secrets, and SBOM validation.
|
||||
|
||||
rules:
|
||||
# === VULNERABILITY GATES ===
|
||||
|
||||
- id: block-critical-cves
|
||||
description: Block images with critical vulnerabilities
|
||||
severity: critical
|
||||
when:
|
||||
signal: vuln.severity.critical
|
||||
operator: gt
|
||||
value: 0
|
||||
deny_message: |
|
||||
BLOCKED: Image contains critical vulnerabilities.
|
||||
Review CVEs and apply patches before deployment.
|
||||
|
||||
- id: block-kev-vulnerabilities
|
||||
description: Block images with Known Exploited Vulnerabilities
|
||||
severity: critical
|
||||
when:
|
||||
signal: vuln.kev.count
|
||||
operator: gt
|
||||
value: 0
|
||||
deny_message: |
|
||||
BLOCKED: Image contains Known Exploited Vulnerabilities (KEV).
|
||||
These vulnerabilities are actively being exploited in the wild.
|
||||
Immediate remediation required.
|
||||
|
||||
# === SECRET DETECTION GATES ===
|
||||
|
||||
- id: block-critical-secrets
|
||||
description: Block deployment when critical secrets are detected
|
||||
severity: critical
|
||||
when:
|
||||
signal: secret.severity.critical
|
||||
equals: true
|
||||
deny_message: |
|
||||
BLOCKED: Critical secrets detected (private keys, service account keys).
|
||||
Rotate exposed credentials and remove from container image.
|
||||
|
||||
- id: block-high-secrets
|
||||
description: Block deployment when high-severity secrets are detected
|
||||
severity: high
|
||||
when:
|
||||
all:
|
||||
- signal: secret.severity.high
|
||||
equals: true
|
||||
- signal: secret.confidence.high
|
||||
equals: true
|
||||
deny_message: |
|
||||
BLOCKED: High-severity secrets detected with high confidence.
|
||||
These appear to be real credentials. Remediate before deployment.
|
||||
|
||||
- id: warn-secret-findings
|
||||
description: Warn when any secrets are detected
|
||||
severity: medium
|
||||
when:
|
||||
signal: secret.has_finding
|
||||
equals: true
|
||||
warn_message: |
|
||||
WARNING: Secret detection found {{secret.count}} potential secret(s).
|
||||
Review findings and add legitimate patterns to the exception list.
|
||||
|
||||
# === SBOM QUALITY GATES ===
|
||||
|
||||
- id: require-sbom
|
||||
description: Require a valid SBOM for all images
|
||||
severity: high
|
||||
when:
|
||||
signal: sbom.present
|
||||
equals: false
|
||||
deny_message: |
|
||||
BLOCKED: No SBOM found for image.
|
||||
Generate an SBOM before deployment (CycloneDX or SPDX format).
|
||||
|
||||
- id: warn-unknown-components
|
||||
description: Warn when SBOM contains many unknown components
|
||||
severity: medium
|
||||
when:
|
||||
signal: sbom.unknown_ratio
|
||||
operator: gt
|
||||
value: 0.2
|
||||
warn_message: |
|
||||
WARNING: Over 20% of SBOM components could not be identified.
|
||||
Consider improving build process for better provenance.
|
||||
|
||||
# === IMAGE CONFIGURATION GATES ===
|
||||
|
||||
- id: block-root-user
|
||||
description: Block images that run as root by default
|
||||
severity: high
|
||||
when:
|
||||
signal: image.runs_as_root
|
||||
equals: true
|
||||
deny_message: |
|
||||
BLOCKED: Image runs as root user.
|
||||
Configure a non-root USER in the Dockerfile.
|
||||
|
||||
- id: warn-old-base-image
|
||||
description: Warn when base image is outdated
|
||||
severity: medium
|
||||
when:
|
||||
signal: image.base_age_days
|
||||
operator: gt
|
||||
value: 90
|
||||
warn_message: |
|
||||
WARNING: Base image is over 90 days old.
|
||||
Consider updating to get latest security patches.
|
||||
|
||||
Reference in New Issue
Block a user