Back to Cheat Sheets

๐Ÿ” Software or Data Integrity FailuresOWASP 2025

OWASP Web Top 10 2025 ยท A08

HIGH RISK

๐Ÿ“‹ What Is It?

Software or Data Integrity Failures occur when code, infrastructure, or data is trusted without verifying it has not been tampered with. Modern apps are assembled through long automated pipelines โ€” package managers, CI/CD, CDNs, registries, auto-updaters โ€” each an opportunity to inject or alter code. Integrity is solved in theory (a hash detects modification; a signature proves authorship); the failures are almost never bad math โ€” they are a failure to actually perform the check. The category also absorbed Insecure Deserialization, because deserializing untrusted data is another way of trusting data whose integrity was never checked.

A08OWASP 2025 Rank
CWE-502Key: Deserialization of Untrusted Data
New '21Introduced (as A08:2021)

โš ๏ธ Top Attack Vectors

  • Dependency substitution: typosquatting and dependency confusion pull attacker packages into the build (malicious postinstall hooks).
  • Compromised maintainer / floating ranges: a poisoned minor version auto-upgrades via ^2.0.0.
  • Unverified CDN script (missing SRI): a compromised CDN runs skimmer code in every visitor's session.
  • Insecure auto-update: unsigned binary installed from an attacker-influenceable channel, often at high privilege.
  • Build-pipeline injection (SolarWinds-class): code inserted before signing ships malware under a genuine signature.
  • Insecure deserialization โ†’ RCE: native deserializers run gadget chains on attacker bytes; tampered cookies/tokens trusted server-side.

๐Ÿ”ด Attack Flow

1. Locate a trust boundary with NO verification
โ†“
2. Position the payload (publish pkg, sit on update channel, craft gadget)
โ†“
3. Victim installs / builds / updates / deserializes it
โ†“
4. No signature or hash is checked against a trusted reference
โ†“
5. EXECUTE: RCE, backdoor, or rewritten authorization decision

โŒ Vulnerable Code

# Python โ€” native deserialization of user input runs __reduce__ => RCE import pickle, base64 @app.route("/restore") def restore(): raw = base64.b64decode(request.cookies["state"]) return render(pickle.loads(raw)) # attacker-controlled bytes -> code exec <!-- HTML โ€” browser trusts whatever the CDN serves (no integrity) --> <script src="https://cdn.example.com/pay/2.4.0/checkout.js"></script>

โœ… Secure Code

# Python โ€” data-only JSON parsed into a strict schema (no code execution) import json from pydantic import BaseModel, ValidationError class State(BaseModel): view: str page: int @app.route("/restore") def restore(): try: state = State(**json.loads(request.cookies["state"])) # validated except (ValueError, ValidationError): abort(400) return render(state) <!-- HTML โ€” runs ONLY if the fetched bytes match the pinned hash --> <script src="https://cdn.example.com/pay/2.4.0/checkout.js" integrity="sha384-q8Wj5r2Fh0m3s...pinned-hash..." crossorigin="anonymous"></script>

โœ“ Prevention Checklist

  • Commit lockfiles; install frozen & hash-verified (npm ci, pip --require-hashes)
  • Scope internal package names to a private registry (blocks confusion)
  • Add SRI hashes to all CDN scripts/styles; enforce with CSP
  • CI/CD: least-privilege & short-lived (OIDC) creds; isolate the signing step
  • Pin actions/plugins to immutable commit SHAs, not mutable tags
  • Protected branches, mandatory review, segregation of duties
  • Verify a pinned-key signature + hash before installing any update; block rollback
  • Never deserialize untrusted data natively; use data-only formats + schema; HMAC client state

๐Ÿ” Detection & Tools

osv-scanner npm audit pip-audit Sigstore cosign SLSA / provenance ysoserial SRI Hash Generator

Detection Signals:

  • Lockfile hash mismatches; unexpected new transitive packages; install-time network calls
  • Pipeline definition changes; unexplained use of signing secrets; update requests over plain HTTP
  • Deserialization of request bodies/cookies; tokens with alg=none
Key Takeaway: Verify before you trust. A single verified checkpoint breaks the whole chain โ€” had any step checked a signature or hash against a trusted reference, the substituted artifact would have been rejected.
Myth to drop: "The update is signed, so we're safe." A signature only proves the artifact came from the signing key after the build. If the pipeline was compromised, the malware is signed by the genuine key โ€” integrity must extend to the build itself.