This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Scan for Secrets and Keys

Configure Anchore Enterprise to detect hardcoded secrets, credentials, and key patterns in container images, and enforce policy gates to block non-compliant images.

Hardcoded secrets — AWS credentials, private keys, API tokens, Docker auth configs — are one of the most common causes of container image security incidents. This quickstart walks you through configuring Anchore Enterprise to detect these patterns during image analysis and enforce policy gates that block non-compliant images from progressing through your pipeline.

By the end of this quickstart you will have:

  • Configured the secret_search cataloger with default and custom patterns
  • Scanned an image and retrieved secret findings
  • Created a policy gate that fails images containing hardcoded secrets
  • Run a policy check and interpreted the results

Before You Start

  • A running Anchore Enterprise deployment (Docker Compose or Kubernetes)
  • AnchoreCTL installed and configured
  • Images accessible from your Anchore Enterprise deployment via a container registry

Step 1 — Configure the Secret Search Cataloger

The secret_search cataloger scans file contents inside the image against a list of named regular expressions. It is disabled by default and must be enabled via your deployment configuration.

Five patterns are provided out of the box:

Pattern NameMatches
AWS_ACCESS_KEYAWS access key IDs
AWS_SECRET_KEYAWS secret access keys
PRIV_KEYPEM-encoded private keys
DOCKER_AUTHDocker config.json auth tokens
API_KEYGeneric API key patterns

Docker Compose

Create an analyzer_config.yaml file in your Docker Compose directory:

secret_search:
  match_params:
    - MAXFILESIZE=10000
  regexp_match:
    - "AWS_ACCESS_KEY=(?i).*aws_access_key_id( *=+ *).*(?<![A-Z0-9])[A-Z0-9]{20}(?![A-Z0-9]).*"
    - "AWS_SECRET_KEY=(?i).*aws_secret_access_key( *=+ *).*(?<![A-Za-z0-9/+=])[A-Za-z0-9/+=]{40}(?![A-Za-z0-9/+=]).*"
    - "PRIV_KEY=(?i)-+BEGIN(.*)PRIVATE KEY-+"
    - "DOCKER_AUTH=(?i).*\"auth\": *\".+\""
    - "API_KEY=(?i).*api(-|_)key( *=+ *).*(?<![A-Z0-9])[A-Z0-9]{20,60}(?![A-Z0-9]).*"

Mount the file into the analyzer service in your docker-compose.yaml:

services:
  analyzer:
    volumes:
      - ./analyzer_config.yaml:/anchore_service/analyzer_config.yaml:ro

Restart the analyzer service to apply the configuration:

docker compose up -d --no-deps analyzer

Helm

Add the following to your values.yaml:

anchoreConfig:
  analyzer:
    malware:
      configFile:
        secret_search:
          match_params:
            - MAXFILESIZE=10000
          regexp_match:
            - "AWS_ACCESS_KEY=(?i).*aws_access_key_id( *=+ *).*(?<![A-Z0-9])[A-Z0-9]{20}(?![A-Z0-9]).*"
            - "AWS_SECRET_KEY=(?i).*aws_secret_access_key( *=+ *).*(?<![A-Za-z0-9/+=])[A-Za-z0-9/+=]{40}(?![A-Za-z0-9/+=]).*"
            - "PRIV_KEY=(?i)-+BEGIN(.*)PRIVATE KEY-+"
            - "DOCKER_AUTH=(?i).*\"auth\": *\".+\""
            - "API_KEY=(?i).*api(-|_)key( *=+ *).*(?<![A-Z0-9])[A-Z0-9]{20,60}(?![A-Z0-9]).*"

Apply the chart update:

helm upgrade anchore-enterprise anchore/enterprise -f values.yaml

Step 2 — Add Custom Patterns

You can extend the default set with your own named patterns. Add entries to the regexp_match list using the format NAME=<regex>. The name is what you will reference in policy rules.

For example, to detect GitHub personal access tokens and GCP service account keys:

secret_search:
  match_params:
    - MAXFILESIZE=10000
  regexp_match:
    - "AWS_ACCESS_KEY=(?i).*aws_access_key_id( *=+ *).*(?<![A-Z0-9])[A-Z0-9]{20}(?![A-Z0-9]).*"
    - "AWS_SECRET_KEY=(?i).*aws_secret_access_key( *=+ *).*(?<![A-Za-z0-9/+=])[A-Za-z0-9/+=]{40}(?![A-Za-z0-9/+=]).*"
    - "PRIV_KEY=(?i)-+BEGIN(.*)PRIVATE KEY-+"
    - "DOCKER_AUTH=(?i).*\"auth\": *\".+\""
    - "API_KEY=(?i).*api(-|_)key( *=+ *).*(?<![A-Z0-9])[A-Z0-9]{20,60}(?![A-Z0-9]).*"
    - "GITHUB_TOKEN=(?i).*(github|gh)(_|-)?token( *=+ *).*(?<![A-Za-z0-9_])[A-Za-z0-9_]{36,40}(?![A-Za-z0-9_]).*"
    - "GCP_SERVICE_ACCOUNT=(?i).*\"private_key\"( *: *\").*(?<![A-Za-z0-9/+=])[A-Za-z0-9/+=]{64,}(?![A-Za-z0-9/+=]).*"

Restart the analyzer after any configuration change.


Step 3 — Scan an Image and Retrieve Findings

Add an image for analysis. Since secrets scanning requires Centralized Analysis, omit the --from flag so Anchore Enterprise pulls and analyzes the image directly:

anchorectl image add <your-registry>/<image>:<tag> --wait

Once analysis is complete, retrieve the secret scan results:

anchorectl image content <your-registry>/<image>:<tag> -t secret_search

A finding looks like this:

Secret Search:
┌────────────────┬────────────────────────┬────────────┐
│ SEARCH NAME    │ PATH                   │ AT LINE(S) │
├────────────────┼────────────────────────┼────────────┤
│ API_KEY        │ /app.conf              │ 0          │
│ PRIV_KEY       │ /etc/ssl/fake_priv.key │ 0          │
│ AWS_ACCESS_KEY │ /root/.aws/credentials │ 1          │
│ AWS_SECRET_KEY │ /root/.aws/credentials │ 2          │
└────────────────┴────────────────────────┴────────────┘

Each row shows the pattern name that matched, the file path where it was found, and the line number within that file.

You can also retrieve findings via the GUI on the image’s SBOM tab, under the Secret Searches content type.

Secret search findings in the Anchore Enterprise GUI — image SBOM tab, Secret Search content type.


Step 4 — Create a Policy Gate for Secrets

Detecting secrets is useful, but the real value is using policy gates to automatically block images that contain them. The secret_scans gate with the content_regex_checks trigger lets you do exactly that.

Create a Policy Bundle

Save the following as secrets_policy.json:

{
  "id": "secrets-scanning-quickstart",
  "name": "Secrets Scanning Policy",
  "version": "2",
  "description": "Block images containing hardcoded secrets and credentials.",
  "rule_sets": [
    {
      "id": "secrets-ruleset-01",
      "name": "Block Hardcoded Secrets",
      "version": "2",
      "description": "Fail if any configured secret pattern is found in the image.",
      "artifact_type": "image",
      "rules": [
        {
          "id": "rule-aws-access-key",
          "gate": "secret_scans",
          "action": "STOP",
          "trigger": "content_regex_checks",
          "params": [
            { "name": "match_type", "value": "found" },
            { "name": "content_regex_name", "value": "AWS_ACCESS_KEY" }
          ],
          "recommendation": "",
          "description": "Fail if an AWS access key is found anywhere in the image."
        },
        {
          "id": "rule-aws-secret-key",
          "gate": "secret_scans",
          "action": "STOP",
          "trigger": "content_regex_checks",
          "params": [
            { "name": "match_type", "value": "found" },
            { "name": "content_regex_name", "value": "AWS_SECRET_KEY" }
          ],
          "recommendation": "",
          "description": "Fail if an AWS secret key is found anywhere in the image."
        },
        {
          "id": "rule-priv-key",
          "gate": "secret_scans",
          "action": "STOP",
          "trigger": "content_regex_checks",
          "params": [
            { "name": "match_type", "value": "found" },
            { "name": "content_regex_name", "value": "PRIV_KEY" }
          ],
          "recommendation": "",
          "description": "Fail if a private key is found anywhere in the image."
        },
        {
          "id": "rule-api-key",
          "gate": "secret_scans",
          "action": "STOP",
          "trigger": "content_regex_checks",
          "params": [
            { "name": "match_type", "value": "found" },
            { "name": "content_regex_name", "value": "API_KEY" }
          ],
          "recommendation": "",
          "description": "Fail if an API key is found anywhere in the image."
        },
        {
          "id": "rule-docker-auth",
          "gate": "secret_scans",
          "action": "STOP",
          "trigger": "content_regex_checks",
          "params": [
            { "name": "match_type", "value": "found" },
            { "name": "content_regex_name", "value": "DOCKER_AUTH" }
          ],
          "recommendation": "",
          "description": "Fail if Docker auth credentials are found in the image."
        }
      ]
    }
  ],
  "allowlists": [],
  "mappings": [
    {
      "id": "secrets-mapping-default",
      "name": "default",
      "registry": "*",
      "repository": "*",
      "image": { "type": "tag", "value": "*" },
      "description": "",
      "rule_set_ids": ["secrets-ruleset-01"],
      "allowlist_ids": []
    }
  ],
  "source_mappings": [],
  "allowlisted_images": [],
  "denylisted_images": [],
  "sbom_mappings": []
}

Add the policy to Anchore Enterprise:

anchorectl policy add --input secrets_policy.json

You can also create and manage these rules directly in the GUI under PolicyPolicies → your policy → Edit.

Configuring a secret_scans gate rule in the Anchore Enterprise policy editor — Gate: secret scans, Trigger: content regex checks, Parameter: content_regex_name = AWS_ACCESS_KEY.


Step 5 — Run a Policy Check

Evaluate an image against the secrets policy:

anchorectl image check <your-registry>/<image>:<tag> --policy secrets-scanning-quickstart --detail

An image containing hardcoded secrets will produce output like the following:

Tag: docker.io/myrepo/myimage:latest
Policy ID: secrets-scanning-quickstart
Evaluation: fail
Final Action: stop

Policy Evaluation Details:
┌──────────────┬──────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────┬────────┐
│ GATE         │ TRIGGER              │ DESCRIPTION                                                                                │ ACTION │
├──────────────┼──────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────┼────────┤
│ secret_scans │ content_regex_checks │ Secret content search analyzer found regexp match in container: file=/app.conf              │ stop   │
│ secret_scans │ content_regex_checks │ Secret content search analyzer found regexp match in container: file=/etc/ssl/fake_priv.key │ stop   │
│ secret_scans │ content_regex_checks │ Secret content search analyzer found regexp match in container: file=/root/.aws/credentials │ stop   │
│ secret_scans │ content_regex_checks │ Secret content search analyzer found regexp match in container: file=/root/.aws/credentials │ stop   │
└──────────────┴──────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────┴────────┘

To fail a CI pipeline step automatically when the policy evaluation returns fail, add the -f flag:

anchorectl image check <your-registry>/<image>:<tag> --policy secrets-scanning-quickstart --detail -f

The -f flag (shorthand for --fail-based-on-results) returns exit code 1 on a failing evaluation, which causes the CI step to fail. See Use Anchore Enterprise in CI for guidance on wiring this into a full pipeline.

Policy evaluation result — Final Action: STOP, Policy Result: FAILED, 4 violations from the secret_scans gate listed under Policy Evaluation.


Conclusion

You have configured Anchore Enterprise to scan images for hardcoded secrets, extended the default patterns with custom regular expressions, and created a policy gate that blocks non-compliant images. Combined with a CI integration, this provides automated enforcement to prevent secrets from reaching production container images.

Further reading: