Before Lab 3.5: API Security Testing with OWASP ZAP
Before Lab 3.5: API Security Testing with OWASP ZAP
What You'll Learn
Your application code passed Semgrep, dependencies passed Trivy, infrastructure passed Checkov. But how does your running API behave when accessed over the network?
OWASP ZAP (Zed Attack Proxy) performs dynamic application security testing (DAST) by sending HTTP requests to your deployed API and analyzing the responses for common vulnerabilities.
This lab focuses on:
- DAST vs. SAST: Testing running applications vs. static code analysis
- Baseline scanning: Passive, non-intrusive checks (no aggressive attacks)
- API-specific vulnerabilities: Missing headers, exposed debug info, weak TLS, CORS misconfigurations
- Post-deployment validation: Security checks that run after the app is deployed
SAST vs. DAST
Static Application Security Testing (SAST)
Tools: Semgrep, Trivy (code/dependency scanning)
When: Before deployment, during build
What it checks: Code patterns, dependencies, configuration files
Limitations: Cannot detect runtime behavior or environment-specific issues
Dynamic Application Security Testing (DAST)
Tools: OWASP ZAP, Burp Suite, Nuclei
When: After deployment, during testing
What it checks: HTTP responses, headers, TLS configuration, API behavior
Limitations: Requires running application, cannot see code logic
Complementary Approaches
Example: Semgrep might catch eval(userInput) in code. ZAP might catch missing X-Content-Type-Options header in the deployed API response.
What OWASP ZAP Tests
Baseline Scan (Passive Mode)
ZAP's baseline scan is designed for CI/CD pipelines. It:
- Sends normal HTTP requests (GET, POST) to your API
- Analyzes responses for security issues
- Does NOT attempt aggressive attacks (SQL injection payloads, fuzzing, brute force)
- Completes in minutes, safe for dev/test environments
Common API Vulnerabilities Detected
| Vulnerability | Description | Example Finding |
|---|---|---|
| Missing Security Headers | No X-Frame-Options, X-Content-Type-Options, Strict-Transport-Security | Clickjacking, MIME sniffing risks |
| Weak TLS Configuration | Outdated TLS 1.0/1.1, weak ciphers | Man-in-the-middle attack risk |
| Information Disclosure | Debug logs, stack traces, version headers in responses | Reveals technology stack to attackers |
| CORS Misconfiguration | Allows any origin (Access-Control-Allow-Origin: *) with credentials | Cross-origin data theft |
| Insecure Cookies | Missing Secure, HttpOnly, SameSite flags | Session hijacking risk |
| Open Redirects | Accepts untrusted URLs in redirect parameters | Phishing attacks |
ZAP Alert Levels
- High: Definite security issue (e.g., missing HSTS header over HTTPS)
- Medium: Likely issue requiring review (e.g., weak cookie settings)
- Low: Minor issue or best practice (e.g., missing
X-Content-Type-Options) - Informational: No direct risk, useful context (e.g., server version disclosure)
Reviewing ZAP Findings
HTML Report Format
ZAP generates an HTML report with:
- Summary: Total alerts by risk level
- Detailed findings: Each alert with description, URL, evidence, solution
- Affected URLs: Which endpoints triggered each alert


Example alert:
Alert: Missing Anti-clickjacking Header
Risk: Medium
Confidence: Medium
URL: https://<API_BASE_URL>/api/health
Description: The response does not include either Content-Security-Policy with
'frame-ancestors' directive or X-Frame-Options header.
Solution: Modern browsers support the Content-Security-Policy header. Add this
header with 'frame-ancestors' directive.Common Findings for Node.js/Express APIs
| Finding | Cause | Fix |
|---|---|---|
Missing X-Frame-Options | Not set by default | Use Helmet.js: helmet.frameguard({ action: 'deny' }) |
Missing Strict-Transport-Security | HTTP or missing HSTS header | Use Helmet.js: helmet.hsts({ maxAge: 31536000 }) |
X-Powered-By: Express header | Express default | Disable: app.disable('x-powered-by') or use Helmet |
| Weak TLS cipher suites | Azure App Service default | Configure custom TLS policy in Azure |
| CORS allows any origin | cors({ origin: '*' }) | Restrict: cors({ origin: process.env.FRONTEND_ORIGIN }) |
Fixing vs. Accepting Findings
High-Priority Fixes
These should be addressed before production:
- Missing security headers (X-Frame-Options, X-Content-Type-Options, CSP)
- Weak TLS configuration (TLS 1.0/1.1, weak ciphers)
- CORS misconfigurations allowing credential theft
- Insecure cookie settings (missing Secure/HttpOnly flags)
Low-Priority/Accepted Risks
These may be documented as known issues:
- Server version disclosure (informational, low risk if patched)
- Missing HSTS on HTTP endpoints (if HTTPS redirect is in place)
- Debug info in dev environment (acceptable if not in production)
Suppression Strategy
Unlike Trivy/Checkov, ZAP doesn't have a built-in suppression file. Instead:
- Fix in code: Update Helmet configuration, CORS settings, cookie options
- Document in pipeline: Add comments explaining why certain alerts are accepted
- Environment-specific scans: Run stricter checks against production, relaxed checks against dev
Key Questions Before Starting
Why run ZAP after deployment instead of during build?
DAST requires a running application to send HTTP requests and analyze responses. You cannot test API security headers, TLS configuration, or runtime behavior until the app is deployed and accessible.
Is baseline scan sufficient for production?
Baseline scan is a minimum check for CI/CD. For production, consider:
- Full ZAP scan (authenticated, deeper testing)
- API schema-based testing (OpenAPI import)
- Penetration testing by security professionals
How do you prevent ZAP from attacking production?
- Use baseline scan only (no active attacks)
- Scan dev/test environments in pipeline, not production
- For production validation, use passive monitoring tools (not ZAP)
What if ZAP finds a vulnerability in a third-party dependency?
ZAP tests the deployed API behavior, not dependencies. If ZAP finds a vulnerability, it's likely in your code or configuration (missing headers, weak TLS). Dependency vulnerabilities are caught by Trivy, not ZAP.
What You'll Do in Lab 3.5
- Run OWASP ZAP baseline scan against the dev API URL
- Review HTML report for missing headers, TLS issues, CORS misconfigurations
- Fix high-priority findings using Helmet.js or Azure configuration
- Verify pipeline integration and artifact publishing of ZAP reports
Lab File
Download Lab 3.5 — OWASP ZAP PDF