When Security Rules Live in Documents, They Get Ignored
A security team spends weeks drafting a container image scanning policy. They send it via email, announce it in the all-hands meeting, and store it in the company wiki. Three months later, someone checks the production pipeline and discovers the scan was never enabled. The configuration was missing in one project, and nobody noticed.
This is not a story about bad intentions. It is a story about how rules break when they live outside the pipeline.
The Problem with Rules as Documents
Written policies have a fundamental weakness: they depend on humans to read, remember, and apply them correctly. Every team interprets the same rule differently. Every project has its own configuration quirks. When a rule changes, someone has to manually update every place it applies, and someone else has to verify the update actually happened.
The result is predictable. Some teams follow the rules. Some teams follow a slightly different version. Some teams forget entirely. And nobody knows which situation is happening until something goes wrong.
The difference between these two approaches becomes clear when you map the flow:
This is not a people problem. It is a delivery problem. The rules are not part of the system that delivers software. They exist outside it, as text that needs human translation into action.
Writing Rules as Code
Policy as code changes the delivery model for rules. Instead of writing policies in documents, you write them in a format that machines can read, store them in a repository, and execute them as part of the pipeline. The same workflow that handles application code now handles your security and compliance rules.
The format varies. Some teams use Rego from Open Policy Agent. Some use YAML with a defined schema. Some use the built-in policy frameworks from their existing scanning tools. The language matters less than the principle: rules are written, versioned, reviewed, and executed automatically.
Consider a simple rule: containers must not run as root. In policy as code, this becomes a clear statement that a policy engine can evaluate. The pipeline runs the engine against every container image before deployment. If the image runs as root, the pipeline stops. If the rule needs to change, someone edits the policy file, opens a pull request, and waits for review. The change goes through the same process as any code change.
What Changes When Rules Become Code
The first benefit is consistency. The same rule runs against every project, every pipeline, every deployment. There is no gap because someone forgot to enable a scan or because two teams configured the same tool differently. When a new rule is added, every pipeline picks it up automatically.
The second benefit is testability. Before policy as code, how did you know a new rule was correct? You might test it in a production pipeline, which is risky. Or you might skip testing entirely and hope for the best. With policy as code, you write tests for your rules. You create a test case where a container with root user fails the policy, and another where a non-root container passes. These tests run in CI, just like unit tests. If someone changes the rule and breaks the logic, the tests catch it before the rule reaches production.
The third benefit is auditability. Every rule change is recorded in version control. You can see who changed what, when, and why. You can roll back a bad rule change the same way you roll back a bad code change. When an auditor asks whether your containers run as root, you point to the policy file and the pipeline logs, not a document that might be outdated.
You Do Not Need to Write Everything from Scratch
A common misconception is that policy as code means writing every rule yourself. In practice, most rules come from existing frameworks. Security tools ship with policies for CIS benchmarks, regulatory frameworks, and common security patterns. You enable the ones that apply to your organization and adjust the thresholds to match your risk tolerance.
What you write from scratch is usually specific to your organization. Maybe your company prohibits deploying to certain cloud regions. Maybe every resource must have a specific set of labels. Maybe production deployments require a second signature. These are the rules that existing frameworks do not cover, and these are the ones that benefit most from being written as code.
The Practical Shift
Policy as code changes the relationship between security teams and engineering teams. Security no longer sends rules over the wall and hopes they get implemented. Security writes rules as code, submits them through the same review process as application code, and sees the results in every pipeline run.
Engineering teams no longer guess whether they are following the rules. The pipeline tells them immediately. If a change violates a policy, the build fails with a clear message. The team fixes the issue before it reaches production, not after an audit discovers it six months later.
A Quick Checklist for Getting Started
- Pick one rule that is currently documented but frequently violated.
- Write that rule as code using your existing security tool's policy framework.
- Add the policy check to your CI pipeline.
- Write a test that proves the rule catches violations.
- Write another test that proves the rule allows compliant changes.
- Remove the old document and point people to the policy file instead.
Start with one rule. Prove the workflow works. Then expand.
The Takeaway
Rules that live in documents are rules that get ignored. Rules that live in the pipeline are rules that get enforced. Policy as code is not about writing more rules. It is about making the rules you already have actually work, every time, for every change, without depending on someone remembering to read an email.