Every engineering team runs a CI/CD pipeline. Most of them run unit tests, integration tests, and maybe a SAST scan. Very few validate against the OWASP Top 10 at runtime — the class of vulnerabilities that static analysis cannot catch.
This guide shows you how to close that gap, whichever DAST tool you use.
Why OWASP Top 10 Requires Runtime Validation
OWASP's most critical category, Broken Access Control (A01), cannot be detected by reading code. Tools need to exercise the application as a real attacker would — submitting requests, testing authorization boundaries, probing for privilege escalation.
Static analysis misses:
- IDOR (Insecure Direct Object Reference) — requires authenticated session testing
- JWT algorithm confusion — requires crafting malformed tokens
- Mass assignment — requires understanding business object structure
This is exactly what DAST (Dynamic Application Security Testing) is designed for.
The Pipeline Integration Pattern
A security-gated pipeline looks like this:
git push
→ Build & Unit Tests
→ Deploy to staging
→ DAST scan (OWASP Top 10 validation)
→ Gate: fail if CRITICAL or HIGH findings
→ Deploy to production
The key insight: the DAST scan runs against the live staging environment, not against source code.
Step 1: Define Your Target Scope
Before running any scan, write down what's in scope, and keep it in version control next to your pipeline config, in whatever format your scanner expects:
- Base URL: your staging environment (for example
https://staging.yourapp.com), never production for active tests - Paths to include: for example
/api/v1/**and/dashboard/** - Paths to exclude: anything with side effects — email sends, payment triggers, third-party webhooks
- Test accounts: referenced by name and stored as CI secrets, never written into the scope file
Only scan assets you own or are authorized to test.
Step 2: Authentication — The Most Skipped Step
Most teams run unauthenticated scans and wonder why they miss half the vulnerabilities. Authentication is non-negotiable for OWASP A01 (Broken Access Control).
Configure your scanner with a dedicated scan account that has standard user privileges. Run a second pass with an elevated account to test privilege separation.
Keep both sets of credentials in your CI system's secret store and pass them to the scan step as environment variables. How a scanner accepts credentials (a bearer token, a session cookie, a scripted login) varies by tool, so check its documentation.
Step 3: Map OWASP Categories to Scan Rules
The table uses the OWASP Top 10:2021 categories, which many scanners still use to label findings. The 2025 edition reorders and merges some of them — see what changed in the OWASP Top 10:2025.
| OWASP Top 10:2021 category | Scan Technique | Can Automate? |
|---|---|---|
| A01 Broken Access Control | IDOR testing, auth bypass | Partially |
| A02 Cryptographic Failures | TLS audit, header analysis | Yes |
| A03 Injection | SQL, XSS, SSTI active probing | Yes |
| A04 Insecure Design | Threat modeling | No |
| A05 Security Misconfiguration | Header/config audit | Yes |
| A06 Vulnerable Components | SCA scan | Yes |
| A07 Auth & Session Failures | Session fixation, brute-force | Yes |
| A08 Software Integrity | SBOM verification | Yes |
| A09 Logging Failures | Response analysis | Partially |
| A10 SSRF | Blind SSRF probing | Yes |
Categories A04 and A09 require human review. The rest can be automated at least partially.
Step 4: Gate Your Pipeline
Set your pipeline to fail on critical or high findings only — medium and low should create tickets, not block deployments. This prevents alert fatigue while maintaining a meaningful security gate.
Scanners report results differently (exit codes, JSON or SARIF reports), so the gate is usually a short script that reads the report:
# Pseudo-code: adapt to your scanner's report format
findings = load_report("scan-report.json")
blocking = [f for f in findings if f.severity in ("critical", "high")]
if blocking:
fail_pipeline("CRITICAL/HIGH findings — deployment blocked")
elif findings:
create_ticket(findings) # medium/low: track it, don't block
Step 5: Handle False Positives Systematically
Every DAST tool generates some false positives. Build a suppression list in code (not in the tool UI) so it's version-controlled, and have the gate script from Step 4 apply it:
# security/suppressions.yml (read by your own gate script; the format is up to you)
suppressions:
- rule: "sql-injection"
url: "/api/v1/search"
reason: "Parameterized query confirmed via code review"
expires: "2026-06-01"
approved_by: "security-team"
Never suppress permanently — always set an expiry date and require security team sign-off.
The Result: Security as Code
When OWASP validation runs in your pipeline, security stops being a gate that happens once a quarter. It becomes a continuous signal — every feature branch, every PR, every deployment.
The teams that ship the fewest vulnerabilities don't have the best security team. They have security embedded in the feedback loop that engineers already use every day.
PentestCheck doesn't run inside your pipeline. It works from the outside: it maps the internet-facing assets of domains you own and scans them on demand or on a daily, weekly or monthly schedule, labeling findings with OWASP Top 10:2021 categories where a detection maps to one.