Writing
secure code review
11 articles on this subject.
The document that reads your filesystem: XXE in docx, xlsx and SVG parsers
A docx, xlsx or SVG is a bundle of XML, and an XML parser that resolves external entities will fetch files and URLs on the attacker's behalf. CVE-2019-12415 in Apache POI is the office-document case. How XXE reaches an upload endpoint, how to find it, and how to turn it off.
9 min read
Writing to __proto__: prototype pollution in Node.js and the lodash defaultsDeep bug
Prototype pollution lets an attacker set a property on every object in a Node process by writing through __proto__. CVE-2019-10744 in lodash is the canonical case. How the merge goes wrong, how to find it, and how it differs from Python class pollution.
9 min read
No 'Access-Control-Allow-Origin' header is present on the requested resource: the error is right, and both popular fixes are vulnerabilities
No 'Access-Control-Allow-Origin' header is present on the requested resource. The two fixes developers copy do not fix CORS, they delete it. One is account takeover.
13 min read
CERTIFICATE_VERIFY_FAILED: unable to get local issuer certificate is not corruption, and verify=False is not a fix
CERTIFICATE_VERIFY_FAILED: unable to get local issuer certificate means no path to a trusted root. The five real causes, and why verify=False is not a fix.
13 min read
COPY ... TO PROGRAM in mail_logs: what Cisco's CVE-2026-76461 indicator actually means
COPY ... TO PROGRAM is a documented PostgreSQL feature that runs shell commands. Why Cisco's CVE-2026-76461 grep turns SQL injection into root, and how to hunt it.
12 min read
ECB byte-at-a-time: recovering a secret you are never shown
If an application encrypts your input concatenated with a secret, and does it in ECB mode, you can extract that secret one character at a time. A complete walkthrough with runnable code. The clearest demonstration of why ECB is not encryption.
7 min read
BOLA, BFLA, BOPLA: the three authorisation bugs no scanner will find for you
Optus lost roughly 10 million customer records to an API with sequential IDs and no authorisation check. Here is how to tell the three authorisation failures apart, how to test each one, and why automated tools are structurally blind to them.
7 min read
Prototype pollution has a Python cousin: class pollution and the road to __globals__
Python has no prototypes, so it cannot have prototype pollution, except it can. A walkthrough of class pollution: the vulnerable merge function, the four attribute chains that matter, and how to spot it in a code review.
7 min read
Argument injection: how a soft hyphen became CVE-2024-4577 and put 9.8 on the board
You escaped the shell metacharacters and the command still ran. Argument injection is the bug that survives shell-safe APIs, here is the mechanism, the PHP-CGI case that got mass-exploited, and the one-character fix.
7 min read
Pickle is a code format, not a data format: CVE-2025-32434 and the model file you just downloaded
torch.load(weights_only=True) was the recommended safe path, and it was bypassable. A practical look at Python deserialization, pickle, PyYAML and jsonpickle, how one gadget works, and what actually stops it.
12 min read
Server-side template injection: why {{7*7}} is a bad test, and how CVE-2023-22527 got to CVSS 10.0
Most SSTI write-ups teach one Jinja2 payload and stop. Here is the actual bug class, the per-engine probe table, a lab you can build in ten minutes, and the code-review rule that removes it entirely.
9 min read