Get listed

Cost of unsecured code: IBM 2026 average is $4.99 million

A broken lock with coral coins spilled on the desk.

The cost of a bug is the incident, the downtime, and the notice you have to send. A global average is a headline, not your number.

IBM and others publish yearly averages. Your number is the customer table you can dump with one IDOR, times the work to notify. The cheaper move is the test that would have caught it.

The usual mistake is using the average to buy a tool, and never funding the two-account test.

This page puts the headline number next to the engineering work that actually reduces it.

IBM’s 21st Cost of a Data Breach Report, published 29 July 2026, put the global average at USD 4.99 million. That is a 12 percent rise from the 2025 figure of USD 4.44 million, and it is a record in the series.

Ponemon interviewed people who had a real incident. The dollars are accounting, not a horror poster. This page maps those line items onto three handlers you already ship: a scoped read, a bind, and a lockfile pin. Keep the secure coding checklist next to the numbers. Open IDOR when the row is the ticket, and injection when the interpreter is the ticket.

What IBM measured from 2024 through 2026

three first-party pages. The 30 July 2024 newsroom release is the 2024 report: USD 4.88 million global, a 10 percent jump, 604 organizations, incidents from March 2023 through February 2024. Healthcare sat at USD 9.77 million that year. Stolen or compromised credentials were the most common initial vector at 16 percent. The mean identify-and-contain clock was 258 days.

The 2025 report is the dip. IBM’s 30 July 2025 newsroom release, and the 2026 year-over-year table, both put that year’s worldwide mean at 4.44 million dollars, a 9 percent drop, 600 organizations, March 2024 through February 2025. The US figure in that year was 10.22 million dollars. The lifecycle fell to 241 days. If a later errata changes a cell, the 2026 PDF is the sheet I used on 22 August 2026.

The 2026 report landing page and the full PDF dated with the 29 July 2026 study put the new worldwide mean at 4.99 million dollars. Sample: 602 organizations, March 2025 through February 2026, 17 industries, 16 countries and regions, 2,590 to 115,380 records. US cell: 11.5 million dollars, more than twice the worldwide figure, up 13 percent in the key-findings text and 11 percent in the country table. I am using 11.5 million as the US number and noting that IBM printed both 11 and 13 percent in different sections. Healthcare: 6.64 million dollars, still first among industries, down from 7.42 million in 2025. Financial services: 6.29 million. Lifecycle: 247 days, a 2.5 percent uptick after five years of decline.

Report yearGlobal averageUS averageLifecycle
2024USD 4.88Mnot the number I am using here258 days
2025USD 4.44MUSD 10.22M241 days
2026USD 4.99MUSD 11.5M247 days

That US cell stays blank because IBM’s 2024 newsroom release does not restate a US average in the same table. Do not invent it from a blog recap.

The two buckets that ate the average

The 2026 PDF splits that year’s mean into four cost components. Detection and escalation is 1.64 million dollars. Lost business is 1.54 million. Those two are 63 percent of the average, 3.18 million together. Ex-post response is 1.36 million. Notification is 0.45 million. IBM writes that the first pair covers crisis work, disrupted operations, and customer churn. The third covers fines, legal spend, and credit monitoring.

That split is why a missed WHERE org_id is a finance problem, not a scanner aesthetic. The cheap miss is a 200 on someone else’s invoice. The expensive part is the months IBM still measures: 183 days to identify and 64 days to contain in 2026, 247 combined. Internal teams that found the incident themselves ran 209 days and USD 5.01 million. Attacker-disclosed incidents ran USD 5.12 million. I am not claiming your invoice route equals those means. I am claiming the bill is mostly detection and lost business, so a test that fails on a foreign id is the work that never enters those two buckets.

Customer PII was the most stolen data type in 2026, 52 percent of incidents, USD 192 per record. Intellectual property was 32 percent and USD 196 per record. Employee PII was 35 percent and USD 188. Those are IBM’s per-record means, not a price list for your schema. They tell you which columns are the ones loadInvoice must refuse to a foreign session.

Public-facing apps sit at $4.68 million

Figure 10 in the 2026 PDF lists initial vectors with a cost. Phishing, voice or SMS, is USD 5.29 million. Social engineering is USD 5.23 million. Valid-account abuse is USD 5.07 million. Supply chain compromise is USD 4.96 million. Exploiting public-facing applications is USD 4.68 million. That last row is the one a handler you wrote can still close this week. Injection, XSS, and a missing object check are how a public app becomes that vector. They are not IBM categories. They are the code under it.

CWE-89, CWE-79, and CWE-639 are the three I would budget first on a CRUD API. A concatenated ORDER BY is still a 2026 CVE class. An innerHTML assignment is still CWE-79 at rank 1 on MITRE’s 2025 Top 25. A SELECT that only asks for id is still the inbox-id story. The sibling pages name the fixes. This page only names the dollar row they sit under.

// Named helper. Tenant comes from the session, never from req.body.
async function loadInvoice(pool, invoiceId, orgId) {
 const { rows } = await pool.query(
 `SELECT id, memo, amount_cents
 FROM invoices
 WHERE id = $1 AND org_id = $2`,
 [invoiceId, orgId]
 );
 return rows[0] || null;
}

app.get("/invoices/:invoiceId", async (req, res) => {
 if (!req.actor) {
 res.status(401).send("Unauthorized");
 return;
 }
 const row = await loadInvoice(pool, req.params.invoiceId, req.actor.orgId);
 if (!row) {
 res.status(404).send("Not found");
 return;
 }
 res.json(row);
});

A 200 with amount_cents for org B, under org A’s cookie, is the public-app miss. IBM will not print your route name. It will print a vector that looks like that row. Bind the id. Scope the org. Encode memo if it ever becomes HTML. Those three lines are cheaper than USD 1.64 million of detection work.

Supply chain is still a code bill

IBM put supply-chain compromise at USD 4.96 million in 2026, and at 258 days to identify and contain, tied with removable-media copies for the longest clock in Figure 13. That is not a vendor-pitch number. It is the same class as a lockfile you did not pin.

live HN item 45196235. The date on the comment is 10 September 2025. The packages named are the ones your package-lock.json still lists if you never froze them. The control is a pinned lockfile in CI, a deny on npm install without that file, and a diff on unexpected version bumps. See the vulnerable versus malicious dependencies page for the split. This page only ties that week to IBM’s 258-day cell.

# CI: fail closed if the lockfile is missing or ignored
if [ ! -f package-lock.json ]; then
 echo "missing package-lock.json" >&2
 exit 1
fi
npm ci --ignore-scripts

npm ci is the named fallback. npm install that rewrites the lock is the open. --ignore-scripts is the extra belt after a maintainer account is the one that shipped the tarball. It does not replace a review of the diff. It does stop a postinstall from running in CI before a human sees the bump.

A control that is cheaper than detection

Extensive use of security AI and automation saved USD 1.93 million in the 2026 report and cut 65 days off the clock, versus shops that used none. Only 36 percent of breached organizations said they used those tools extensively across prevention, detection, investigation, and response. Only 18 percent applied agents to vulnerability scanning. Those are IBM’s SOC numbers. They are not a reason to skip the query.

The cheap control is still a function with two arguments. loadInvoice(invoiceId, orgId) has no path that returns a row when orgId is missing. A missing actor is 401. A missing row is 404. There is no 200 that means “we will check ownership later.”

Same invoice id. The open query becomes detection spend. The scoped query never enters the two big buckets.
GET /invoices/B-id
Cookie: __Host-session=A

 OPEN SELECT... WHERE id = B-id
 200 + B cents
 |
 IBM detection USD 1.64M mean
 lost business USD 1.54M mean

 FIX loadInvoice(B-id, actor.orgId)
 zero rows -> 404
 TEST A cookie + B id => 404

AI-driven incidents added about USD 1 million on top of the 2026 average, and one in four malicious breaches in the study were AI-enabled. That is IBM’s attacker-tooling row. It does not change the helper. A model that finds a missing org_id faster still hits 404 if the helper is the only read path.

Prove the miss before finance does

You are not pricing a breach. You are proving loadInvoice returned nothing for a foreign id. Two fixture accounts. One invoice. One cookie swap.

  1. Create org A and org B in your own fixtures. Insert invoice B-id under B only.
  2. Log in as A. Copy the __Host-session cookie from DevTools. Do not send that cookie anywhere else.
  3. GET /invoices/B-id with A’s cookie. Expect 404 and an empty body, not 200 with amount_cents.
  4. Repeat with no cookie. Expect 401. A 200 here means the route never called loadInvoice.
curl -sS -D - -o /tmp/invoice-body -X GET \
 "https://your-app.example/invoices/B-id" \
 -H "Cookie: __Host-session=PASTE_FROM_YOUR_DEVTOOLS"
# Expect: HTTP/2 404
# Expect: body without amount_cents

curl -sS -D - -o /dev/null -X GET \
 "https://your-app.example/invoices/B-id"
# Expect: HTTP/2 401

Put both curls in CI against a local app. The test fails closed: a 200 is a red build, not a skip. That is the whole cost argument. IBM’s 2026 mean is the bill after the miss has already shipped. The 404 is the line that never becomes that bill.

Questions we keep getting

Is the 2026 mean what my company would pay?

No. It is IBM’s worldwide average across 602 studied incidents, 2,590 to 115,380 records. Your bill can be smaller or much larger. The US cell in that report is 11.5 million dollars. Use the year and the cell. Do not brief the mean as your quote.

Did the average go down in 2025, then back up?

Yes. IBM printed 4.88 million dollars in 2024, 4.44 million in 2025, and 4.99 million in 2026. The 2025 drop was the first decline in five years in that series. The latest PDF says detection, escalation, and lost business drove the rebound.

Should I buy a tool because IBM saved USD 1.93 million?

No. That cell is extensive AI and automation versus none, inside IBM’s sample. Pin the lockfile. Ship loadInvoice. Fail the curl on 200. Buy tools after those three exist, not instead of them.

Shimi Eshkenazi

Shimi Eshkenazi / About Author

Shimi is a Product Manager at WhiteSource. Shimi has spent more than a decade on software development in a variety of organizations and gathered experience in the application security world for more than 6 years.

Shimi had lectured in conferences like OWASP-EU & SecTor, published security researches, and participated in the writing of patents regarding innovation in this field, some of them are already granted. Shimi is currently working at WhiteSource leading a cutting-edge technology offering for open source security.

LinkedIn