Brutalist Application Security (Updated)
After speaking with two Principal Engineers and a CTO, I decided to update the original post on Application Security. We collectively reached a similar conclusion on applying Security Brutalism to application security—especially within CI/CD pipelines that support modern tech stacks and a blend of cloud and local development environments. This approach embraces a philosophy of transparency, visible and unapologetic security measures, and infrastructure-aware controls. It prioritizes clarity over subtlety and enforces protection, even when the implementation feels a bit rough or intrusive.
Here’s how you can apply these principles to your setup:
Core Security Brutalism Tenets in Practice
1. Make Security Controls Visible and Unignorable
- Fail loudly and early: If a security check fails in CI/CD, make the error unambiguous and impossible to ignore. For example, reject secrets in commits with a red-flashing CLI.
- Force exposure of controls in developer workflows: If code must pass a security lint or static analysis, don’t hide it in a GitHub Action. Run it locally and in CI so devs experience the friction.
2. Immutable, Auditable, and Declarative Pipelines
- Embrace declarative CI/CD (GitHub Actions, GitLab CI, CircleCI) where the security config is code-reviewed and stored alongside the app code.
- Make all security gates (SAST, DAST, dependency checks, infrastructure as code scanning) part of the default pipeline and block merges until they pass.
3. Don't Trust Developer Devices—Verify Everything
For local development:
- Use pre-commit hooks to enforce secure coding patterns.
- Employ containerized dev environments to isolate code from local system entropy.
- Use signed commits (
git commit -S
) and enforce verification in the pipeline.
Security Brutalist twist: If you can't verify commit signatures, reject the merge. Make that policy loudly known.
4. Zero Implicit Trust in CI/CD
- Secure secrets via external secret managers (HashiCorp Vault, AWS Secrets Manager, etc), not CI/CD environment variables alone.
- Enforce signed artifacts and implement SBOM (Software Bill of Materials) tracking.
- Use runtime attestations.
Remember: Sign everything. Make developers see the cryptographic chain instead of hiding it behind trust-on-first-use assumptions.
5. Loud, Inflexible Policy Enforcement
- Treat policies like WAFs or firewalls: brutal, deterministic, unapologetic.
Examples:
- If you use an unapproved base image, the build fails—no exceptions.
- If a dependency is unpinned, your PR is rejected.
- If Terraform tries to open port 22 to 0.0.0.0/0, you get a Slack alert and the pipeline blocks.
6. Expose Risk Visibly in Git or UI
- Have bots post visible messages on PRs about security debt, for example:
This PR introduces 3 new dependencies, including one with known CVEs (CVSS 8.3). Link to triage: [Snyk dashboard]
- Label pull requests with security impact levels:
SEC-LOW
,SEC-HIGH
,SEC-REVIEW-BLOCKED
.
Security Brutalist Example Flow: Secure CI/CD Pipeline
[Developer]
↓
Local dev in Gitpod (containerized)
↓
Pre-commit hooks run Semgrep, secrets scanner
↓
Signed commit pushed → GitHub
↓
[CI/CD: GitHub Actions]
↓
[CD]
Final Security Brutalist Recommendations
- Do not hide security behind UX niceties Let devs feel the edge.
- Enforce policies as code, not by tribal knowledge or Slack messages.
- Accept friction as a signal—not a flaw.
- Be transparent about what failed, how, and why.
Security Brutalism focuses on truth over comfort. Make the security rules visible, inflexible, and codified into your developer lifecycle—both locally and in the cloud.