Amazon Inspector was relaunched at re:Invent 2021, replacing the Clair-based "basic scanning" tier in Amazon ECR with an "enhanced scanning" engine that continuously rescans container images, EC2 instances, and Lambda functions against updated CVE data instead of scanning once at push time. That single change is a useful proxy for a bigger shift: AWS now ships enough native security primitives — Inspector, CodePipeline manual-approval actions, Security Hub finding aggregation, Signer for code and container signing — that a team can build a real security gate without buying a platform. What AWS does not ship is the wiring — the actual DevSecOps architecture that connects those primitives into a single enforced pipeline. The Supply-chain Levels for Software Artifacts (SLSA) framework reached version 1.0 on April 19, 2023, per the OpenSSF's announcement, giving teams a common vocabulary — L1 through L3 — for how much build provenance a pipeline actually produces, but SLSA is a specification, not a CodePipeline template. Executive Order 14028, signed in May 2021, pushed SBOM generation into federal procurement and made CycloneDX and SPDX the two formats every AWS-targeted pipeline now has to speak. This post lays out a concrete reference architecture — source, build, scan, gate, sign, deploy, admit — for stitching these AWS-native services and open standards into one enforced pipeline, rather than five dashboards nobody correlates.
Where does scanning actually happen in an AWS-native pipeline?
Scanning happens at three distinct points, and conflating them is the most common architecture mistake. First, CodeBuild runs SAST and SCA as buildspec steps immediately after compilation — this is where a tool inspects source and dependency manifests before an artifact even exists. Second, Amazon ECR's enhanced scanning (built on Inspector) rescans every pushed container image against the National Vulnerability Database and now Amazon's own CVE feed, continuously, not just at push time — critical because a CVE published six weeks after you pushed an image should still trigger an alert. Third, Amazon Inspector separately covers EC2 instances and Lambda functions, closing the gap for workloads that never go through ECR at all. AWS's own Well-Architected Framework Security Pillar guidance recommends feeding all three scan sources into AWS Security Hub, which aggregates GuardDuty, Inspector, and Config findings into one normalized event stream — so a policy engine downstream has a single feed to evaluate instead of three APIs with different schemas.
How do you actually block a bad build instead of just alerting on it?
CodePipeline has no native "policy gate" concept — it has manual-approval actions and Lambda invoke actions, and you compose a gate out of those two primitives. The pattern: a CodeBuild stage runs the scan tooling and writes a machine-readable report (SARIF is the common format for SAST/SCA findings) to an S3 artifact; a Lambda function in the next stage parses that report against policy and calls PutApprovalResult on the pipeline — approving automatically if findings are below threshold, or leaving the manual-approval action pending (which can page a human, or auto-reject) if not. This is functionally the same shape as any CI gate: exit non-zero, block promotion. Safeguard's own CLI gate implements this exact pattern for teams who don't want to hand-write the Lambda — safeguard gate check --source . --policy production --fail-on critical runs as a CodeBuild buildspec step and returns a non-zero exit code plus a report, which a downstream Lambda or a CodeBuild on-failure block can turn straight into an approval rejection.
What does "provenance" mean and why does SLSA level matter here?
Provenance is a signed record of how an artifact was built — which source commit, which build system, which inputs — and SLSA gives that record a maturity scale so a policy can require a minimum level instead of trusting an unverifiable claim. SLSA L1 just requires a build process and provenance generation; L2 requires the provenance be signed and the build run on a hosted service (CodeBuild qualifies); L3 requires the build to be isolated and non-forgeable end to end, which on AWS typically means CodeBuild running in an ephemeral, single-use environment with no persistent credentials an attacker could reuse across builds. SLSA hit v1.0 on April 19, 2023 per OpenSSF's release announcement, consolidating three draft levels into a stable spec that AWS's own DevSecOps reference materials now cite as the target maturity model. In practice, a gate checks slsa.level >= 3 the same way it checks a CVSS score — it's just another field in the policy document, sourced from a Sigstore or in-toto attestation attached to the build.
How does image signing connect to what runs in EKS?
Signing closes the gap between "this image passed the gate" and "only that image can actually run." AWS Signer handles code-signing for Lambda and IoT artifacts, while container images typically use Notation (the Notary v2 CLI, a CNCF project) or Sigstore's Cosign to attach a signature to the image manifest stored in ECR. The enforcement half lives at the Kubernetes admission layer: an admission controller — Kyverno, Sigstore's policy-controller, or a vendor equivalent — intercepts every pod creation request, resolves the image digest, fetches the attached signature and SBOM attestation, and denies the pod if the signature doesn't verify or the required attestations are missing. This is the point at which a policy like "block any image without a CycloneDX SBOM attestation signed in the last 90 days" becomes unbypassable — a developer can't kubectl apply around a gate that already passed, because the cluster itself refuses to schedule an unsigned image regardless of how it got into ECR.
How do you avoid rebuilding this from scratch for every new CVE?
You avoid it by treating the SBOM as a persistent, queryable inventory rather than a one-time scan artifact, generated in CycloneDX or SPDX format on every CodeBuild run and stored centrally. AWS's own SSDF-aligned guidance (mirroring NIST SP 800-218) treats SBOM generation as a build-stage requirement precisely so that when a new CVE drops, the question "are we affected, and where" is a query against existing data instead of a fleet-wide rescan. This is also where Safeguard's guardrails model maps cleanly onto the architecture described above: it defines enforcement points at IDE, commit, CI, registry, admission, and runtime, with policy-as-code rules (CVSS, EPSS, license, SLSA level) evaluated against exactly the kind of combined SBOM-plus-vulnerability-plus-signature document this pipeline produces. Built-in guardrails like "block KEV-listed CVEs in production" or "require SLSA L3 provenance" slot directly into the CodePipeline Lambda-gate and EKS admission-controller stages described above, so a team assembling this DevSecOps architecture on AWS primitives doesn't have to hand-roll the policy evaluator or the audit trail — just the plumbing between CodeBuild, ECR, and the gate.