14.8 · Defensive coding: secure decoding, injection, dependency integrity and file protection

Most real breaches in apps come from untrusted input reaching a powerful interpreter, or from trusting something you did not verify. Each question here reproduces the bug and the fix.

Mental model. Treat every byte that crosses a boundary as data until a typed, checked path says otherwise.

Untrusted input

Decoding archives safely and keeping data out of interpreters.

  1. What is NSSecureCoding, what attack does it prevent, and how do you unarchive data from an untrusted source? 14.8.1 · L3
    Unarchiving builds objects of classes named in the data. If the decoder lets the data choose any class, a crafted archive can instantiate and run initialisers…
  2. Where else besides SQL can injection happen in an iOS app: NSPredicate, JavaScript in a web view, URLs, and what is the common fix? 14.8.2 · L3
    Injection is always the same bug: data concatenated into a string that another interpreter then parses as code. SQL is the famous case and the fix is a bound…

What you ship and store

Verifying dependencies and the real behaviour of data protection classes.

  1. How do you keep third-party code from being swapped under you: Package.resolved, revisions, binary target checksums and what a checksum does not prove? 14.8.3 · L3
    Your app’s security includes every dependency, so treat them as code you ship. With Swift Package Manager, Package.resolved records the exact version and Git…
  2. What do the file protection classes mean, how do you set them, and why can you not test them in the simulator? 14.8.4 · L3
    Data Protection ties a file’s encryption key to the device passcode. The four classes, with the raw strings you see in code: NSFileProtectionComplete (readable…

More in Security & privacy