PCI DSS 4.0 requirement 6: code review evidence that holds up
PCI DSS 4.0 requirement 6 is the part of the card industry standard written for the people who build software. If your application stores, processes or transmits cardholder data, or can affect the security of the systems that do, your assessor will ask how its code is reviewed, how it is protected against common attacks and what third-party components it contains. They will want evidence for each answer, not a policy that says it happens.
This post walks through the parts of requirement 6 that land on engineering teams (6.2.3 code review, 6.2.4 attack prevention and 6.3.2 the software inventory), what automated code scanning can contribute to each, and where it stops. It ends with the evidence Vulkro Core produces against the PCI DSS 4.0 requirements it maps.
Which version of PCI DSS applies?
The PCI Security Standards Council published PCI DSS v4.0 in March 2022 and a limited revision, v4.0.1, in June 2024. The revision corrected wording and clarified intent without adding or removing requirements, and v4.0 was retired at the end of 2024. The requirements that v4.0 introduced as future-dated best practices became mandatory on 31 March 2025, so every one discussed here now applies. The standard itself is in the PCI SSC document library; the requirement numbers below are the same in both versions.
Requirement 6 is titled "Develop and Maintain Secure Systems and Software". It speaks of bespoke and custom software: software developed for you by a third party (bespoke) or by your own teams (custom). Your payment service, your checkout front end and the internal API behind them are all in scope.
What does PCI DSS 6.2.3 require for code review?
6.2.3 requires that bespoke and custom software is reviewed before it is released into production or to customers, to identify and correct potential coding vulnerabilities. The reviews must check the code against your secure coding guidelines, look for both existing and emerging vulnerabilities, and make sure corrections are in place before release.
The standard allows the review to be manual or automated. When it is manual, 6.2.3.1 adds conditions: the reviewer is someone other than the author who knows code review techniques, and management approves the results before release.
This is the requirement automated scanning fits most directly. A scan that runs on every change before it merges is a review of that change against a defined set of rules, with a record of what it found and whether it was fixed.
What does PCI DSS 6.2.4 require?
6.2.4 asks that software engineering techniques or other methods are defined and in use to prevent or mitigate common attacks on bespoke and custom software. The standard lists the classes, including:
- injection attacks (SQL, LDAP, XPath, OS command and similar),
- attacks on data and data structures, such as buffer overflows,
- attacks on how cryptography is used,
- attacks on business logic, including abuse of APIs,
- attacks on access control mechanisms,
- and attacks through any high-risk vulnerability found under 6.3.1.
Here is the shape the first item usually takes in a Node.js payment service:
// Vulnerable: the order id from the URL becomes part of the SQL text
app.get('/orders/:id', requireLogin, async (req, res) => {
const { rows } = await db.query(
`SELECT id, amount, last4 FROM orders WHERE id = '${req.params.id}'`
);
res.json(rows[0]);
});
The fix binds the value as a parameter, and adds the ownership check that the access-control item on the same list asks for:
// Fixed: a bound parameter, scoped to the signed-in customer
app.get('/orders/:id', requireLogin, async (req, res) => {
const { rows } = await db.query(
'SELECT id, amount, last4 FROM orders WHERE id = $1 AND customer_id = $2',
[req.params.id, req.user.id]
);
if (!rows[0]) return res.sendStatus(404);
res.json(rows[0]);
});
The first version is exactly what a scanner should report under 6.2.4, with the route, the line and the path from req.params.id to the query. The second shows the access-control half of the same list; we wrote about why that one is so common in broken access control is still number one.
What does PCI DSS 6.3.2 require for the software inventory?
6.3.2 requires an inventory of bespoke and custom software, and of the third-party components incorporated into it, to support vulnerability and patch management. It was one of the future-dated requirements, so it has applied since 31 March 2025.
The standard does not name a format, but an SBOM generated from your lockfiles is the natural answer for the third-party part, because it lists the versions you actually ship. The related requirements 6.3.1 (identify vulnerabilities and rank their risk) and 6.3.3 (patch them in time) then work off that inventory. A dependency alert ranked by whether your code reaches the vulnerable function is far easier to act on within a patch window; we covered that in ranking dependency alerts by real risk, and the formats in SBOM and VEX explained.
What can automated code scanning evidence, and what can it not?
Scanning supports some requirement 6 controls directly and some not at all. It helps to be explicit with your assessor.
What it can evidence:
- 6.2.3: that each change was reviewed by an automated tool before release, what the review found and that findings were fixed or recorded.
- 6.2.4: code where an attack class on the list is still possible, such as injection, missing authorization or weak cryptography.
- 6.3.1 and 6.3.3: dependencies with published advisories or known compromised releases, with a severity.
- 6.3.2: the third-party component part of the inventory.
What it cannot:
- 6.1.1 and 6.2.2: documented processes and developer training are people and process controls.
- 6.2.3.1: whether a manual reviewer was independent and management approved.
- Whether the secure coding guidelines themselves are adequate.
- That an automated attack-protection solution is deployed in front of public web applications (6.4.2). Related code findings help, but the deployment itself is evidence from your infrastructure.
- Anything outside requirement 6: network segmentation, key management, physical security.
A scan with no findings also does not prove the code is safe. It proves no detector fired. Treat it as one input to the review, not the whole review.
How does Vulkro produce PCI DSS evidence?
Vulkro Core has a pci profile for a quick control view and a pci-dss-4-0 evidence pack that maps findings to PCI DSS 4.0 requirements 6, 11 and 12, control by control:
# control status in the terminal
vulkro compliance . --profile pci
# a folder of evidence for the assessor
vulkro compliance-pack . --framework pci-dss-4-0 -o pci-evidence/
# the component inventory for 6.3.2
vulkro sbom . --format cyclonedx > sbom.cdx.json
The pack writes a manifest, a summary, a findings CSV with file and line, one file per control and a pci-dss-4-0.html table. Each control carries a plain-language description and the rule IDs whose findings support or contradict it. In the pack, 6.2.3 is described as code review before release, where a scan in the merge or release pipeline is the automated review and its findings are what that review found. 6.2.4, 6.3.1, 6.3.2 and 6.3.3 are mapped the same way. Controls with no automated evidence, such as 6.1.1 and 6.2.2, say that Vulkro produces no evidence for them rather than showing a pass.
To make the review happen on every change rather than once a quarter, run vulkro gate --base origin/main in the pull request pipeline: it fails only on findings the change introduced. vulkro scan . --save keeps a dated history for the assessment period. Everything runs on your machine, so code from the cardholder data environment never leaves it.
A checklist for requirement 6 evidence
- Every change to in-scope code is scanned before it merges, and the result is stored.
- New High and Critical findings block release, and exceptions are approved and recorded.
- Manual reviews, where used, record an independent reviewer and management approval.
- An SBOM is generated per release and kept with it.
- Dependency advisories are ranked and patched within your defined time frames.
- Process and training evidence is kept separately, because no scan provides it.
Where to see it
The compliance evidence use case shows the control view. The PCI DSS reference and the compliance-pack reference list the controls and outputs, and the gate reference covers the pipeline step. To build a PCI pack from your own repository, start here.
Frequently asked questions
Can automated scanning satisfy PCI DSS 6.2.3?
PCI DSS allows code review to be manual or automated, so a scan that runs before release on every change can be the review 6.2.3 asks for. The assessor will still want evidence that findings were corrected before release. If you also review manually, 6.2.3.1 adds independence and approval conditions.
Is 6.3.2 the same as an SBOM requirement?
Not quite. 6.3.2 asks for an inventory of bespoke and custom software and the third-party components in it, without naming a format. An SBOM is the most practical way to cover the component part, and it also feeds the vulnerability work in 6.3.1 and 6.3.3.
Which PCI DSS requirements are out of scope for a code scanner?
Process and people controls such as 6.1.1 and 6.2.2, the deployed attack-protection solution in 6.4.2, and the network, key management and physical requirements elsewhere in the standard. A code scan sees code and dependencies, not how they are deployed.
Does a clean scan mean we pass requirement 6?
No. A clean scan means no detector fired on the code that was read. It is one piece of evidence for a review that also covers your guidelines, your process and your people. The assessor decides compliance, not the tool.
