DEV Community

jasonmills94
jasonmills94

Posted on

ECR Scan Emails Need Image Digests

I have seen a lot of teams enable Amazon ECR scanning, wire up an email, and call the job done. The scan fires, a message lands somewhere, and everyone feels safer. Then a real release gets blocked and nobody is sure which image the alert was about, whether the digest matches the artifact that shipped, or if the finding came from an older push. That gap is where alert fatigue starts.

For this kind of workflow, I want every email to prove the exact container object that triggered it. If the message only includes a repo name and a tag like latest, it is not good enough. Tags move. Digests do not. In practice, using AWS plus Docker well means treating the digest as the main identity and the email as an auditable receipt.

Why scan emails become hard to trust

The weak version of this setup looks familiar:

  • CI pushes an image to ECR
  • a scan runs automatically
  • a Lambda or EventBridge rule sends an email
  • the email says something vague like "high severity finding detected"

That is technicaly working, but it is not very useful during a release window. The hard part is not sending the email. The hard part is making sure the operator can answer three questions fast:

  1. Which exact image digest failed?
  2. Was that digest part of the current deployment candidate?
  3. Where is the fastest path to the evidence?

When teams cannot answer those from the email alone, they start checking old inbox threads, comparing tags, and scribbling weird notes like tepm mail com in runbooks just to remember how they tested the flow. That is a smell. The process, not the people, needs tightening.

What the email must prove

My baseline email for ECR scan findings includes:

  • repository name
  • immutable image digest
  • pushed tag, if one exists
  • severity summary
  • account and region
  • pipeline run ID or commit SHA
  • one direct link to the finding in AWS

AWS documents image scanning at the registry and repository layers, but the operational win comes from how you present the result to humans: https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-scanning.html. The message should save a context switch, not create one.

I also prefer plain-text friendly formatting. The moment an email becomes a glossy template with hidden metadata, people stop trusting it under pressure. The same habit behind this SES smoke-test workflow applies here too: test the message as an operational artifact, not just as content.

A CI/CD pattern that binds alerts to one digest

The pattern that has worked best for me is pretty small:

  1. Build the image once in CI.
  2. Capture the digest right after the push.
  3. Store that digest beside the deployment metadata.
  4. Route the scan email check to one short-lived inbox for that run.
  5. Assert that the email includes the same digest and commit reference.

That inbox isolation matters more than it first seems. If two pipelines push close together, shared inboxes turn a simple check into guesswork. I would rather generate throwaway email targets per run than let two valid alerts cross paths and produce a false pass.

This is also where I borrow the idea of email guardrails before rollout. Your delivery channel should have boundaries. If the alert cannot be tied back to one reviewed artifact, it should not be allowed to silently pass a release gate.

A small AWS and Docker example

Here is the rough shape I use in CI/CD:

IMAGE_REPO="123456789012.dkr.ecr.us-east-1.amazonaws.com/payments-api"
IMAGE_TAG="${GIT_SHA}"

docker build -t "${IMAGE_REPO}:${IMAGE_TAG}" .
docker push "${IMAGE_REPO}:${IMAGE_TAG}"

IMAGE_DIGEST="$(aws ecr describe-images \
  --repository-name payments-api \
  --image-ids imageTag="${IMAGE_TAG}" \
  --query 'imageDetails[0].imageDigest' \
  --output text)"

echo "IMAGE_DIGEST=${IMAGE_DIGEST}" >> "$GITHUB_ENV"
Enter fullscreen mode Exit fullscreen mode

The important part is not the shell itself. It is freezing the digest early and passing it through the rest of the job. Later, when EventBridge or a small notifier sends the scan result, the assertion step compares the email body against IMAGE_DIGEST, not just the tag. That one detail saves anoying triage when tags get reused in preview or hotfix lanes.

If you use enhanced scanning with Amazon Inspector, the event payload already carries enough structure to build a useful email, but only if you preserve it cleanly: https://docs.aws.amazon.com/inspector/latest/user/scanning-ecr.html. I have seen teams flatten those fields too early, which makes the final message much less actionable than it should be.

Checklist before you ship it

Before I trust ECR scan emails in production, I verify:

  • the email contains the immutable digest in plain text
  • the commit SHA or pipeline run ID is visible
  • the AWS account and region are not implied, they are written out
  • a duplicate email for the same digest is explainable
  • the link opens the exact finding page, not a generic console landing page
  • the test inbox is isolated per run and cleaned up after

It is not glamorous platform work, but it keeps release decisions boring, which is what you want. A scan email should reduce doubt, not add another mini investigation to the deploy path. When that contract is tight, AWS and Docker alerts start feeling dependable instead of noisy.

Q&A

Is the digest really worth showing to humans?

Yes. Most people will not memorize it, obviousy, but it lets them verify that the alert belongs to the same artifact referenced in the deploy logs, ticket, or rollback notes.

Can I just use the image tag?

Only as supporting context. Tags are handy for reading, but they are mutabl in a way digests are not.

Do I need a temporary inbox for every scan check?

Not for every environment. But for CI/CD gates and release-critical validation, per-run inboxes keep the evidence clean and the failures much easier to explain.

Top comments (0)