Safeguard
DevSecOps

What is Security as Code

Security as code turns policies and controls into version-controlled, pipeline-enforced rules. Here's what it looks like, why it matters, and how to adopt it.

Priya Mehta
DevSecOps Engineer
Updated 7 min read

Security as code means writing your security policies, controls, and tests as version-controlled, machine-readable code that runs automatically inside the same CI/CD pipelines that build and ship software — instead of storing them as PDF standards, spreadsheet checklists, or tribal knowledge that a human has to remember to apply. A Rego policy that blocks a Terraform plan from creating a public S3 bucket, a GitHub Actions step that fails a build when Trivy finds a critical CVE, a security code scan that blocks a pull request when Semgrep flags an injectable string, a Conftest rule that rejects a Kubernetes manifest without resource limits — these are security as code. The approach traces back to the same "everything as code" logic that produced infrastructure as code (Terraform, CloudFormation) a decade earlier: if the control lives in a file that gets reviewed, versioned, and tested, it scales with your commit velocity instead of your headcount. Below, we break down what security as code actually looks like, where it fits next to DevSecOps, and how to start writing it.

What is security as code?

Security as code is the practice of expressing security requirements — access controls, compliance checks, vulnerability thresholds, network policies — as executable code that a pipeline enforces on every commit, rather than as documentation a reviewer consults manually. The clearest example is Open Policy Agent (OPA), open-sourced by Styra in 2016 and graduated by the CNCF in 2021: teams write policies in Rego, a declarative query language, and those policies evaluate Kubernetes admission requests, Terraform plans, or API calls in real time. Compare that to a traditional security review, where an engineer opens a 40-page PDF standard, checks a box, and signs off — a process that doesn't scale past a handful of releases a week and produces no audit trail beyond a signature. With security as code, the same check runs on every one of the 500+ pull requests a mid-size engineering org might merge in a month, with the pass/fail result attached directly to the commit.

How is security as code different from DevSecOps?

DevSecOps is the organizational philosophy of integrating security into every phase of the software delivery lifecycle; security as code is the technical mechanism that makes that philosophy enforceable rather than aspirational. DevSecOps says developers and security teams share responsibility for risk starting at design time. Security as code is the actual Sentinel policy in a Terraform Cloud run, or the Semgrep rule in a pre-merge GitHub Actions job, that makes "shared responsibility" concrete instead of a value stated in an onboarding deck. NIST formalized much of this thinking in SP 800-218, the Secure Software Development Framework, published in February 2022 following Executive Order 14028 — which itself was signed May 12, 2021, in direct response to the SolarWinds supply chain attack. The order pushed federal software vendors toward machine-readable attestations and SBOMs; security as code is how vendors actually produce them on a schedule instead of once a year for an audit.

What does a security-as-code pipeline look like in practice?

A typical security-as-code pipeline runs five categories of automated checks on every pull request: static application security testing (SAST) — a source code security scanner — with a tool like Semgrep, software composition analysis (SCA) that generates a CycloneDX or SPDX SBOM and flags vulnerable dependencies, infrastructure-as-code scanning with Checkov or tfsec, container image scanning with Trivy or Grype, and a policy-as-code gate — OPA/Conftest, Kyverno, or AWS CloudFormation Guard — that enforces org-specific rules like "no IAM role may attach AdministratorAccess." Each stage is a job in a CI config file (a GitHub Actions YAML file, a GitLab .gitlab-ci.yml, a Jenkinsfile) that runs in seconds to minutes and either passes or blocks the merge. A minimal gate might look like:

- name: Policy check
  run: conftest test --policy ./policy k8s-manifests/
- name: Fail on critical CVEs
  run: trivy image --exit-code 1 --severity CRITICAL myapp:latest

Nothing here requires a human to remember a rule exists — the pipeline enforces it or the build fails, every time, for every engineer.

What are concrete examples of security-as-code policies?

Concrete security-as-code policies include: denying any Terraform plan that sets an S3 bucket ACL to public-read (the exact misconfiguration class behind the 2017 Verizon/Nice Systems exposure of 14 million customer records); requiring a signed SBOM in CycloneDX 1.5 or SPDX 2.3 format attached to every release artifact before it can be promoted to production; blocking container images that carry any CVE with a CVSS score of 9.0 or higher unless a time-boxed exception ticket is linked; requiring container images to carry a Sigstore/cosign signature consistent with SLSA Build Level 3 provenance before a Kubernetes admission controller will schedule the pod; and enforcing that Lambda functions cannot be deployed with a role that includes wildcard (*:*) IAM actions. Each of these is a short, testable rule — typically 10 to 50 lines of Rego, Sentinel, or Cedar — that replaces a paragraph in a written standard nobody re-reads after onboarding.

What are the measurable benefits of security as code?

The direct benefit of security as code is catching a misconfiguration in a pull request that takes seconds to fix instead of in production, where the same class of error caused the 2019 Capital One breach — a misconfigured web application firewall and overly permissive IAM role that exposed roughly 106 million customer records. IBM's 2023 Cost of a Data Breach Report put the average global breach cost at $4.45 million, and cloud misconfiguration remained one of the most commonly cited initial attack vectors in the underlying survey. Security as code moves the cost of finding that misconfiguration from "post-incident forensics" to "a failed CI check that blocks one PR," and it does so identically for the 1st and the 1,000th deployment, which a manual review process cannot promise. It also produces a durable audit trail: every policy evaluation is logged with the commit SHA, the rule that fired, and the outcome, which is exactly the evidence SOC 2 and FedRAMP assessors ask for during a control walkthrough.

What are the biggest challenges in adopting security as code?

The biggest challenge in adopting security as code is policy sprawl across incompatible languages — a typical platform team ends up maintaining Rego for Kubernetes admission, Sentinel for Terraform Cloud, and CloudFormation Guard for native AWS deploys, each with its own syntax and testing framework. A second challenge is false-positive fatigue: a poorly tuned SAST or SCA policy that fails 30% of builds on non-exploitable findings trains developers to add blanket suppressions rather than fix real issues, which defeats the point — most security code analysis tools ship default rule packs tuned for zero missed findings rather than low noise, which is exactly backwards for adoption. A third is coverage gaps from "ClickOps" — infrastructure changed by hand in the AWS or GCP console never passes through the pipeline that enforces the policy in the first place, so the control exists on paper but never actually runs. Getting past these requires prioritizing exploitability over raw CVE count and continuously reconciling deployed infrastructure against what's declared in code, not just writing more rules.

How Safeguard Helps

Safeguard operationalizes security as code by turning policy enforcement into signal you can actually act on instead of noise you suppress. Our reachability analysis traces whether a vulnerable function in a flagged dependency is actually called by your application code, so policy gates block builds for exploitable CVEs rather than every CVSS 9+ finding regardless of context — directly addressing the false-positive fatigue that kills security-as-code adoption. Griffin AI, Safeguard's detection engine, correlates SBOM data, reachability, and runtime context to prioritize findings the way a senior security engineer would, and Safeguard generates and ingests SBOMs in CycloneDX and SPDX formats automatically on every build so the artifact required by EO 14028 and NIST SSDF is never a manual afterthought. When a policy does catch a real, exploitable issue, Safeguard opens an auto-fix pull request with the dependency bump or config change already applied, so the fix lands with the same commit-and-review velocity as the original code — closing the loop from detection to remediation without leaving the pipeline.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.