Blog
Notes on cybersecurity, DevSecOps, and shipping secure software.
The analysis your supplier already did
Your vendor knows which CVEs in their component are actually reachable. They wrote it down. Then you retyped their conclusion into your own config, where it became a decision you are answerable for. Why consuming a VEX document beats copying it, and what the record looks like when the claim keeps its author.
A misconfiguration has no CVSS, which is why nobody fixes it
A privileged pod and a public S3 bucket have no CVE, no CVSS score and no NVD entry, so every IaC tool invents its own severity, and findings that would be a breach get sorted below dependency CVEs that are unreachable. Why misconfiguration findings get ignored, and what to rank them by instead.
CIS benchmarks are somebody else's checklist, and that is the point
A benchmark will flag things you have deliberately chosen, and treating every failed check as a defect is how teams end up ignoring the whole report. The value is not the score. It is the short list of checks you decided not to meet, and the record of who decided.
Most of your container CVEs aren't yours: base images and what to do about them
Scan a 35-line Python app and you get 292 findings. 219 of them, three quarters, come from the base image, and not one is fixable by changing your code. Why container scanning produces so much noise, what the actionable move actually is, and how VEX and reachability change the arithmetic.
Shift left became "run everything on every commit", which is why people turned it off
The idea was that feedback is cheaper the earlier it arrives. What got built was a pipeline that runs twelve scanners on every push, takes eleven minutes, and gets bypassed. The useful version is about latency and relevance, not about location.
The certificate nobody was watching: TLS as an availability problem
Expired certificates take down more services than TLS vulnerabilities compromise. The check is trivial, the failure is total, and it is nearly always owned by nobody, because the padlock was green the last time anyone looked.
The ignore file is where security programs go to die
Every scanner ships a way to make findings disappear, and every team uses it. The problem is not that risk gets accepted. It always does, but that the record of who accepted it, and why, and until when, does not survive the commit that added the line.
The license nobody gated on: copyleft in your dependency tree
A CVE is embarrassing and fixable. A copyleft obligation you have been shipping for two years is neither, and you find out during due diligence. How to gate a build on license policy with Trivy or Mend, why permissive licenses should not be findings, and why this belongs on a different threshold from your CVEs.
Threat intelligence in a build pipeline: useful only when it is narrow
Most threat-intel feeds are a firehose aimed at a SOC, and pointing one at a CI job produces noise nobody actions. Scoped to the specific hosts and images you already declared, the same data answers a question no scanner can: what has the outside world already observed about this?
Authenticated DAST finds the real bugs, and that is why it is hard to automate
An unauthenticated scan reaches the login page. Everything worth finding is behind it, which is why serious DAST means credentials, session handling and a spec, and why so many pipelines quietly run the shallow version instead. What each mode is actually good for, including where Draugr currently stops.
You don't need twelve scanners, you need to know which four apply
Security tooling is usually adopted in one of two ways: nothing, or everything at once. Both fail for the same reason. Nobody decided which controls the thing you actually build requires. A short way to work that out from what your software is made of.
Your CI logs are not evidence
The first time somebody asks you to prove a release was checked, the instinct is a screenshot of a green build. It will not survive the follow-up questions, which version, which checks, against what data, and would it produce the same answer twice.
Your CSP is strong and broken, and no scanner will tell you
Every header tool grades a Content-Security-Policy on strength. None of them checks whether it works. A policy that blocks your own scripts scores well and breaks the site, which is why so many teams ship a strong CSP in report-only mode forever, or a weak one that scores badly and works.
The SBOM you ship is half an answer: pairing CycloneDX with VEX
An SBOM tells your customers what you are made of. Left on its own, it also hands them a list of every CVE they can match against you, and no way to tell which ones matter. The other half is VEX, and most of it is already in your descriptor.
Findings where you're already looking: SARIF in your editor and the Security tab
A security finding you have to go looking for is a finding you fix later. Draugr writes standard SARIF, so a scan opens as inline squiggles in VS Code or JetBrains with no plugin of ours. Here is what it takes to make that actually work.
Your agent doesn't have a token problem: what raw scanner output costs an AI assistant
Four scanners on one small repo produce 2.3 MB to report 56 findings, and the bytes are the least of it. A third of those findings arrive with no severity, in three different path conventions, describing the same leaked key under two names. Something has to translate that before an agent can act.
Why we didn't build an AI pentester
Models can find bugs in code they've never seen. That commoditizes the pentester's craft, and leaves untouched the thing security tooling is actually for: the same answer, every time, cheap enough to run on every commit, with evidence someone will accept.
Your coding assistant is already answering security questions
Ask an assistant to check your repository for security problems and it will, by running whatever scanner it can find, over a scope it chose. On our demo app that missed 78 of the 99 things you'd fix first, all of them in a container image nothing told it about.
Scan any repo for vulnerabilities with zero config
Most security tools make you write config before you get a single result. Draugr scans a repo with no descriptor at all: draugr scan . runs SAST, SCA, secret and IaC checks over your code and ranks what it finds. Nothing to write first.
We pointed Draugr at itself: what happens when a security scanner runs its own gate
A security tool has no business gating your code if it can't survive its own gate. So we turned Draugr on Draugr, here's what it found, what we suppressed, and why the suppressions are the interesting part.
When everything is “critical,” nothing is: prioritizing vulnerabilities by real risk
Security scanners flag hundreds of “critical” issues, so which do you fix first? Severity is not priority, and what matters depends on where a problem lives and how much the business would feel it, which is context a scanner cannot see but your app description can.
Describe your app, not your scanners: one config for Trivy, Semgrep and Gitleaks
Security tooling breaks down at scale because teams wire up scanners instead of describing software. A declarative descriptor flips the model, and fixes the noise, the toil, and the cost.