After reading this guide you can explain how a vulnerability class is eliminated by moving its safety preconditions into a safe API with a build-time conformance check, how to find the classes in your own findings data that pave well, and how to shift scanning effort as paving lands.
github.com/juliedavila/paving-vulnerability-classes. It holds every claim with its source and evidence grade, the eight-phase method, and the schemas, so a team of agents can run the analysis on an organization's own data.
How to read this guide
This guide is for security engineers, platform engineers and AppSec leaders who already have a backlog of confirmed vulnerabilities and want to know which of them could have been prevented by changing the platform rather than the developer. It assumes familiarity with SAST, DAST and CWE, and nothing else.
Every claim rests on one of five kinds of evidence, and the distinction matters when you take a recommendation to your own organization:
- Peer-reviewed: published in a refereed venue.
- Primary industry: the organization that did the work, reporting its own results.
- Secondary: a third party reporting someone else's results.
- Practitioner: widely practiced or argued, with little public measurement.
- Synthesis: an inference this guide makes from the above. These passages carry a Synthesis mark. Treat them as hypotheses to test against your data.
The companion repository holds the same material in machine-readable form: a register of 59 claims, each with its source, grade and caveats; JSON schemas for tagging findings and scoring candidate classes; and an eight-phase playbook written so that a team of LLM agents can run the analysis on an organization's own data with human checkpoints.
Safe APIs, build-time checks and audited exceptions retire whole classes
The prior art is real, and it converges. Google's Safe Coding work is the most rigorous public version. A vulnerability class persists because application code can reach a risky operation whose safety depends on preconditions the caller has to know. You eliminate the class by moving those preconditions into a safe API owned by a small expert team, enforcing at build time that nobody calls the raw operation, and running an audited exception path for the rare legitimate need. Google reports close to zero residual rates of XSS and SQL injection across many of its user-facing applications built this way.
The question to ask of every finding is "what did the developer call, and what did they have to know to call it safely?" This guide calls it the precondition question. It moves the conversation from who made the mistake to who should own the knowledge. Findings that cluster on the same sink with the same missing guard are paving candidates.
Not everything paves. Context-free preconditions (output escaping, parameter binding, safe parsing) pave well. Business-specific preconditions (authorization on a particular object, workflow rules) pave only partly, through framework hooks and default-deny, and still need detection behind them.
Adoption is the bottleneck. The developer-experience research says developers take the easiest path that works, so the secure path has to be the easiest path: the best examples, fast low-noise feedback inside code review, and an exception process that doesn't feel like punishment. Safe libraries without a conformance check and migration tooling go unused.
Scanners change jobs. As paving lands, retire the scanner rules that find instances of now-paved classes, one class and one conforming repository at a time, behind an evidence gate that includes a planted positive control. Keep the detectors that verify the paved road holds. Move the freed triage attention to authorization and business logic, the classes paving can't reach.
The gap. A structured literature screen found no controlled study of what secure-by-default adoption does to developer experience or security outcomes, and no published end-to-end method for turning an organization's own vulnerability history into a paving roadmap. This guide assembles one from adjacent work. Measure your own results, and publish them if you can.
Where the idea came from
The thread runs from academic usable-security work, through a long run of web-framework research, into a handful of large engineering organizations that proved it at scale.
- 2000. Viega and Evans, Separation of Concerns for Security: isolate security as its own concern, because most developers know little about writing secure code.
- 2007. Livshits and Erlingsson show that modifying a web construction framework, rather than each application, can eliminate a wide range of script injection with little or no developer change (PLAS 2007).
- 2008. Wurster and van Oorschot, The developer is the enemy: teaching every developer to be a security expert is unrealistic, so focus on the people who build the APIs everyone else consumes, and make the path of least resistance the secure one.
- 2014. Kern, Securing the Tangled Web (CACM 57:9): the early public account of Google's inherently safe web APIs.
- 2016. Green and Smith, Developers are not the enemy!: the counterpoint. Developer mistakes trace back to unusable security APIs.
- 2017. Netflix's application security team builds the "paved road" for its studio platform. Security review collapses to a yes/no question: does the team use the paved-road product? (Netflix Technology Blog)
- 2019. Meta publishes Designing Security for Billions, describing Hack and XHP as frameworks that help prevent whole bug classes, XSS included.
- 2021. Wang, Bangert and Kern, If It's Not Secure, It Should Not Compile (ICSE): the peer-reviewed mechanics of API hardening against DOM XSS at Google scale.
- 2024. Kern, Developer Ecosystems for Software Safety (ACM Queue; CACM reprint), Google's Secure by Design whitepaper, and Android's memory-safety results. CISA's Secure by Design program cites the same body of work.
The frame has since moved from "secure libraries" to "secure developer ecosystems": languages, frameworks, build tooling and the production platform together, designed per application archetype (web service, mobile app, data pipeline), so that a threat model is solved once and amortized across every application of that shape.
OWASP Proactive Controls and ASVS catalogue defensive controls and verification requirements, and they are useful vocabularies for naming paving mechanisms and writing conformance criteria. Neither prescribes how to mine an organization's own history.
A class is paved when its preconditions live in the API
A vulnerability class persists because application code can reach a risky operation whose safety depends on something the caller must know: escape for this HTML context, bind these parameters, validate this URL against an allowlist, check that this user owns this object. Strip the literature down and every successful program that removes such a class has the same three parts.
Safe API. A replacement for the risky primitive that carries its own precondition, usually as a type. A SafeHtml value can only come from a builder that escapes or sanitizes; a query type accepts only compile-time constants plus bound parameters.
Conformance check. A compile-time or CI check that fails the build when application code calls the raw primitive. This is what turns a recommendation into an invariant. Google's ICSE paper describes "a simple yet capable compile-time checker."
Audited escape hatch. A way to do the unsafe thing for a legitimate need, routed through security review and counted. Without it, teams fork or route around the platform.
Google's account is explicit that scale came from rigorous tooling and consultant support, so that tens of thousands of engineers could adopt the APIs "without significant productivity impact." The safe API alone did not do it. A paved road also needs an owner: a team funded to maintain it, and a place (central build, dependency authority, platform) where conformance can be enforced.
Two kinds of paving
- APIs that carry preconditions fix classes rooted in how code calls a primitive: injection, XSS, unsafe deserialization, crypto misuse, path traversal.
- Placement fixes classes rooted in something every service has to do identically: authentication, transport security, rate limiting, secrets delivery. Put it in a gateway, mesh or platform layer and the property becomes structural. Every request is authenticated because of where the service sits, and no team has to remember. Netflix's result is that assurance becomes a yes/no question per service.
The archetype idea
Kern's 2024 argument is that the unit of design is the application archetype, because each archetype shares a threat model that can be solved once. A roadmap organized by archetype ("the paved web service," "the paved batch job") often lands better than one organized by library.
Where detection fits
Kern names two key aspects of assurance at scale: Safe Coding, and secure design for application archetypes. He is blunt about after-the-fact detection: code review, testing, scanning and fuzzing "find only a fraction" of defects and are "inherently incomplete" for large systems. That is the case for paving.
Detection still has a role, for reasons outside that paper. Safe frameworks carry residual risk; an outside researcher notes that a Trusted Types policy can contain a mistake or rely on a sanitizer with a bypass. Android credits part of its gains to parallel work on its remaining unsafe code. Google still runs static analysis in code review, under strict noise limits. From scanner volume to paved roads covers how detection's job changes.
Mining a vulnerability history
No public source describes turning an organization's own vulnerability history into a paving roadmap end to end. The method below combines three bodies of work: empirical studies of security patches, fix-pattern mining from program-repair research, and root-cause and variant-analysis practice.
1 · Link every finding to its fix
A finding record says what was wrong. The fix diff says what knowledge was missing, and that knowledge is what you want to move into an API. Research datasets show linking is tractable: SAP's manually curated fix-commit dataset (624 vulnerabilities, 1,282 commits), CVEfixes for automated collection, and Hommersom et al. for ranking candidate fix commits when the link is missing, which puts a true fix in the top 10 for 84% of open-source advisories.
Where history allows, trace the introducing change too, with SZZ-style blame on the lines the fix changed. It is noisy, but it carries workflow signal. Meneely et al. found vulnerability-contributing commits had more than twice the churn of other commits and were twice as likely to come from someone new to that code (one project). Iannone et al., across 3,663 vulnerabilities, found most were introduced by developers under high workload, often during maintenance. That is developer-experience evidence hiding inside a security dataset.
When there are no fix links, the method still runs on finding descriptions, with weaker evidence; Section 12 covers that branch.
2 · Classify by root cause, not by CWE alone
CWE names the symptom and is labeled inconsistently across sources. Paving decisions need a few extra fields per finding.
| Field | Question it answers | Example values |
|---|---|---|
sink | What primitive or API did the vulnerable code call? | innerHTML; raw SQL exec; ObjectInputStream; HTTP client with a user-supplied URL |
sink_family | Which group of sinks could one safe API replace? (closed vocabulary) | html_output; sql_exec; deserialization; outbound_http |
precondition | What did the caller have to know or check to call it safely? | escape for the HTML attribute context; bind parameters; allowlist hosts; check object ownership |
precondition_kind | Is that knowledge context-free, archetype-specific or business-specific? | context_free · archetype_specific · business_specific · unresolved, plus a business_residual flag |
layer | Where did the defect live? | app code · shared library · framework config · IaC · platform |
fix_shape | What did the fix change? | added guard · swapped API · config flip · moved to platform · logic rewrite · compensating control |
found_by | Which detection sources reported it? (all of them) | SAST · DAST · pentest · bug bounty · incident · code review |
evidence_basis | What do the tags rest on? | fix diff · code read · description only |
precondition_kind decides abstractability. Use business_residual when a context-free floor exists but safe use also needs business knowledge. Every tag field may be null: when the evidence doesn't name a sink or precondition, leave it empty rather than guess, and record that in evidence_basis.
Two common tagging errors are worth naming. Copying CWE into precondition loses the signal: CWE-79 is a symptom, while "output written into an HTML attribute through the shared render helper without context-aware escaping" is a precondition. And a one-line authorization fix is not context_free; ask whether the check could be written without knowing the business rule.
LLMs are reasonable first-pass taggers. Zero-shot retrieval-augmented CWE labeling has been shown competitive with trained models, and Haddad et al. released 4,012 hand-labeled CVE-to-CWE mappings for evaluation. Measure reliability anyway: calibrate on 30 to 50 shared findings, double-tag a sample, and compute Krippendorff's alpha on the closed-vocabulary fields with a target of at least 0.67. When the taggers are agents running on the same model, they share blind spots, so the agreement between agents and a human on at least 30 records is the figure to report.
3 · Cluster on root cause; read the fixes as evidence
Group findings by sink_family and normalized precondition. Then use the fix diffs to confirm and to choose the remedy. Several studies show recurrence living in the fixes:
- Bui et al. (2023): security fixes are short but distinctive, and many add method calls with input-validation names like
encode,normalizeandtrim(Java). - Iannone et al. (2023): vulnerabilities fall into 144 categories and are removed mostly by adding new checks on inputs.
- Campos and Maia, across 4 million bug-fix commits: developers often forget to add
ifpreconditions (Java).
Each time the same guard is added around the same sink, that guard belongs inside an API. At internal-dataset scale (hundreds to low thousands of findings), grouping in a spreadsheet gets most of the way; for larger sets, program-repair techniques like FixMiner cluster AST-level edit scripts into reusable patterns. Keep business-specific clusters rather than discarding them: they usually become mechanism-level paving (default-deny, a declared policy per handler) plus detection. And don't let a small high-severity cluster hide under a large low-severity one.
Historical fix pairs are also a rule-authoring corpus. In one Java study, 28 insecure/secure code pairs yielded 21 reusable detection-and-repair templates at 95% precision, with 76 of 77 suggested repairs correct (Zhang et al., ICPC 2022).
4 · Run variant analysis before designing the API
Incomplete fixes are common. 7% of open-source security fixes failed to fully close the hole (Li and Paxson 2017). Project Zero reported that at least half of the 18 zero-days exploited in the wild in the first half of 2022 were variants of earlier bugs that hadn't been fully fixed (secondary reporting, SecurityWeek). The pattern: the fix blocked the proof-of-concept path while the root cause stayed reachable another way.
For each candidate class, query the whole estate for the same sink family with CodeQL, Semgrep or internal code search. The historical findings are a sample; the variant count is the real denominator and the migration scope. Label a random sample of hits (vulnerable now, safe by context, already on a safe API, unsure) to estimate how noisy a conformance check built from that query would be. The same query later becomes the conformance check.
5 · Sequence using vulnerability decay
Android's memory-safety bugs fell from 76% to 24% of its vulnerabilities over six years, mostly by writing new code in memory-safe languages rather than rewriting old code. The explanation offered is that vulnerabilities decay exponentially, so most live in new or recently modified code. Alexopoulos et al. independently measured average vulnerability lifetimes of about four years in open source, roughly exponentially distributed.
The rollout implication: make the paved road mandatory for new code and touched files first, migrate old code where it is hot or exposed, and leave stable cold code for last. Exposure overrides age; old internet-facing code can still justify early migration.
Deciding what to pave
The five gates
- Recurrence and cost. Enough findings and severity to justify a platform investment. One-offs don't.
- Context-free precondition. The dominant safety rule can be encoded without business knowledge, or a mechanism-level floor exists (such as default-deny).
- Choke point. In code, one API or control could replace the sink family. In the organization, a team could own it and somewhere exists to enforce it.
- Off-road use is detectable with near-zero false positives. Name the check. If no check exists, you have a library and no guardrail.
- Migration is bounded. Call-site counts and codemod feasibility make migration tractable.
A failed gate removes a candidate from the ranking; keep it in the report with the reason. An unknown keeps it in, flagged.
The ranking
Estimate low and high ranges in engineer-hours over a stated horizon (three years is a sensible default):
class_cost = findings_per_year × mean_fix_hours × horizon_years
paving_cost = build + migrate + enforce + maintain + exceptions
ratio = class_cost × addressable_share × expected_adoption ÷ paving_cost
Severity enters once, as a second, weighted ranking (a convention such as critical 8, high 4, medium 2, low 1), rather than inside the cost terms, where it tends to get counted several times over. If the unweighted and weighted rankings pick different top three, that disagreement is worth discussing explicitly.
expected_adoption is the term most programs leave out and the one that sinks them (How this goes wrong). A reasonable discipline: unless the plan includes both an enforcing conformance check and migration tooling, cap the high end of expected adoption at 0.3.
Select two or three classes. Name the strongest runner-up and why it was cut, and state how stable the top three are across the low and high ends of the estimates.
Which classes pave well
| Class | Paving mechanism | Evidence | Fit |
|---|---|---|---|
| XSS, incl. DOM XSS | Typed safe-HTML values, auto-escaping templates, Trusted Types enforced by CSP | Peer-reviewed (ICSE 2021); Google reports about one XSS per year across its high-assurance-framework services; secondary reporting of no DOM XSS across 130+ Trusted Types services | High |
| SQL and query injection | Query builders that accept only compile-time constants plus bound parameters; ban raw string execution | Primary industry: close to zero residual rates in many Google applications | High |
| Memory safety | Memory-safe language for new code; interop with legacy | Primary industry: Android, 76% → 24% | High (high cost) |
| Crypto misuse | Misuse-resistant high-level crypto API with secure defaults and key management | Peer-reviewed (Acar 2017): simpler APIs help, but documentation and examples matter as much | High |
| Authentication | Gateway or mesh enforcement; services never parse credentials | Primary industry: Netflix paved road | High |
| Insecure framework defaults | Organization-wide hardened configuration baseline per framework | Peer-reviewed (Islam et al., SecDev 2020, Spring Security) | High |
| Deserialization, XXE, SSRF, path traversal | Wrapped parsers with safe defaults; egress-allowlisted HTTP client; safe path-join API | Practitioner | High |
| Secrets in code | Secret-manager client as the only configuration path; literal detection as the guardrail | Practitioner | High |
| Cloud and IaC misconfiguration | Hardened modules plus policy-as-code admission checks | Practitioner; CNCF secure-defaults guidance on gradual, reversible rollout | High |
| Vulnerable dependencies | Automated update PRs as the default path; lockfiles and a vetted internal registry | Peer-reviewed (Mohayeji et al., MSR 2023, npm only) | High (known-vulnerable versions) |
| Supply-chain integrity | Registry firewall; provenance and signature checks at the build authority | Practitioner | High (where builds are centralized) |
| Authorization, IDOR | Framework-level default-deny; every handler declares a policy; policy as data; detection behind it | Peer-reviewed detection research (RoleCast, MACE, Nemesis, GuardRails); developers frequently omit access-control checks | Partial |
| Business logic, workflow abuse | Threat modeling; security constraints written into specifications; abuse-case tests; domain types that encode invariants | None convincing | Low |
Reading the table against data
- A class marked high that barely appears in the data may be under-detected, or may already be paved. Check which before dropping it.
- A partial class that dominates high-severity findings deserves attention even though it paves badly. What paves in authorization is the mechanism: a framework that forces every handler to declare a policy and denies by default. The policy content stays business-specific. "No handler ships without a declared policy" is the realistic first guardrail.
- The data will surface classes not listed here, often organization-specific sinks such as an internal templating helper or a shared HTTP wrapper. Those are frequently the best candidates, because the organization already owns the choke point.
Developers take the easiest path, so the safe path has to be easiest
Developers take the easiest path that works
In a lab study, Android developers limited to Stack Overflow wrote significantly less secure code than those using official documentation, and those limited to official documentation wrote significantly less functional code (Acar et al. 2016). Only 17% of the Stack Overflow threads participants used contained secure snippets. At ecosystem scale, 15.4% of 1.3 million Android apps contained security-related Stack Overflow snippets, and 97.9% of those apps had at least one insecure snippet (Fischer et al. 2017). The paved road has to win on findability and copy-pasteability: if the secure example isn't the first thing a developer, or their AI assistant, finds, the insecure one wins.
Simple APIs aren't enough without documentation and examples
Acar et al.'s 256-developer crypto study found simplified APIs reduce bad parameter choices, but poor documentation, missing examples and missing features such as key storage still sank participants. About 20% of functionally correct solutions were insecure while the developer believed them secure (Acar et al. 2017). A paved road that covers most common tasks but not all of them sends developers off-road for the missing one, and they often don't come back.
The problem is organizational, not individual
Assal and Chiasson's survey of 123 developers found security problems "frequently stem from a lack of organizational or process support," and that developers were self-motivated toward security (CHI 2019). Mokhberi and Beznosov's systematization across 126 papers sorts developer challenges into 17 areas across human, organizational and technological dimensions (EuroUSEC 2021). A case study found that appointing security champions without expert and management support produced widely varying results (Gutfleisch et al. 2023).
Guardrails live or die on false positives and placement
In 20 developer interviews, false positives and how warnings are presented were among the barriers to using static analysis (Johnson et al. 2013). Google's answer is the most useful operational standard in the literature (Software Engineering at Google, ch. 20):
- A new check must "produce less than 10% effective false positives," where an effective false positive is any result developers take no positive action on, including a real bug they misunderstood. The overall rate runs "just below 5%." Compiler-level checks must produce none.
- "Code review is a sweet spot for analysis results." Results appear as review comments on changed lines only, with "Not useful" and "Please fix" buttons, and analyzers with high "Not useful" rates get disabled.
- Blocking presubmit checks are a separate, smaller tier.
Fixes beat findings. A bot that opened fix PRs for static-analysis violations had 57% merged, and those PRs were evaluated faster than ordinary ones (C-3PR, SANER 2020). Security advice placed at the API call site led 73% of participants to fix insecure crypto code (Gorski et al., SOUPS 2018, 53 participants). Most tools are still weak here: a review of 46 static-analysis tools found more than half had poor warning messages and three-quarters offered hardly any fix support (Nachtigall et al. 2022).
The DevEx frame
Noda, Storey, Forsgren and Greiler reduce developer experience to three dimensions: feedback loops, cognitive load and flow state (ACM Queue 2023). Synthesis: The mapping onto paving is direct. A good paved road removes cognitive load, because there are fewer security decisions to make. A good guardrail is a fast feedback loop: it fires at review time with a fix attached. A bad guardrail breaks flow by arriving late, noisy, or blocking without explanation. Surveying developers on those three dimensions before and after a rollout gives you a developer-experience measure.
Practitioner consensus
Practitioner writing (tl;dr sec on secure defaults, Jason Chan on the origin of the paved road, and golden-path writing from platform teams) lines up with the research. The road should be prescriptive but flexible, mostly invisible in daily work, and come with a real migration path. Going off-road stays permitted and unsupported, which by design makes it the worse experience.
Guardrails escalate from paved defaults to nudges to blocks
Pave. Templates, scaffolds and defaults make the secure path the one you get without deciding. No friction, no enforcement. Entry: a safe API exists. Use: new services on the archetype.
Nudge. A review-time comment with a one-click fix when raw use appears. Entry: the check runs under 10% effective false positives, or it gets turned off. Use: migrating existing code.
Block. Build or presubmit failure on raw use, with a named, reviewed, counted exception path. Entry: the safe API covers the common tasks, the check is near-zero false positive, and a codemod exists.
Treat exception requests as product data. A rising count for one class means the safe API is missing a use case, and that belongs on the platform team's backlog. A falling count with stable incidence is part of the evidence for retiring scanner rules (Section 09).
From scanner volume to paved roads
Most organizations start this work with a full stack of high-volume scanners (SAST, DAST, IAST, SCA) and are adding AI-assisted review that is higher fidelity but still imperfect. No published study measures what happens when scanners are retired as paving lands. This section gives what the sources do support, then a model for the transition.
What the evidence says
- Detection can't carry the load alone. Kern's two key aspects of assurance are Safe Coding and secure archetype design; after-the-fact discovery "find[s] only a fraction" of defects and is "inherently incomplete" for large systems (ACM Queue 2024).
- For conforming code, the conformance check is the assurance. Code built only on hardened APIs, with the compile-time check passing, inherits the framework's guarantee. Netflix describes review collapsing to whether a team uses the paved-road product.
- Independent layers catch different things. Google reports that Trusted Types catch more than 60% of DOM XSS that static analysis misses. An outside researcher, Michał Bentkowski, warns that a policy can still contain a mistake or rely on a sanitizer with a bypass (secondary reporting, PortSwigger).
- Today's SAST is noisy and incomplete on real vulnerabilities, at least in C/C++. Across 815 vulnerability-contributing commits in 92 projects, a single SAST tool warned in the vulnerable function for 52% of commits, at least 76% of warnings in vulnerable functions were irrelevant, and 22% of commits got no relevant warning from any of five tools (Charoenwet et al., ISSTA 2024).
- The noise standard is the gate. Under 10% effective false positives for new checks, with limited extra tolerance only for analyses that catch critical problems (SWE at Google, ch. 20).
- Automated fixes outperform findings. Developers merged 57% of Dependabot security updates, and bot-mediated fixes happened 1.8 times as often as manual ones; unmerged updates took months to resolve by hand (Mohayeji et al., MSR 2023).
- "Shift down." Google Cloud uses the term for moving controls into the platform so developers don't carry them, layered on top of shift-left (Google Cloud; Venables at RSAC 2025, via tl;dr sec).
- AI is arriving as both finder and migration tool. Big Sleep found an SQLite flaw attackers were preparing to exploit; CodeMender is pitched as rewriting code to remove whole classes. Both rest on vendor announcements so far (The Record; The Hacker News).
A model: split scanners by the job they do
| Job | Examples | As paving lands |
|---|---|---|
| 1. Find instances of pavable classes | SAST injection, XSS and crypto-misuse rules | Retire: per class, per conforming repository, behind the gate. Most of the volume and noise lives here. |
| 2. Verify the paved road holds | Off-road detection queries; DAST and IAST against paved services; bug bounty | Keep and repurpose: The old SAST rule becomes the conformance query; runtime testing becomes the independent check on the framework. Pull these last. |
| 3. Find what can't be paved | Authorization, business logic, workflow abuse | Invest: Point AI-assisted review and threat modeling here, with the triage time freed from job 1. |
If one detection source is the only signal for a class, the conformance check has to replace it before its rules retire.
The retirement gate
- The repository routes every use of the sink family through the safe API, verified by the conformance query.
- The conformance check has blocked for at least a quarter, with effective false positives under 5% on reviewed results.
- The exception count for the class is flat or falling for two consecutive quarters.
- No confirmed class findings from any non-SAST source over a window in which the historical rate predicts at least three.
- Positive control: a planted off-road instance in a test branch is caught by the remaining backstop (conformance check, runtime test or review).
Criterion 4 alone proves little, because a blocking conformance check zeroes the old rule's output whether or not the safe API is correct. The positive control is what shows the backstop works. For classes with no runtime detector, such as crypto misuse or deserialization, the conformance check and the positive control carry the gate.
Where auditors or customers review assurance evidence, conformance results plus a tested backstop make a stronger record than a findings count. Expect to explain that shift to them.
The business-logic point
What to compute from the data
- The share of historical findings, by count and by severity, in job-1 classes. This is the ceiling on scanner noise that paving can remove.
- For each job-1 class, the detection-source mix, to find sole-signal rules.
- The share of high-severity findings in job-3 classes. This sizes the review and threat-modeling investment.
How this goes wrong
Each failure mode below comes with the check that catches it.
| Failure | What it looks like, and the evidence | Check |
|---|---|---|
| Nobody adopts the framework | The safe library exists; raw use continues. A Meta security engineer describes roughly 15 underused Android secure-by-default frameworks: wrapping dangerous functions "works in theory" but struggles at scale (NorthSec abstract). | Does the plan include a conformance check and a codemod? |
| Fixing the instance, not the cause | The fix blocks the reported path; the root cause stays reachable. 7% of open-source security fixes were incomplete; about 3% of Apache vulnerabilities reappeared in later releases (Piantadosi et al. 2019). | Was variant analysis run for the class? |
| Fixes introduce new bugs | Remediation churn creates new findings. In JavaScript projects, fix commits introduced new vulnerabilities in 82% of projects studied (Bandara et al. 2020; scanner-based, so indicative). | Does the plan concentrate fixes in one tested API? |
| Guessed tags | Sinks or preconditions filled in without evidence, especially by LLM taggers. | Are tags null where evidence is missing, with the evidence basis recorded? |
| Gate passes by construction | "Zero findings" reported after the rule that produced findings was retired. | Did a planted positive control pass? |
| No owner | A safe API ships with no team funded to maintain it. | Is an owning team named? |
| The road covers most tasks, not all | Teams leave the road for the one task it can't do (Acar 2017). | Are exception requests tracked and fed back? |
| Labels drift | CWE is inconsistent across sources and over time. | Are decisions based on sink and precondition tags, with agreement measured? |
| Detection bias | Scanner-friendly classes dominate the ranking. | Were counts weighted by detection source and severity? |
| Old code eats the budget | The migration plan rewrites stable legacy code first. | Is the rollout ordered new and touched code first? |
| Scanners pulled too early | Rules retired because paving is planned, before conformance blocks. | Does every retirement pass the gate? |
| Too many classes | The roadmap selects six or ten classes and finishes none. | Are two or three selected, with reasons for the cuts? |
| Overclaiming | Synthesis presented as established fact. | Does each recommendation cite its evidence and grade? |
AI-generated code makes build-time invariants more valuable
Code assistants reproduce whatever patterns are common, which is the Stack Overflow copy-paste problem at higher volume. About 40% of 1,689 programs Copilot generated across 89 security-relevant scenarios were vulnerable (Pearce et al., IEEE S&P 2022; a 2021-era model). Rule sets that feed secure defaults into agent context, such as Project CodeGuard, are early attempts to act at the generation step.
- A conformance check doesn't care who wrote the code. As generation outpaces human review, a build-time invariant scales where review can't.
- Safe APIs are easier for models to use correctly, for the same reason they're easier for people: fewer preconditions to get right. Put the paved-road APIs in the agent's context through rules files, scaffolds and retrievable internal docs, and you shift what gets generated.
- The fix history doubles as an evaluation set. Before/after fix pairs are exactly what you need to test whether an assistant follows the paved road.
- AI as the migration tool. Codemods written or assisted by AI can lower the migration-cost term in the ranking. Validate them the way you would any automated fix.
The analysis runs in eight phases with human checkpoints
The companion repository turns mining and deciding what to pave into an eight-phase procedure, each phase with inputs, steps, outputs and exit criteria. It is written so that a human team or a team of LLM agents can run it on data whose format isn't known in advance: a scanner export, a ticket dump, pentest reports, bug-bounty submissions, or several at once.
| Phase | Name | What happens |
|---|---|---|
| 00 | Profile the data | Inventory sources; map fields; pin down what "true positive" means here; propose an archetype vocabulary; profile distributions; write down what the data cannot tell you. Human checkpoint. |
| 01 | Normalize and link | One record per root cause; deduplicate across tools while keeping every source; link fixes (explicit references first, then ranked candidates); trace introducing changes for a sample. |
| 02 | Tag root causes | Calibrate on shared findings; write a tagging guide with a closed sink-family vocabulary; tag; measure agreement; revise once. |
| 03 | Cluster | Group by sink family and precondition; merge or split by which single intervention would serve; assign a mechanism hypothesis. |
| 04 | Score candidates | Five gates, a quick variant pass on the top five, two rankings, two or three picks plus a named runner-up. Human checkpoint. |
| 05 | Variant analysis | Query the estate for each selected sink family; label a sample of hits; size the migration. |
| 06 | Sequence and transition | Rollout order, tier progression, a scanner job map with sole-signal flags, retirement gates, the exception process. |
| 07 | Plan and measure | Final report and one-page brief per class; the measurement plan; a skeptic review against the failure modes. Human checkpoint. |
Size paths
| Root-cause records | Approach |
|---|---|
| Fewer than about 100 | Small. Tag everything; one tagger plus a human adjudicator; report counts, not shares; say plainly that rankings are directional. |
| About 100 to 1,500 | Standard. Tag everything; double-tag at least 10% and at least 50 records. |
| More than about 1,500 | Sampled. Stratified random sample (source × first detection source × severity), at least 20 per stratum; extrapolate with stratum weights and report intervals; double-tag at least 100. |
Scanner exports count instances, not root causes. Collapse them first, using the most specific key the data supports: rule, repository and fix commit; then rule, repository and file; then rule and repository. Report both counts.
Access constraints
- Findings, fixes and code search: the full procedure.
- Findings and fixes, no estate-wide search: variant analysis becomes "write the query and hand it to whoever can run it," and the migration gate stays unknown until results return.
- Findings only: tag from descriptions and leave sinks and preconditions null where the text doesn't name them. Clusters built that way are hypotheses, the ranking is provisional, and the first recommendation is to obtain fix links or code access for the top candidates.
Do not fabricate call-site counts, sinks or fixes to fill a field. Null and unknown are valid answers.
Measuring the result
Track per class: incidence per application or per thousand changes, paved-road adoption share, open and new exceptions, the conformance check's effective false-positive rate, time to first deploy for a new service on the paved road, and a DevEx baseline and follow-up. Teams that adopt early differ from those that don't, so a plain adopted-versus-not comparison is biased. Prefer a staggered rollout with the order fixed in advance, and compare before and after across waves (difference-in-differences). Google reports XSS in its high-assurance-framework services at roughly one per year across the company; incidence falling toward zero in adopted applications while staying flat elsewhere is the kind of evidence to aim for.
A focused first pass
Two or three classes done properly beat a taxonomy of twenty.
- Weeks 1-2. Pull the dataset, link fix commits, and tag a stratified sample of a few hundred findings (LLM first pass, human adjudication). Keep every detection source and the severity.
- Weeks 3-4. Cluster on sink family and precondition, run the five gates on the top clusters, and run an estate-wide variant query for each finalist to get real call-site counts.
- Weeks 5-6. Pick the top two or three. For each, answer four questions: does a safe API already exist internally or in the ecosystem, what is the conformance check, what is the codemod, and who owns the escape hatch? Take a DevEx baseline of the target teams.
- Then. Ship the pave and nudge tiers for new and touched code; move to block once effective false positives are low and exception volume has settled. Report incidence per class quarterly.
Decide early whether the deliverable is a library roadmap or an archetype roadmap ("the secure web service," "the secure batch job"). Kern's argument is that archetypes are where the amortization happens; if the data concentrates in a few application shapes, lean archetype.
Seven gaps remain open for anyone who runs the method
- No published end-to-end method exists for turning an organization's own vulnerability history into a paving roadmap. This guide assembles one from adjacent work, and it has not yet been run end to end on a real dataset. Results, positive or negative, would be valuable to publish.
- Transfer. The best-measured results (XSS, SQL injection, memory safety) come from organizations with unusual central control over languages and build tooling. How well they transfer to more heterogeneous estates is not well measured.
- Narrow empirical base. Several supporting studies cover one language or ecosystem (Java, C/C++, npm) or one project. Treat their figures as indicative elsewhere.
- Developer-experience outcomes. A structured screen of the literature (about 200 papers retrieved, 11 screened in) found no controlled study of secure-by-default adoption effects on developer experience, productivity or security outcomes. The strongest outcome evidence is industry self-reporting.
- Scanner retirement. No study measures risk when scanning volume is reduced as paving lands. The retirement gate in Section 09 is a design proposal.
- Specifications as the lever for business logic is a hypothesis with no direct evidence yet.
- Secondary figures. The Trusted Types service counts and the 2022 zero-day variant figure come through secondary reporting; confirm them at the primary source before relying on them externally.
How this was made
Question. Given an organization's history of true-positive vulnerability findings, which vulnerability classes can be engineered out of existence with secure-by-default frameworks, libraries, APIs and platform controls, and how is that rolled out without hurting developer experience? A follow-up asked how high-volume scanning shifts toward AI-assisted review and paved roads. Set by Julie Davila in October 2026.
Process. AI research agents built on Anthropic Claude models searched the public literature and industry sources; a structured literature screen in Elicit covered the academic side. The agents drafted the guide and the companion repository. A separate adversarial review pass then checked the claims against their primary sources and scrubbed method and publication details, and every fix it found was applied before publication. Julie Davila reviewed the result.
What was checked. Every factual claim is listed with its source, grade and caveats in the repository's claims file. Passages marked Synthesis are inferences drawn in the guide itself and should be tested against your own data.
Sources
The full bibliography, with every claim it supports, is in the companion repository's sources.yaml and claims.yaml.
Peer-reviewed (44)
- Wang, Bangert, Kern. If It's Not Secure, It Should Not Compile: Preventing DOM-Based XSS in Large-Scale Web Development with API Hardening. ICSE 2021.
doi.org/10.1109/ICSE43902.2021.00123 - Sadowski et al. Lessons from Building Static Analysis Tools at Google. CACM 2018.
research.google/pubs/lessons-from-building-static-analysis-tools-at-google - Livshits, Erlingsson. Using web application construction frameworks to protect against code injection attacks. PLAS 2007.
doi.org/10.1145/1255329.1255346 - Wurster, van Oorschot. The developer is the enemy. NSPW 2008 (proceedings published 2009).
doi.org/10.1145/1595676.1595691 - Green, Smith. Developers are not the enemy! The need for usable security APIs. IEEE S&P Magazine 14(5), 2016.
doi.org/10.1109/MSP.2016.111 - Li, Paxson. A Large-Scale Empirical Study of Security Patches. CCS 2017.
doi.org/10.1145/3133956.3134072 - Iannone et al. The Secret Life of Software Vulnerabilities: A Large-Scale Empirical Study. IEEE TSE 2023.
doi.org/10.1109/TSE.2022.3140868 - Meneely et al. When a Patch Goes Bad: Exploring the Properties of Vulnerability-Contributing Commits. ESEM 2013.
doi.org/10.1109/ESEM.2013.19 - Ponta et al. A Manually-Curated Dataset of Fixes to Vulnerabilities of Open-Source Software. MSR 2019.
arxiv.org/abs/1902.02595 - Bhandari, Naseer, Moonen. CVEfixes: automated collection of vulnerabilities and their fixes from open-source software. PROMISE 2021.
arxiv.org/abs/2107.08760 - Hommersom et al. Automated Mapping of Vulnerability Advisories onto their Fix Commits in Open Source Repositories. TOSEM 2024.
arxiv.org/abs/2103.13375 - Bui et al. APR4Vul: an empirical study of automatic program repair techniques on real-world Java vulnerabilities. EMSE 2023.
doi.org/10.1007/s10664-023-10415-7 - Campos, Maia. Discovering common bug-fix patterns: A large-scale observational study. JSEP 2019.
doi.org/10.1002/smr.2173 - Koyuncu et al. FixMiner: Mining relevant fix patterns for automated program repair. EMSE 2020.
arxiv.org/abs/1810.01791 - Zhang et al. Example-Based Vulnerability Detection and Repair in Java Code. ICPC 2022.
doi.org/10.1145/3524610.3527895 - Charoenwet et al. An Empirical Study of Static Analysis Tools for Secure Code Review. ISSTA 2024.
doi.org/10.1145/3650212.3680313 - Piantadosi, Scalabrino, Oliveto. Fixing of Security Vulnerabilities in Open Source Projects: A Case Study of Apache HTTP Server and Apache Tomcat. 2019.
doi.org/10.1109/ICST.2019.00017 - Bandara et al. Fix that Fix Commit: A real-world remediation analysis of JavaScript projects. SCAM 2020.
doi.org/10.1109/SCAM51674.2020.00027 - Alexopoulos et al. How Long Do Vulnerabilities Live in the Code? USENIX Security 2022.
usenix.org/conference/usenixsecurity22/presentation/alexopoulos - Haddad et al. Automated Mapping of CVE Vulnerability Records to MITRE CWE Weaknesses. 2023.
arxiv.org/abs/2304.11130 - Nordqvist et al. RAG Against the Machine: Zero-Shot Software Vulnerabilities Classification using LLMs. LLM4Code@ICSE 2026.
doi.org/10.1145/3786181.3788722 - Son, McKinley, Shmatikov. RoleCast: finding missing security checks when you do not know what checks are. OOPSLA 2011.
doi.org/10.1145/2048066.2048146 - Monshizadeh, Naldurg, Venkatakrishnan. MACE: Detecting Privilege Escalation Vulnerabilities in Web Applications. CCS 2014.
doi.org/10.1145/2660267.2660337 - Son, McKinley, Shmatikov. Fix Me Up: Repairing Access-Control Bugs in Web Applications. NDSS 2013.
- Islam et al. Coding Practices and Recommendations of Spring Security for Enterprise Applications. SecDev 2020.
doi.org/10.1109/SecDev45635.2020.00024 - Acar et al. You Get Where You're Looking For: The Impact of Information Sources on Code Security. IEEE S&P 2016.
doi.org/10.1109/SP.2016.25 - Acar et al. Comparing the Usability of Cryptographic APIs. IEEE S&P 2017.
doi.org/10.1109/SP.2017.52 - Fischer et al. Stack Overflow Considered Harmful? The Impact of Copy&Paste on Android Application Security. IEEE S&P 2017.
arxiv.org/abs/1710.03135 - Assal, Chiasson. 'Think secure from the beginning': A Survey with Software Developers. CHI 2019.
doi.org/10.1145/3290605.3300519 - Mokhberi, Beznosov. SoK: Human, Organizational, and Technological Dimensions of Developers' Challenges in Engineering Secure Software. EuroUSEC 2021.
doi.org/10.1145/3481357.3481522 - Gutfleisch et al. Security Champions Without Support. EuroUSEC 2023.
doi.org/10.1145/3617072.3617115 - Johnson et al. Why don't software developers use static analysis tools to find bugs? ICSE 2013.
doi.org/10.1109/ICSE.2013.6606613 - Nachtigall, Schlichtig, Bodden. A large-scale study of usability criteria addressed by static analysis tools. ISSTA 2022.
doi.org/10.1145/3533767.3534374 - Carvalho et al. C-3PR: A Bot for Fixing Static Analysis Violations via Pull Requests. SANER 2020.
doi.org/10.1109/SANER48275.2020.9054842 - Mohayeji et al. Investigating the Resolution of Vulnerable Dependencies with Dependabot Security Updates. MSR 2023.
doi.org/10.1109/MSR59073.2023.00042 - Gorski et al. Developers Deserve Security Warnings, Too: On the Effect of Integrated Security Advice on Cryptographic API Misuse. SOUPS 2018.
usenix.org/conference/soups2018/presentation/gorski - Greiler, Storey, Noda. An Actionable Framework for Understanding and Improving Developer Experience. IEEE TSE 2022.
arxiv.org/abs/2205.06352 - Pearce et al. Asleep at the Keyboard? Assessing the Security of GitHub Copilot's Code Contributions. IEEE S&P 2022.
arxiv.org/abs/2108.09293 - Viega, Evans. Separation of Concerns for Security. 2000.
- Dalton, Kozyrakis, Zeldovich. Nemesis: Preventing Authentication & Access Control Vulnerabilities in Web Applications. USENIX Security 2009.
- Burket, Mutchler, Weaver, Zaveri, Evans. GuardRails: A Data-Centric Web Application Security Framework. USENIX WebApps 2011.
- Tahaei, Vaniea. A Survey on Developer-Centred Security. EuroS&PW 2019.
doi.org/10.1109/EuroSPW.2019.00021 - Vassallo et al. How developers engage with static analysis tools in different contexts. EMSE 2020.
doi.org/10.1007/s10664-019-09750-5 - Noda, Storey, Forsgren, Greiler. DevEx: What Actually Drives Productivity. ACM Queue 2023.
doi.org/10.1145/3595878
Primary industry (11)
- Kern. Developer Ecosystems for Software Safety. ACM Queue 22, 2024; CACM 67(6), 2024.
queue.acm.org/detail.cfm?id=3648601 - Kern. Securing the Tangled Web. CACM 57(9), 2014.
doi.org/10.1145/2643134 - Google. Tackling cybersecurity vulnerabilities through Secure by Design. 2024.
blog.google/technology/safety-security/tackling-cybersecurity-vulnerabilities-through-secure-by-design - Google Bug Hunters. Secure by Design: Google's blueprint for a high-assurance web framework.
bughunters.google.com/blog/6644316274294784/secure-by-design-google-s-blueprint-for-a-high-assurance-web-framework - Google Security Blog. Eliminating Memory Safety Vulnerabilities at the Source. September 2024.
security.googleblog.com/2024/09/eliminating-memory-safety-vulnerabilities-Android.html - Winters, Manshreck, Wright (eds.). Software Engineering at Google, ch. 20: Static Analysis.
abseil.io/resources/swe-book/html/ch20.html - Netflix Technology Blog. The Show Must Go On: Securing Netflix Studios At Scale. 2021.
netflixtechblog.com/the-show-must-go-on-securing-netflix-studios-at-scale-19b801c17b50 - Meta. Designing Security for Billions. 2019.
about.fb.com/news/2019/01/designing-security-for-billions - Stone. The State of 0-Day In-the-Wild Exploitation. USENIX Enigma 2021.
usenix.org/conference/enigma2021/presentation/stone - Google DeepMind. Introducing CodeMender: an AI agent for code security. October 2025.
deepmind.google/discover/blog/introducing-codemender-an-ai-agent-for-code-security - Google Cloud. Shift down with platform engineering.
cloud.google.com/solutions/platform-engineering
Secondary (6)
- PortSwigger Daily Swig. Google checks rise of DOM XSS with Trusted Types.
portswigger.net/daily-swig/google-checks-rise-of-dom-xss-with-trusted-types - SecurityWeek. Google: Half of 2022's Zero-Days Are Variants of Previous Vulnerabilities.
securityweek.com/google-half-2022s-zero-days-are-variants-previous-vulnerabilities - tl;dr sec. Phil Venables at RSAC 2025.
tldrsec.com/p/phil-venables-rsac-2025 - The Record. Google says Big Sleep AI tool found bug hackers planned to use. 2025.
therecord.media/google-big-sleep-ai-tool-found-bug - The Hacker News. Google's new AI doesn't just find vulnerabilities, it rewrites code to patch them. October 2025.
thehackernews.com/2025/10/googles-new-ai-doesnt-just-find.html - VibeGuard: A Security Gate Framework for AI-Generated Code. arXiv 2026.
arxiv.org/abs/2604.01052
Practitioner (8)
- NorthSec speaker abstract on underused secure-by-default Android frameworks at Meta.
nsec.io/speaker/tanu-jain - OWASP Top 10 Proactive Controls. top10proactive.owasp.org
- OWASP Application Security Verification Standard.
owasp.org/www-project-application-security-verification-standard - CISA. Secure by Design.
cisa.gov/securebydesign - tl;dr sec. The Race to Make a Business of Secure Defaults.
tldrsec.com/p/business-of-secure-defaults - Semgrep. Clint Collabs: Jason Chan on the Origin of the Paved Road.
semgrep.dev/events/clint-collabs-jason-chan-on-the-origin-of-the-paved-road - CNCF TAG Security. Secure Defaults: Cloud Native 8.
tag-security.cncf.io/community/resources/security-whitepaper/secure-defaults-cloud-native-8 - Cisco. Project CodeGuard rules.
github.com/project-codeguard/rules
Julie Davila · Research. Researched with AI agents and reviewed by Julie Davila: how this research is made. Text licensed CC BY 4.0. Source on GitHub.