Use code review to find likely defects early, then use penetration testing to confirm whether those defects are exploitable in the deployed system. The two controls answer different questions. One identifies risk in source code, while the other validates behaviour under real runtime conditions, including configuration, trust boundaries, and chained attack paths.
Why This Matters for Security Teams
Code review and penetration testing solve different parts of the same assurance problem. Code review is strongest when teams need to spot insecure logic, unsafe assumptions, hidden authz gaps, or dependency misuse before deployment. Penetration testing is strongest when the question is whether those weaknesses can be chained into a real compromise in the live environment. That distinction matters because many failures are not visible in source alone, especially when configuration, integrations, identity boundaries, or third-party services shape the actual attack surface.
For security leaders, the real value is sequencing. Review helps reduce the number of exploitable defects that reach production. Testing helps validate which issues actually matter under runtime conditions. That makes the pair complementary rather than redundant, and it aligns well with the outcome-oriented approach in the NIST Cybersecurity Framework 2.0, which emphasises continuous risk management rather than a single assurance event.
In practice, many security teams discover the gap between “looks safe in code” and “is safe in production” only after an application has already been abused through a trust-boundary mistake or a chained exploit path.
How It Works in Practice
The most effective pattern is to treat code review as a preventive control and penetration testing as a validation control. Review should focus on high-risk areas such as authentication flows, authorisation checks, input handling, secrets use, cryptography calls, deserialisation, and any logic that changes privilege or data access. Pen testing should then target the deployed system to see whether those same conditions can be reached, bypassed, or combined with misconfiguration, exposed services, or weak identity controls.
A practical workflow usually looks like this:
- Review the code first, especially changes touching security-sensitive paths.
- Map findings to likely attack paths, not just code defects.
- Test the running application with its real configuration, dependencies, and network exposure.
- Validate whether compensating controls, such as WAF rules, IAM policies, or segmentation, change exploitability.
- Feed confirmed findings back into secure coding standards and regression tests.
This approach is consistent with control integration guidance in OWASP work on application security, and with adversary-focused validation thinking from MITRE ATT&CK, where the emphasis is on how weaknesses are actually abused, not just whether they exist.
Teams should also make room for automated support. Static analysis can accelerate review, while dynamic testing and manual exploitation attempts can confirm real-world impact. Neither replaces expert judgment. A finding that is “theoretically severe” in code may be harmless in deployment if the relevant path is unreachable, while a modest flaw may become critical when paired with weak credentials, overly broad privileges, or exposed admin interfaces. These controls tend to break down when release cycles are too fast for meaningful review and the production environment drifts from what the testers actually saw.
Common Variations and Edge Cases
Tighter review and deeper testing often increase delivery time and specialist effort, so organisations have to balance assurance against release pressure and risk tolerance. The right mix depends on application criticality, change volume, and the maturity of the engineering team.
There is no universal standard for how much code review and pen testing is enough. Current guidance suggests risk-based depth: high-impact systems deserve targeted manual review and attacker-minded testing, while lower-risk changes may rely more on automated checks and selective validation. For cloud-native and microservices environments, the issue is often less about a single application bug and more about service-to-service trust, secrets exposure, and identity propagation across components. In those cases, penetration testing should examine the assembled system, not just the codebase.
Another edge case is when security tooling creates a false sense of coverage. A clean static scan does not prove exploit resistance, and a passing pen test does not guarantee that future code changes are safe. That is why review findings should become test cases, and pen test findings should become code-level guardrails. For teams handling regulated data or resilient services, the operational model should also reflect NIST Cybersecurity Framework 2.0 principles of continuous improvement rather than one-time verification.
The biggest exception is legacy systems with poor testability and limited source access. In those environments, penetration testing often carries more weight because code review may be incomplete, stale, or impossible to perform effectively.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
OWASP Non-Human Identity Top 10 and MITRE ATT&CK address the attack and risk surface, while NIST CSF 2.0, NIST AI RMF and NIST SP 800-63 set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| NIST CSF 2.0 | GV.OC-01 | Risk context determines how much review and testing the system needs. |
| OWASP Non-Human Identity Top 10 | NHI-01 | Secrets and credential misuse often surface in code before they are exploitable. |
| NIST AI RMF | GOVERN | Assurance should be governed as a lifecycle process, not a one-off check. |
| NIST SP 800-63 | Identity assurance matters when testing auth flows and session handling. | |
| MITRE ATT&CK | T1190 | Pen testing validates whether application weaknesses are reachable for exploitation. |
Validate authentication and session controls in the live environment, not just in code.
Related resources from NHI Mgmt Group
- How should security teams combine AI code scanning with runtime security?
- How should security teams design AI review pipelines for code changes?
- How should security teams use AI-assisted code review safely?
- How should security teams use AI-assisted penetration testing without losing trust in the results?