PCI DSS requires that code review be performed by someone other than the code's author.
When an AI writes the code, who is the author?
I've been building payment SDKs for four years and using AI tooling as my primary development environment for the last one. That question sounds like a technicality. It isn't. It sits at the centre of how I now review anything before it ships.
Here's what I've learned.
The blast radius is different
When you write a mobile app, a mistake affects your users. When you write an SDK, a mistake ships to every merchant who integrates it, and then to all of their users. You don't get to push a hotfix and be done — you publish a version, and it propagates at whatever speed your integrators upgrade. Some never do.
That asymmetry existed before AI. What changed is throughput. I now produce more code in a day than I used to produce in three, and my review capacity did not triple. If you don't consciously rebalance, the ratio of code written to code genuinely understood quietly degrades — and in a payments library, that ratio is the whole job.
So I stopped treating generated code as a draft to be corrected and started treating it as a third-party contribution from a fast, confident contributor who has never read our threat model.
Four failure modes I look for specifically
Logging. This is the one that worries me most, because it's invisible in review if you're skimming. Ask for error handling and you'll often get generous, helpful diagnostics — the full request body, the complete response object. In a payments path, one such line can put a primary account number into a log aggregator, or capture sensitive authentication data that must never be retained after authorization. The code is correct. The code also just created a compliance incident. I now grep every generated diff for logging statements before I read anything else.
Cryptographic defaults. Ask for encryption and you frequently get something that works and shouldn't be used — a weak mode, a static initialization vector, a hash chosen for speed rather than resistance. It compiles, the tests pass, and the round trip succeeds. Correctness and security are different properties, and generated code optimizes for the first.
Storage shortcuts. Tokens and credentials land in UserDefaults or SharedPreferences with remarkable consistency. It's the path of least resistance and it's wrong. Keychain and Keystore exist for a reason, and the generated code rarely reaches for them unless you say so explicitly.
Dependencies. This is the newest one. Suggested packages arrive with total confidence, and some of them are unmaintained, some are wrong, and occasionally some don't exist at all — which is itself an attack surface now that adversaries have noticed the pattern. In an SDK, every dependency you add becomes a dependency your merchant inherits without ever choosing it. I don't accept a new package from a suggestion. Ever.
What actually changed in my practice
Three things.
I review generated code harder than hand-written code, not more leniently. The instinct runs the other way — it looks clean, it's well-structured, it has comments. That polish is exactly what makes it dangerous to skim.
I read diffs in a fixed order now: logging, then data handling, then crypto, then logic. Logic bugs surface in testing. The first three often don't.
And I stay slow at the trust boundaries. Card data handling, tokenization, key management, the network layer — I write these myself or review them line by line, because those are the places where a plausible-looking mistake is also a reportable one.
Everywhere else, the tooling has made me substantially faster, and I'm not interested in pretending otherwise.
The question I don't have a clean answer to
Back to the beginning. The separation-of-duties requirement exists because authors are blind to their own assumptions. A second reader breaks that blindness.
But when I prompt for an implementation, review it, adjust it, and commit it — am I the author who needs a second reader, or am I the second reader?
I've settled on treating myself as the author, because I made the decisions that shaped the output and I'm the one who chose to ship it. That means generated code still gets a colleague's eyes before it goes anywhere near production. It's the more conservative reading, and in payments I'd rather be conservative than clever.
I'm not certain that's the right answer. I'm fairly certain the standards haven't caught up with the question yet.
If you work in payments or any regulated environment and you've thought this through differently, I'd like to hear it.
Top comments (0)