◇ OpenCyber Academy
Technologist · Chapter 14 · English

Chapter 14 — Application and software supply chain security: methods I

Open, free learning for anyone who wants to protect people and technology. No account is required to read this text or its worked answers.

Chapter 14 — Application and software supply chain security: methods I

Lesson map

Lesson 14 published. Map, example, EX040.

flowchart TD
  N0["Learning outcomes"]
  N1["14.1 Why uploads matter"]
  N2["14.2 The checks"]
  N3["Lab — upload checks"]
  N4["14.3 Lab result"]
  N5["14.4 Testing"]
  N6["Reviewing the rules"]
  N7["Shared module"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
  N7 --> EX["Worked example"]
  EX --> Q["Exercise EX040"]

Logical drawing

flowchart LR
  N0["Learning outcomes"]
  N1["14.1 Why uploads matter"]
  N2["14.2 The checks"]
  N3["Lab — upload checks"]
  N4["14.3 Lab result"]
  N5["14.4 Testing"]
  N6["Reviewing the rules"]
  N7["Shared module"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7 --> Q["EX040"]
[Learning outcomes]
    |
    v
[14.1 Why uploads matter]
    |
    v
[14.2 The checks]
    |
    v
[Lab — upload checks]
    |
    v
[14.3 Lab result]
    |
    v
[14.4 Testing]
    |
    v
[Reviewing the rules]
    |
    v
[Shared module]
    |
    v
[Worked example] --> [Exercise EX040]

Learning outcomes

You will (1) validate file uploads safely; (2) check type, content and size; (3) store uploads safely; (4) test the checks with synthetic files.

14.1 Why uploads matter

The Greenleaf flaw was in upload handling. Even with a patched library, Brightwave wants its own checks so that a future library flaw is less likely to be reachable. OWASP ASVS 4.0.3 section V12 covers files and resources. The January flaw showed that Brightwave relied entirely on upload-kit to handle uploads safely. Adding its own checks means the next library flaw would have to get past Brightwave's rules as well, which makes the flaw less likely to be reachable from the public booking form.

14.2 The checks

Allow only listed types (PNG, JPEG, PDF); check that the file content matches the claimed type by its leading bytes; limit size to 5 MB; give stored files new random names; store them outside the web root and serve them with a safe download header. Each of these checks addresses a different problem with uploaded files. The type allowlist rejects files the clinic never needs, the content check rejects files whose leading bytes do not match their name, the size limit protects storage and processing, and random names stop an upload from choosing where it lands.

Lab — upload checks

"""Validate synthetic uploaded files: extension allowlist, size limit and content signature."""
SIG = {".png": b"\x89PNG", ".pdf": b"%PDF"}
files = [("xray.png", b"\x89PNG....", 120_000), ("report.pdf", b"%PDF-1.7", 900_000),
         ("notes.pdf", b"PK\x03\x04", 40_000), ("scan.png", b"\x89PNG....", 9_000_000), ("run.exe", b"MZ..", 10_000)]
for name, head, size in files:
    ext = name[name.rfind("."):]
    if ext not in SIG: verdict = "reject: type not allowed"
    elif size > 5_000_000: verdict = "reject: too large"
    elif not head.startswith(SIG[ext]): verdict = "reject: content does not match type"
    else: verdict = "accept"
    print(f"{name:11} {verdict}")

Run with python3 lab_upload.py. Verified output:

xray.png    accept
report.pdf  accept
notes.pdf   reject: content does not match type
scan.png    reject: too large
run.exe     reject: type not allowed

14.3 Lab result

xray.png and report.pdf are accepted. notes.pdf is rejected because its content does not match a PDF. scan.png is rejected as too large. run.exe is rejected because the type is not allowed. Every rejection names its reason, which helps support staff explain it to clinic users. The order of checks matters: run.exe is rejected on type before its content is ever examined. The lab's signature table covers only PNG and PDF, so JPEG support would need its own entry before JPEG uploads could be accepted.

14.4 Testing

Synthetic test files cover each rule. Tests run in the build on every change. For each rule there is at least one file that should pass and one that should fail, mirroring the five lab files. A change that loosens a rule therefore fails the build, and the reviewer sees exactly which test broke. The synthetic files are tiny and contain no real patient data. Diego adds a test whenever a support case shows a file the rules handled wrongly.

14.5 Limits

Content checks reduce risk but cannot prove a file is harmless; storage and serving rules provide the second layer. A PDF with correct leading bytes can still contain unexpected content, so a passing check is not a guarantee. That is why accepted files are stored outside the web root with new names and served as downloads, so even a harmful file is never run by the server or rendered as part of the site. The second layer is what protects clinics if a future content check misses something new.

Reviewing the rules

The allowed types and size limit are reviewed with each client, since clinics, museums and cafes need different files. Every change to the rules goes through review with updated tests.

Shared module

The checks live in one shared module used by all client projects, so a fix reaches everyone at the next deployment.

Worked example

After the checks go live, the Greenleaf support log shows clinic users occasionally uploading oversized phone photos. Brightwave adds a clear message suggesting how to reduce size instead of raising the limit.

Synthetic case. Files are synthetic.

Errors and limits

Keep the allowed list short; every added type adds risk.

Exercises

Synthesis

Validate uploads on type, content and size, and store them safely.

Continue studying — chapter 14 of 30

← Chapter 13 (draft) · Course chapter index · Chapter 15 (draft) →