Integrity Failures

OWASP Top 10

Course 1 · Chapter 8 · A08: Software & Data Integrity Failures

A08 is a relatively new category (added in 2021) that consolidates a critical idea: you must be able to verify that code and data haven't been tampered with — whether at rest, in transit, or during the build/deploy pipeline. It's the inverse of confidentiality: instead of "nobody can read this," it's "I can prove nobody changed this." This chapter covers the three biggest threat surfaces: deserialization, CI/CD pipeline integrity, and insecure software updates.

A08: Software & Data Integrity Failures

This category spans assumptions about code/data being authentic and unmodified — and the attacks that exploit when those assumptions break. It's fundamentally about trust: can you prove the code you're running is the code that was built? Can you prove the data came from where you think? Without integrity checks, every layer of security collapses — an attacker who can modify code or data owns the system, full stop.

Deserialization Attacks (the "Untrusted Input" Extreme)

Serialization is the process of turning an object (a class instance, a data structure) into a byte string so you can store or transmit it. Deserialization is reconstructing the object from those bytes. Many languages provide "native" serializers (Java's ObjectInputStream, Python's pickle, PHP's unserialize) that are expressive but dangerous: they can reconstruct objects by executing methods during deserialization, which means a crafted byte string can trigger arbitrary code.

Deserialization: code execution via object reconstruction
If an attacker can control the byte string being deserialized, they can craft one that, when deserialized, instantiates a class and calls methods that execute code (e.g. opening a file, running a command, starting a reverse shell). This is why deserializing untrusted input (user uploads, network messages, database blobs) with a language's native serializer is an RCE vulnerability — as bad as SQL injection or command injection. The fix: never deserialize untrusted data. Use safe formats (JSON, Protocol Buffers, msgpack) that only produce data, not executable objects, and validate the structure after parsing.

CI/CD Pipeline Integrity (the Build Supply Chain)

The CI/CD pipeline is your automated build-and-deploy system — and it is a prime attack surface. An attacker who gains access to the pipeline can inject malicious code into the build, sign it with your credentials, and ship it to production without anyone noticing (unless you're watching). A08 defences here are:

  • Least privilege — CI/CD workers (containers, VMs) run with minimal permissions; they can't ssh to prod, can't access secrets they don't need, can't push to main.
  • Audit logging — every CI/CD action (build start, secret access, deploy) is logged and monitored; unusual patterns trigger alerts.
  • Code review before merge — changes to production code require human review and approval; no auto-merge from a build or a bot (or if it exists, it's narrowly scoped and logged).
  • Artifact signing — the build produces a binary/image/package with a cryptographic signature; the deploy step verifies the signature before running it.
  • Signed commits — code commits are GPG-signed; the CI system verifies the signature and fails unsigned/invalid pushes (prevents an attacker who gains repo access from committing unsigned code).

The principle: every step in the pipeline must be auditable, and code/artifacts must be signed so you can prove they came from an authorized person/system.

Insecure Software Updates (Trusting Without Verifying)

Many apps auto-update without user intervention or verification. If the update mechanism doesn't verify the authenticity and integrity of the update, an attacker who can intercept or replace the update (via DNS hijacking, MITM, or compromised CDN) can push malicious code directly to users. A08 defences:

  • Sign updates — the update (binary, package, script) is cryptographically signed by the vendor's private key.
  • Verify the signature before installing — the client checks the signature using the vendor's public key; unsigned or invalid updates are rejected.
  • Use HTTPS for downloads — prevents simple interception (though doesn't stop a compromised server).
  • Staged rollouts — don't push the same version to all users at once; watch for crashes/anomalies in early adopters before rolling out globally.

The Integrity Idea: Trust is Proof, Not Faith

A08 = "verify, don't assume"
A08 collapses into one idea: never assume data or code is authentic or unmodified just because it came from a familiar source or format. Verify it cryptographically. Hashing (SHA-256) proves tampering (any change breaks the hash). Signing (asymmetric crypto) proves authorship (only the holder of the private key could have signed it). Encryption proves confidentiality (only the holder of the key can read it) — but not integrity; use authenticated encryption (AES-GCM) or sign + encrypt. The three places this matters most: (1) deserialization — only deserialize data you've authenticated; (2) CI/CD — sign commits, artifacts, deployments, and log everything; (3) software updates — sign updates and verify before installing.

Interlocks and Connections

A08 doesn't stand alone:

  • A06 (Vulnerable & Outdated Components) — A06 is about getting the component versions right; A08 is about ensuring the supply chain that delivers them is trustworthy. Together: inventory your deps (A06) + verify the build/deploy pipeline (A08) = you can ship with confidence.
  • A02 (Cryptographic Failures) — A08 uses cryptography (signing, hashing, authenticated encryption) to enforce integrity; weak crypto breaks A08's defences.
  • A05 (Security Misconfiguration) — not signing updates, not verifying signatures, auto-merge without review, overprivileged CI workers — these are all misconfigurations that enable A08 attacks.
  • A03 (Injection) — if an attacker injects malicious code into your code repository (via a compromised package, a MITM, or a CI/CD flaw), it is then built and shipped as part of A08's supply-chain attack.

Hands-On Exercises

Exercise 1

Explain why deserializing untrusted data with Java's ObjectInputStream (or Python's pickle) is an RCE vulnerability. Then contrast this with deserializing JSON; explain why JSON is safe and how you should validate it.

📄 View solution
Exercise 2

Design a CI/CD pipeline's integrity controls. List 5 defences (from least privilege to signed artifacts) and for each, explain: (a) what it prevents, (b) how an attacker exploits its absence. Then explain why code review before merge is the most critical one.

📄 View solution
Exercise 3

Explain the difference between hashing, signing, and authenticated encryption in terms of what each proves (tampering, authorship, confidentiality). Then give a concrete attack on an auto-update system that has no verification and explain how each of the three would stop it.

📄 View solution

Chapter 8 Quick Reference

  • A08 Software & Data Integrity Failures — failures to verify code/data is authentic & unmodified; proves trust, not assumes it; new in 2021
  • Deserialization RCE: native serializers (ObjectInputStream, pickle) execute methods during deserialization; crafted input = code execution. Fix: never deserialize untrusted data; use safe formats (JSON, protobuf) + validate.
  • CI/CD Pipeline Integrity: least-privilege workers · audit logging · code review before merge · signed commits · signed artifacts + verification. An attacker in the pipeline ships malicious code; every step must be auditable & signed.
  • Insecure Software Updates: auto-update without verification = attacker can push malicious code. Fix: sign updates + verify signature before install; use HTTPS; staged rollouts.
  • Integrity idea: verify, don't assume. Hashing proves tampering. Signing proves authorship. Authenticated encryption proves confidentiality + integrity. Use all three in the supply chain.
  • Interlocks with A06 (dependencies + supply chain), A02 (crypto), A05 (misconfig), A03 (code injection)
  • Next chapter: A09 Security Logging & Monitoring Failures — detecting attacks after they happen