
You have the repo, the cloud bill, and a Slack channel with two engineers who left in March. The founder says the code is "mostly fine." Nobody can tell you why the payments service ships its own copy of the auth middleware.
Before you open a file, one finding should reorder your code audit checklist. A study of 570 real code-review comments at Microsoft asked what review actually catches. Defects were 14% of them. Of those 78 defect comments, five were about security and three were about exception handling [V1].
Security is on this list. It is phase three, not item one.
Key takeaways
A code audit is a time-boxed, structured examination of a whole codebase and its dependencies by someone who did not write it, producing findings about the state of the system rather than a verdict on a single change.
The three terms get used interchangeably and shouldn't be.
Same checklist, different consumer. The audit tells an engineering leader what to fix; due diligence tells a buyer what they're absorbing.
Less than everyone assumes. Alberto Bacchelli and Christian Bird sorted 200 review threads and 570 comments at Microsoft into categories. "Code improvements" won with 165 comments, 29% of the total. "Defect" came fourth of nine, at 78 comments, 14% [V1]. Inside that 14%: 65 logical issues, six high-level, five security, three wrong exception handling [V1].
When they surveyed 873 Microsoft programmers, "finding defects" was the top-ranked motivation, first choice for 383 of them, 44% [V2]. The thing everybody believes review is for is the thing it does fourth-best.
Their conclusion isn't that review fails. It's that review pays out elsewhere: reviews "provide additional benefits such as knowledge transfer, increased team awareness, and creation of alternative solutions to problems… code and change understanding is the key aspect of code reviewing" [V1].
One line in that paper is written for your exact situation. Their interviewees admitted that when the code is not among their own codebase, they look at "obvious bugs (such as, exception handling)" [V1]. That's what a good reviewer degrades to on unfamiliar ground. Not laziness — comprehension is the binding constraint and they haven't got it yet.
Another angle. A 10-month study of the Cisco MeetingPlace team in 2006 (50 developers, 2,500 reviews, 3.2 million lines) found an average defect density of 32 per thousand lines, and 61% of those reviews found no defects at all [V3]. One team, one company, twenty years ago: a large sample of a narrow population, not "research shows." But it points the same way as Microsoft's. Review is a comprehension instrument that occasionally catches bugs.
So run the checklist in comprehension order. Everything below is sequenced by what you can only learn after the step above it.
What you buy by putting a senior engineer on a legacy code audit is not sharper eyes. It's a faster map.
A field study of seven real projects, 79 professional developers and 3,244 working hours, found developers spend up to about 58% of their time on program comprehension. The part everyone skips: senior developers spent a significantly lower percentage of their time on it than juniors [V6]. Same code, less time working out what it does. That gap is the product you're buying.
Watch what happens when comprehension has no structure. In a study of 14 developers working bug-fix tasks on a codebase they'd never seen, 42% tried a split screen to hold the documentation and the code in view, and every one abandoned it inside ten minutes; they spent about 19% of their programming time surfing the web [V11]. The checklist isn't bureaucracy here. It's what stops the thrash.
Two constraints belong in the map phase. First, defects cluster: Boehm and Basili's synthesis found 60–90% of defects arise from 20% of modules, median around 80%, and "nearly all defects cluster in about half the modules produced" [V8]. Half the codebase can wait. Second, pace. In the Cisco data, reviewers slower than 400 lines per hour were above average at finding defects; above 450 lines per hour, defect density came in below average in 87% of cases. To explain that, the study reaches for an established finding it cites rather than measures: after 60 minutes reviewers "wear out" and stop finding anything new [V4]. Budget the reading, or the reading budgets you.
One hypothesis to test on any recent code. GitClear's telemetry, from a company that sells the analytics measuring this, reports block duplication up 81% on 2023 and copy/paste up from 9.4% of changed lines in 2022 to 15.7%, across 623 million analysed changes [R16][R17][R19]. A hypothesis, not a verdict: a peer-reviewed study of 151 repositories with self-admitted GenAI usage found "no general increase" in code churn after adoption, "contradicting popular narratives" [V10]. But if your map keeps turning up the same function three times, you know what to grep for.
The least glamorous phase, the highest-yield, and the only one you can finish in an afternoon.
The best dataset here is Black Duck's, and its population is why it deserves your attention: 947 codebases submitted to Black Duck Audit Services between November 2024 and October 2025 for M&A, regulatory compliance and internal risk assessment, including 197 M&A transactions across 17 industries [R8]. Vendor telemetry, but telemetry from code somebody was already worried enough to pay to have audited. Which is exactly where you're standing.
Open source appears in 98% of those codebases [R9]. Every maintenance metric now clears 90%: 93% contain components with no development activity in two or more years, 92% contain components four or more years out of date, 92% are ten or more versions behind, and median component age is 45 months, up from 42 [R12]. Black Duck calls the abandoned ones "zombie components": software that "continues to exist and be used but receives no active maintenance," where "when a vulnerability is discovered… there may be no one able to fix it" [R12].
Now the part that decides how you count. 64% of open source components in a typical codebase are transitive dependencies [R14], pulled in by something you chose rather than chosen by you. Reading the manifest is not an inventory. Black Duck's own method adds snippet, binary and file-print analysis, because "relying solely on declared dependencies — what appears in a package.json or pom.xml — misses a significant portion of the open source present in a codebase, including vendor code, copy-pasted snippets, and transitive dependencies" [R15].
Then licensing, the item that can kill a transaction while everyone argues about test coverage. 68% of audited codebases contain license conflicts, up from 56%, the largest single-year jump the study has recorded, and still 59% under a stricter metric that excludes component-to-component issues. One codebase held 2,675 distinct conflicts [R13].
Two numbers from Veracode's 2026 analysis, run by the Cyentia Institute, hold the phase together: third-party components account for 66% of all critical security debt vulnerabilities [R5], and the remediation half-life for third-party flaws is 358 days against a 243-day average across all scan types [R6]. Dependency problems clear about four months slower than your own code's, because fixing them means waiting on a maintainer, or forking.
The same dataset carries two traps. Vulnerability counts have a mean of 581 per codebase and a median of 78 [R10]. Anyone quoting 581 as typical is quoting the tail, and the tail is the story: a minority of codebases carry enormous counts, and yours might be one. The second trap runs the other way. High-risk prevalence is falling. 78% of audited codebases contain at least one high-risk vulnerability, down from 81%, and 44% contain critical-risk ones, down from 48% [R11]. What's worsening is volume and maintenance debt, not the share of codebases with a serious hole in them.
With a map and an inventory, scanning finally has something to attach to.
Start with the standard you check against. The current OWASP Top 10 is the 2025 edition, and two changes matter here. Software Supply Chain Failures was promoted to A03, which is Phase 2 arriving on the security list under a different name. And Mishandling of Exceptional Conditions is new at A10 [S3]. That second one should raise an eyebrow: exception handling is what Microsoft's reviewers said they fall back on when they don't know the codebase, and what three of 570 comments actually covered [V1]. The list now agrees with the failure mode.
Second, your SBOM template is probably out of date. The baseline is now the 2026 Minimum Elements for a Software Bill of Materials, published 29 July 2026 by CISA with the NSA, FBI and fifteen international partner agencies, which "updates and replaces" the 2021 NTIA minimum elements [S5]. The change that bites is definitional. The old "Depth" element, top-level dependencies only, is replaced by "Coverage," because the old definition "reflected the capabilities of SBOM tooling at the time rather than the depth of information needed to make informed security decisions" [S6]. An SBOM that stops at your direct dependencies misses 64% of your components [R14].
Third, if any of this was written with a model, scan the flaw classes models are worst at. Veracode tested over 150 LLMs on 80 coding tasks in Java, JavaScript, C# and Python, graded by Veracode's own static analyser against four weakness classes only: SQL injection, XSS, log injection and insecure crypto. Across all models and tasks, 55% of generations were secure [S7]. The aggregate is the least useful part; the splits are the checklist. Insecure crypto passed 86% and SQL injection 82%, but XSS passed 15% and log injection 13%, and Java came in at 29% against Python's 62% [S7]. That is not "AI code is 55% secure." It's four flaw classes, one grader, 80 tasks. But if you inherited a Java service with model-written output handling, you know the two greps to run first.
Fourth, check that every imported package exists. Across 576,000 generated code samples from 16 models, hallucinated package names averaged at least 5.2% for commercial models and 21.7% for open-source ones [S1], and in a 2026 replication, 53 of the 127 names all five frontier models invented were still registrable on PyPI and npm [S2].
Then pace it. 82% of organisations carry security debt older than a year, 60% carry critical security debt [R2][R3], and the median organisation clears about 10% of its backlog a month [R7]. Remediation is a program, not a sprint.
Every inherited codebase arrives with reassurance attached. Here's what each piece entitles you to conclude.
The coverage badge says 84%. Inozemtseva and Holmes generated 31,000 test suites across five Java systems of up to 724,000 lines and found only a low-to-moderate correlation between coverage and effectiveness once suite size is controlled for, and no rescue from stronger coverage criteria. Their conclusion: coverage "should not be used as a quality target because it is not a good indicator of test suite effectiveness" [V5]. It tells you what is untested, and nothing about whether the tested part is tested well.
The SAST scan is clean. An ISSTA 2024 study ran static analysers against real vulnerability-contributing commits: 319 vulnerabilities from 815 commits across 92 C and C++ projects, not synthetic benchmarks. A single tool warned in the vulnerable functions of 52% of those commits; at least 76% of those warnings were irrelevant to the vulnerability, and 22% of commits went undetected because of rule limitations [S8]. Half, buried in noise, with a fifth structurally invisible — measured on C and C++ analysers, so treat it as the shape of the problem rather than a figure for your own stack.
CI is green. Green means the tests that exist passed. In the Cisco team's 2,500 reviews, 61% found nothing [V3], and nobody concluded from that that the code was clean. Hold the 2025 DORA report next to it: it frames AI as "an amplifier, magnifying an organization's existing strengths and weaknesses," and puts the returns "not from the tools themselves, but from a strategic focus on the underlying organizational system" [V12]. Coverage of the same report notes that AI adoption now correlates positively with throughput while still correlating with higher instability [V13].
So audit the delivery system as hard as the code: who reviews, what gates a deploy, how a rollback happens. A green pipeline attached to a team that can't roll back is a light on a dashboard, not a control.
If a consultancy handed you a deck, at least one of these was in it.
"Fixing it in production costs 100x." Real source: Boehm and Basili, IEEE Computer, January 2001. What they wrote is that a post-delivery fix is "often 100 times more expensive," and they added the hedge themselves: "For this updated list, we have added the word 'often'… One insight shows the cost-escalation factor for small, noncritical software systems to be more like 5:1 than 100:1" [F2]. Good architectural practice reduces the multiplier even on large critical systems [F2]. The caveat is the better story: it isn't a law of nature, it's a readout on your architecture.
"$1.52 trillion in technical debt." From CISQ's 2022 report on the cost of poor software quality [V14], whose own sentence reads: "In our 2020 report we estimated the TD principle in the US to be ~$1.3 trillion, which would increase to $1.52 trillion in 2022 due to inflation alone" [F3]. A 2020 estimate uprated for inflation, and the report adds "we have no good estimates yet on the accumulating interest" [F3]. Budget against the Phase 2 maintenance metrics instead; those were measured on real codebases [R12].
"Reviewing 200–400 lines catches 70–90% of defects." Attributed everywhere to the Cisco case study. The strings "70-90", "70%" and "90%" appear nowhere in it [F4]. It reports defect density and rate effects, not a recall percentage [V3][V4] — which is what you would expect, because measuring recall needs a ground-truth defect set to measure against. For a real effectiveness range, use Boehm and Basili: "numerous studies confirm that peer review provides an effective technique that catches from 31 to 93 percent of the defects, with a median of around 60 percent" [V7]. Wide, honest, sourced.
A fourth belongs here even though it isn't a number. I went looking for a vendor claim of the shape "our automated reviewer catches N% of real bugs" with a stated method behind it, and could not find one [F10]. Measuring recall would need a ground-truth defect set. What vendors publish instead is issues raised per pull request: one vendor counts 10.83 per AI-co-authored PR against 6.45 per human-only PR, with AI authorship inferred from signals rather than confirmed [S9][F7]. That measures a tool's output, not what it catches.
Screenshot this. Hand it to a buyer and it's a technical due diligence checklist; every item traces to a phase above.
Phase 1 — Map (half a day, before any scanning)
Phase 2 — Dependencies (one afternoon, highest yield)
Phase 3 — Security (now that it has something to attach to)
Phase 4 — Interrogate the green lights
Run it in that order and by the end of week one you'll know which parts of the system you understand, which parts nobody does, and which problems belong to someone else's maintainer. That beats a list of bugs when you're deciding whether to keep, harden or replace.
If you'd rather someone else ran it, our Code Audit is a fixed-price, three-day, audit-only engagement: findings plus a quote, remediation optional and separate.
Either way, the first question isn't "what's broken." It's "what don't we understand yet, and how fast can we fix that."
A code audit examines a whole codebase and its dependencies in one time-boxed pass, usually by someone outside the team, and reports on the state of the system. A code review examines a single change, continuously, by teammates, and its measured value is comprehension rather than defect-finding: at Microsoft, defects were 14% of 570 review comments, ranking fourth of nine categories [V1]. Technical due diligence is a code audit run to support a transaction, which is why licensing and third-party components dominate it [R8].
Plan roughly a week for a first pass: half a day to map the system, an afternoon for the dependency inventory, then security and delivery. Pace is the real constraint, not calendar time. In the Cisco data, reviewers above 450 lines per hour produced below-average defect density in 87% of cases, and the study cites an established prior finding that reviewers "wear out" after 60 minutes [V4]. Reading faster doesn't finish it sooner; it just finishes it worse.
No. Start with comprehension, because a scan you can't interpret produces a list, not a decision. Developers spend up to about 58% of their time on program comprehension, and senior developers spend a significantly lower share of theirs than juniors [V6]. Microsoft's reviewers admitted that on code outside their own codebase they fall back to "obvious bugs (such as, exception handling)" [V1], which is what an audit without a map degrades into.
Neither result licenses that conclusion. Across 319 vulnerabilities in 815 real vulnerability-contributing commits from 92 C and C++ projects, a single static analyser warned inside the vulnerable functions of 52% of commits, at least 76% of those warnings were irrelevant to the vulnerability, and 22% went undetected due to rule limitations [S8]. That result is specific to C and C++ analysers, not a measurement of every SAST tool on every language. On coverage, Inozemtseva and Holmes concluded it "should not be used as a quality target because it is not a good indicator of test suite effectiveness" [V5].
Target the weakness classes models fail most often, and verify that imported packages exist. Veracode tested over 150 LLMs on 80 coding tasks, graded by its own static analyser against four weakness classes only, and found XSS passing 15% and log injection 13% while insecure crypto passed 86%; Java scored 29% against Python's 62% [S7]. Separately, hallucinated package names averaged at least 5.2% for commercial models and 21.7% for open-source ones across 576,000 generated samples [S1].