Software and Data Integrity Failures

Advanced
11 min

Software and Data Integrity Failures

OWASP's "Software and Data Integrity Failures" (A08) describes a family of problems with one root: code or data is trusted without verifying where it came from or whether it changed on the way. A CDN script that was modified, a CI pipeline that runs an unpinned plugin, a serialized object that turns into code when it is loaded, a webhook whose sender was never checked. Each is an integrity failure, and each has become a real-world breach.

In this lesson you will learn to protect browser assets with Subresource Integrity, avoid insecure deserialization, harden the build and deploy pipeline, and verify signed messages from third parties.

Subresource Integrity for Third-Party Assets

Loading a script from a CDN means trusting the CDN forever. Subresource Integrity (SRI) pins the exact bytes: the browser hashes the downloaded file and refuses to execute it if the hash differs.

html
<script src="https://cdn.example.com/lib/4.2.0/lib.min.js" integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC" crossorigin="anonymous"></script>

Generate the value at build time and update it whenever you upgrade the library:

bash
openssl dgst -sha384 -binary lib.min.js | openssl base64 -A

SRI only works for files with fixed content, so pin versions rather than loading latest. For everything else, self-host the asset so it lives under your own release process.

Insecure Deserialization

Deserialization turns bytes back into objects. Formats that can describe behaviour as well as data (Java serialized objects, Python pickle, PHP unserialize, and Node.js packages that "serialize functions") execute attacker-controlled logic when they load untrusted input. JSON is safer because JSON.parse produces plain data, but it still needs care:

javascript
const data = JSON.parse(req.body); // data only, never code // Guard against prototype pollution when merging parsed objects function safeMerge(target, source) { for (const key of Object.keys(source)) { if (key === "__proto__" || key === "constructor" || key === "prototype") continue; target[key] = source[key]; } return target; }

Rules: never deserialize untrusted input with a format that can carry code, validate the parsed structure with a schema before use, and treat any library that "revives" functions or classes from user input as a remote code execution feature.

Pipeline Integrity

The build pipeline has write access to production, which makes it a prime target. Harden it like an application:

yaml
# .github/workflows/deploy.yml (excerpt) permissions: id-token: write # OIDC: short-lived cloud credentials, no stored secrets contents: read steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # pinned by commit SHA, not tag - run: npm ci --ignore-scripts - run: npm test - run: npm publish --provenance --access public # signed build attestation
  • Pin third-party actions and base images by digest, not by mutable tag.
  • Require reviewed pull requests and signed commits on the release branch; nobody pushes directly.
  • Replace long-lived deploy keys with OIDC-issued tokens scoped to one job.
  • Publish packages with provenance so consumers can verify which repository and workflow built them.

Verifying Data from Third Parties

Any message that arrives from outside must prove its origin before it changes state. The sample code verifies a payment webhook: the HMAC is computed over the raw body (re-serialising JSON would change the bytes), compared in constant time, and only then parsed. The same principle covers software updates (verify the vendor's signature before installing), configuration fetched at runtime (sign it or fetch it over a mutually authenticated channel) and any "callback" URL parameter your application follows.

Quick Quiz
Question 1 of 2

What does the `integrity` attribute on a `<script>` tag do?

Key Takeaways

  • Integrity failures come from trusting code or data without verifying origin and unchanged content.
  • Use Subresource Integrity with pinned versions for CDN assets, or self-host them.
  • Never deserialize untrusted input with formats that carry code; validate parsed JSON and block __proto__ keys.
  • Pin pipeline dependencies by SHA, require reviews and signed commits, use OIDC credentials, publish with provenance.
  • Verify HMAC signatures over raw bytes in constant time before acting on webhooks or updates.

Next lesson: Security Logging and Monitoring — seeing an attack while it is happening instead of months later.

Software and Data Integrity Failures - Cyber Security | CodeYourCraft | CodeYourCraft