You find vulnerabilities in source code by combining methods, since each misses what others catch: human code review, automated static analysis, tests against the running build, and checks on the third-party code you pull in. NIST's secure software development framework asks teams to decide when each applies and to triage every finding in one tracked queue.
What methods does NIST describe?
NIST SP 800-218, the Secure Software Development Framework (SSDF), has several practices for this. PW.7 covers reviewing or analyzing human-readable code to find vulnerabilities before release. It distinguishes code review, where a person looks directly at the code, from code analysis, where tools find issues automatically or with a person. Human-readable code includes source, scripts and anything else readable. PW.8 covers testing executable code to find vulnerabilities that earlier reviews, analysis or testing did not.
NIST's own notes say that automated methods lower the effort and resources needed to find vulnerabilities, and its examples are practical:
- Follow your policy for when review and analysis must happen, including for third-party and reusable code.
- Choose methods based on the stage of the software.
- Perform peer review, and read any existing analysis or test results during that review.
- Use expert reviewers to check for backdoors and other malicious content.
- Run a static analysis tool automatically, with a human reviewing what it reports.
- Use review checklists to verify compliance with requirements.
- Use automated tools to find documented unsafe practices continuously as code is checked in.
- Record the root cause of issues found, and keep lessons learned where developers can search them.
What does each method find?
Human review finds logic errors, broken authorization, misuse of an API and design flaws, since a person can ask whether the code should do what it does. It is slow and varies with the reviewer's attention.
Static analysis reads the code without running it. It is good at known patterns: unvalidated input reaching a query, unsafe function calls, hard-coded secrets. It produces false positives and cannot see runtime configuration. Related practice PW.5.1 lists validating all inputs, properly encoding outputs and avoiding unsafe functions, which are the patterns these tools look for.
Dynamic and executable testing runs the build and probes it. It finds what only exists at runtime: configuration, deployment issues, flaws in how components interact. Slower, and can only exercise paths it reaches.
Dependency analysis covers the code you did not write. Most of a modern application is libraries, so known vulnerabilities in those matter as much as your own bugs.
A constructed example
A small team ships a file upload feature. A reviewer reads the pull request and notices the filename from the request is used directly to build a path. That is a logic and trust issue a tool might flag only as a generic warning. Static analysis separately flags a query built by string concatenation in another module. A dependency scan finds that the image library used for thumbnails has a known flaw, but only one function is affected and the app never calls it. Each method found something different, and the team fixes the path and query bugs first and schedules the library bump. The example is invented.
How do you keep findings usable?
A pile of tool output is not a program. SSDF PW.7.2 says to record and triage all discovered issues and recommended remediations in the development team's workflow or issue tracking system. In practice that means:
- One queue, with each finding having an owner and a status.
- A shared rule for severity that includes whether the code is reachable and exposed.
- Suppression with a reason, reviewed on a schedule, rather than silent ignore.
- A feedback loop: root causes become checklist items, lint rules or tests.
How to check or apply this
- Write a short policy: which changes need human review, which checks run on every commit, and which run before release.
- Turn on static analysis in the pull request path, and set it to block only on high-confidence, high-impact findings at first.
- Add a dependency scan and an inventory of what you use.
- Run tests against a deployed build in a safe environment on a regular schedule.
- Use a review checklist for risky areas such as authentication, file handling and queries.
- Send every finding to your issue tracker with an owner.
- Track how long findings stay open, and fix recurring causes at the source.
- Re-check after every large dependency or framework change.
Safeguard's scanners cover static code analysis, dependency inventory and secrets, and its reachability analysis helps separate flaws that your code can actually hit from those it cannot. Gold also offers a free in-browser scan at gold.safeguard.sh/scan for up to 100 dependencies. Tools support review. They do not replace it.
Quick check
Is static analysis enough on its own?
No. It misses logic flaws and runtime issues, and produces false positives. NIST's framework pairs it with human review and executable testing.
Should every finding be fixed immediately?
No. Triage by impact, exposure and reachability, record the decision, and fix the highest risks first.
Sources
Last reviewed: 18 October 2026.