[
  {
    "id": "a02_dockerfile_hardcoded_secret",
    "file_type": "dockerfile",
    "check_type": "secret_env",
    "pattern": "^[ \\t]*ENV[ \\t]+(?P<name>[A-Z0-9_]*(?:PASSWORD|SECRET|TOKEN|KEY|CREDENTIAL|AUTH|MONGO|MYSQL|POSTGRES|JWT|OAUTH|DATABASE_URL|DB_URL|API)[A-Z0-9_]*)[ \\t]*[=\\s][ \\t]*(?P<value>\\S.+)$",
    "ignore_case": true,
    "multiline": false,
    "severity_fn": "critical_if_url_else_high",
    "confidence": "high",
    "owasp": "A02",
    "cwe": "CWE-798",
    "title_template": "OWASP A02:2021 (Cryptographic Failures): Hardcoded Secret in Dockerfile ENV \u2014 {name}",
    "description_template": "The Dockerfile sets '{name}' to a literal value via an ENV instruction. Secrets baked into Docker images are readable by anyone with image access and may be leaked through image layers, registries, or container inspection.",
    "recommendation_template": "Remove the hardcoded value of '{name}' from the Dockerfile.\nUse Docker build secrets (--secret), runtime environment injection (e.g., Kubernetes Secrets, Docker Swarm secrets, or a secrets manager), or ARG + build-time injection without baking the value into the image layer.",
    "references": [
      "https://docs.docker.com/build/building/secrets/",
      "https://owasp.org/Top10/A02_2021-Cryptographic_Failures/"
    ]
  },
  {
    "id": "a06_dockerfile_unpinned_base_image",
    "file_type": "dockerfile",
    "check_type": "unpinned_from",
    "pattern": "^[ \\t]*FROM[ \\t]+(?P<image>[^\\s:@]+)(?::(?P<tag>[^\\s@]+))?(?:@\\S+)?(?:[ \\t]+AS[ \\t]+\\S+)?[ \\t]*$",
    "ignore_case": true,
    "multiline": false,
    "severity_fn": "high_if_unpinned_else_medium",
    "confidence": "high",
    "owasp": "A06",
    "cwe": "CWE-1395",
    "title_template_unpinned": "OWASP A06:2021 (Vulnerable and Outdated Components): Unpinned Base Image \u2014 {image}{tag_display}",
    "description_template_unpinned": "The base image '{image}{tag_colon}' is not pinned to any version tag. Rebuilding the image in the future may silently pull a different, potentially vulnerable version.",
    "title_template_floating": "OWASP A06:2021 (Vulnerable and Outdated Components): Unpinned Base Image \u2014 {image}:{tag}",
    "description_template_floating": "The base image '{image}:{tag}' uses a floating major version tag. '{tag}' resolves to the latest patch release of that major version and will change on each new patch, making builds non-reproducible and potentially pulling vulnerable versions.",
    "recommendation_template": "Pin the base image to a specific digest or immutable tag, e.g.:\n  FROM {image}:<specific-version>@sha256:<digest>\nUse tools like Dependabot or Renovate to keep base images up to date.",
    "references": [
      "https://docs.docker.com/develop/dev-best-practices/"
    ]
  },
  {
    "id": "a05_dockerfile_runs_as_root",
    "file_type": "dockerfile",
    "check_type": "missing_user",
    "user_pattern": "^[ \\t]*USER[ \\t]+(?P<user>\\S+)",
    "severity": "medium",
    "confidence": "high",
    "owasp": "A05",
    "cwe": "CWE-250",
    "title_template": "OWASP A05:2021 (Security Misconfiguration): Container Runs as Root \u2014 {file_name}",
    "description_template": "No non-root USER instruction was found in the Dockerfile. Containers running as root have elevated privileges that can be exploited if the application is compromised, potentially allowing container escape.",
    "recommendation": "Add a USER instruction near the end of the Dockerfile to run the process as a non-root user:\n  RUN addgroup --system appgroup && adduser --system --ingroup appgroup appuser\n  USER appuser",
    "references": [
      "https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user"
    ]
  },
  {
    "id": "a08_dockerfile_add_remote_url",
    "file_type": "dockerfile",
    "check_type": "regex_match",
    "pattern": "^[ \\t]*ADD[ \\t]+https?://",
    "ignore_case": true,
    "multiline": false,
    "severity": "medium",
    "confidence": "high",
    "owasp": "A08",
    "cwe": "CWE-494",
    "title_template": "OWASP A08:2021 (Software and Data Integrity Failures): ADD with Remote URL in {file_name}",
    "description": "The ADD instruction downloads content from a remote URL at build time. This bypasses image layer caching integrity, may pull unverified content, and cannot be audited for supply-chain attacks. Use COPY or RUN curl/wget with explicit checksum verification instead.",
    "recommendation": "Replace ADD <url> with:\n  RUN curl -fsSL <url> -o <file> && echo '<sha256>  <file>' | sha256sum -c -\nOr use a multi-stage build to copy from a verified source.",
    "references": [
      "https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#add-or-copy"
    ]
  },
  {
    "id": "a05_compose_privileged_container",
    "file_type": "compose",
    "check_type": "regex_match",
    "pattern": "privileged\\s*:\\s*true",
    "ignore_case": true,
    "severity": "critical",
    "confidence": "high",
    "owasp": "A05",
    "cwe": "CWE-250",
    "title_template": "OWASP A05:2021 (Security Misconfiguration): Privileged Container in {file_name}",
    "description": "'privileged: true' grants the container nearly all host kernel capabilities, effectively disabling container isolation. A compromised process can escape to the host.",
    "recommendation": "Remove 'privileged: true'. If specific capabilities are needed, grant only those via 'cap_add' (e.g., cap_add: [NET_ADMIN]) instead of full privilege.",
    "references": [
      "https://docs.docker.com/compose/compose-file/05-services/#privileged"
    ]
  },
  {
    "id": "a05_compose_host_network",
    "file_type": "compose",
    "check_type": "regex_match",
    "pattern": "network_mode\\s*:\\s*['\"]?host['\"]?",
    "ignore_case": true,
    "severity": "high",
    "confidence": "high",
    "owasp": "A05",
    "cwe": "CWE-668",
    "title_template": "OWASP A05:2021 (Security Misconfiguration): Host Network Mode in {file_name}",
    "description": "'network_mode: host' bypasses Docker's network namespace isolation. The container shares the host network stack, enabling access to all host ports and services, increasing the blast radius of any container compromise.",
    "recommendation": "Remove 'network_mode: host'. Use explicit port mappings under 'ports:' and custom Docker networks for inter-service communication.",
    "references": [
      "https://docs.docker.com/compose/compose-file/05-services/#network_mode"
    ]
  },
  {
    "id": "a05_compose_docker_socket_mount",
    "file_type": "compose",
    "check_type": "regex_match",
    "pattern": "/var/run/docker\\.sock",
    "ignore_case": true,
    "severity": "high",
    "confidence": "high",
    "owasp": "A05",
    "cwe": "CWE-250",
    "title_template": "OWASP A05:2021 (Security Misconfiguration): Docker Socket Mounted in {file_name}",
    "description": "Mounting /var/run/docker.sock gives the container full control over the Docker daemon, equivalent to root access on the host. A compromised container can create privileged containers, read host files, or escape the sandbox entirely.",
    "recommendation": "Avoid mounting the Docker socket. If Docker-in-Docker is required for CI, use rootless Docker, kaniko, or a socket proxy (e.g., tecnativa/docker-socket-proxy) that limits which API calls are permitted.",
    "references": [
      "https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html"
    ]
  },
  {
    "id": "a02_ci_secret_echoed",
    "file_type": "ci_yaml",
    "check_type": "regex_match",
    "pattern": "(?:echo|printenv|env)\\s+[\"']?\\$(?P<var>[A-Z0-9_]*(?:SECRET|TOKEN|PASSWORD|KEY|API)[A-Z0-9_]*)",
    "ignore_case": true,
    "multiline": false,
    "severity": "high",
    "confidence": "medium",
    "owasp": "A02",
    "cwe": "CWE-312",
    "title_template": "OWASP A02:2021 (Cryptographic Failures): Secret Variable Echoed to CI Log \u2014 ${var}",
    "description_template": "The CI pipeline echoes the secret variable '${var}' to the build log. CI build logs are often stored for days or weeks and accessible to many team members, making this a significant secret exposure risk.",
    "recommendation_template": "Remove the echo/printenv statement that prints '${var}'. If debugging is needed, use masked variables in your CI system (GitHub Actions, GitLab CI, CircleCI all support secret masking). Never print secrets to logs in production pipelines.",
    "references": [
      "https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions"
    ]
  }
]
