Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions checkov/dockerfile/checks/SecretsInEnvArg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import re
from checkov.common.models.enums import CheckResult, CheckCategories
from checkov.dockerfile.base_dockerfile_check import BaseDockerfileCheck


# 🔍 Regex patterns to detect secrets, credentials, and private keys
SECRET_PATTERNS = [
r"(?i)(key|secret|token|password|pwd|auth|credential|api[_-]?key)\s*=", # generic secrets
r"(?i)AKIA[0-9A-Z]{16}", # AWS access key
r"(?i)ASIA[0-9A-Z]{16}", # AWS temporary key
r"(?i)ghp_[0-9A-Za-z]{36}", # GitHub personal access token
r"(?i)eyJ[a-zA-Z0-9_-]{20,}\.[a-zA-Z0-9_-]{20,}\.[a-zA-Z0-9_-]{20,}", # JWT
r'(?i)["\']?\s*-{3,}BEGIN(?: RSA)? PRIVATE KEY-{3,}', # Private key headers
r"(?i)xox[baprs]-[0-9A-Za-z-]{10,48}", # Slack/Discord tokens
]


class SecretsInEnvArg(BaseDockerfileCheck):
def __init__(self):
name = "Ensure no secrets or private keys are stored in ENV or ARG instructions"
check_id = "CKV_DOCKER_1005"
categories = [CheckCategories.SECRETS]
supported_instructions = ["ENV", "ARG"]
super().__init__(name=name, id=check_id, categories=categories, supported_instructions=supported_instructions)

def scan_resource_conf(self, conf):
"""
conf: list of dicts representing Dockerfile instructions, e.g.:
[
{"instruction": "ENV", "startline": 3, "endline": 3, "value": "API_KEY=abcd1234"},
{"instruction": "ARG", "startline": 4, "endline": 4, "value": "ACCESS_TOKEN=xyz789"}
]
"""
if not conf or not isinstance(conf, list):
return CheckResult.PASSED, None

for item in conf:
if not isinstance(item, dict):
continue

value = str(item.get("value", ""))
print(f"DEBUG: Checking value -> {value}")

for pattern in SECRET_PATTERNS:
if re.search(pattern, value):
print(f"DEBUG: Matched pattern -> {pattern} in {value}")
return CheckResult.FAILED, {
"startline": item.get("startline", 0),
"endline": item.get("endline", 0),
"instruction": item.get("instruction", ""),
"details": f"Potential secret pattern '{pattern}' found in {item.get('instruction', '')}: {value.strip()}"
}

return CheckResult.PASSED, None


check = SecretsInEnvArg()

16 changes: 16 additions & 0 deletions checkov/dockerfile/checks/SecretsInEnvArg.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
metadata:
id: CKV_DOCKER_1005
name: Secrets in ENV or ARG
category: SECRETS
severity: HIGH
description: >
Detects hardcoded secrets, API keys, tokens, and passwords in Dockerfile
ENV and ARG instructions. Hardcoded secrets can be extracted from image layers
or logs and lead to unauthorized access to systems and APIs.
remediation: >
Use Docker build-time secrets or external secret managers like AWS Secrets Manager,
GCP Secret Manager, or HashiCorp Vault. Avoid embedding secrets in Dockerfiles.
Avoid embedding secrets in Dockerfiles. Use Docker BuildKit secrets or
external secret managers like AWS Secrets Manager, GCP Secret Manager,
or HashiCorp Vault.
See: https://docs.docker.com/build/buildkit/secrets/
2 changes: 2 additions & 0 deletions checkov/dockerfile/checks/graph_checks/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import SecretsInEnvArg

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM ubuntu:20.04

# Bad practice: secrets stored directly in ENV or ARG
FROM python:3.10-slim
ENV API_KEY=abcd1234
ENV DB_PASSWORD=mysecretpass
ARG ACCESS_TOKEN=xyz789
RUN echo "Using secret environment variables"
CMD ["python3", "--version"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM ubuntu:20.04

# Safe: no secrets or sensitive data in ENV/ARG
FROM python:3.10-slim
ENV APP_ENV=production
ENV LOG_LEVEL=info
ARG BUILD_VERSION=1.0.0
RUN echo "Building image safely without secrets"
CMD ["python3", "--version"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FROM python:3.10-slim
ENV PRIVATE_KEY="-----BEGIN PRIVATE KEY-----abc123xyz"
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import os
from checkov.dockerfile.runner import Runner


def test_secrets_in_env_arg_check():
"""
Validate CKV_DOCKER_1005 detects secrets in ENV/ARG instructions
"""
test_dir = os.path.dirname(__file__)
report = Runner().run(root_folder=test_dir)

failed_checks = [check for check in report.failed_checks if check.check_id == "CKV_DOCKER_1005"]
passed_checks = [check for check in report.passed_checks if check.check_id == "CKV_DOCKER_1005"]

assert failed_checks, "Expected at least one failed check for secrets in ENV/ARG"
assert passed_checks, "Expected at least one passed check for secrets in ENV/ARG"


def test_private_key_detection():
"""
Ensure CKV_DOCKER_1005 detects private key exposure in ENV variables
"""
test_dir = os.path.dirname(__file__)
report = Runner().run(root_folder=test_dir)
fail_files = [check.file_path for check in report.failed_checks]

assert any("Dockerfile.privatekey.fail" in f for f in fail_files), \
"Expected private key pattern to be detected"