Security Testing: SAST, DAST and OWASP ZAP Basics

Advanced
12 min

Security Testing: SAST, DAST and OWASP ZAP Basics

Every control in this course can be tested, and untested controls erode: a refactor drops a middleware, a new route skips the role check, a dependency update reintroduces a known flaw. Security testing puts those checks into the pipeline so regressions are caught like any broken unit test. No single tool covers everything, so layer several cheap ones.

In this lesson you will learn what each testing category finds, how to run static analysis on Node.js code, how to run an OWASP ZAP scan against a running application, how to write security assertions as ordinary tests, and how to triage results.

The Testing Layers

| Layer | What it examines | Finds | Typical tools | |---|---|---|---| | SAST (static) | Source code, without running it | Injection sinks, unsafe APIs, hard-coded secrets | Semgrep, CodeQL, ESLint security plugins | | SCA (composition) | Dependency manifests | Known vulnerable packages | npm audit, Dependabot, Snyk | | Secret scanning | Repository contents and history | Committed credentials | gitleaks, host push protection | | DAST (dynamic) | The running application over HTTP | Missing headers, reflected input, exposed endpoints | OWASP ZAP | | Security unit tests | Your own controls | Regressions in authz, validation, headers | Jest or Vitest with supertest |

Static tools run in seconds on every pull request; dynamic tools run against staging; periodic manual review and penetration testing find the logic flaws tools cannot.

Static Analysis with Semgrep

Semgrep matches code patterns, and its community rule packs for Node.js and Express cover the classic sinks:

bash
# Run the Node.js and Express rule packs, fail on findings, output SARIF for code-scanning UIs semgrep scan --config p/nodejs --config p/express --error --sarif --output semgrep.sarif

A typical finding points at an exec() call built from a variable and links to the fix. Add project-specific rules for your own conventions, such as "every router under /admin must call requireRole". Findings that block a merge get fixed; weekly reports get ignored.

Dynamic Scanning with OWASP ZAP

ZAP is a free proxy and scanner. Its baseline scan spiders the target and runs passive checks only, so it is safe against staging in every pipeline:

bash
docker run --rm -v "$PWD":/zap/wrk:rw ghcr.io/zaproxy/zaproxy:stable \ zap-baseline.py -t https://staging.example.com -r zap-report.html -c zap.conf

The report lists missing security headers, cookies without flags, information leakage and reflected parameters. The full scan (zap-full-scan.py) adds active attacks such as injection probes; run it only against environments you own, with written authorization, never against production or third parties. For APIs, zap-api-scan.py takes an OpenAPI definition so every documented endpoint is exercised.

Security Tests in Your Own Suite

The most durable checks live next to the feature tests. The sample file asserts three controls: the header baseline, ownership on a data route, and type validation on a login body. Write one such test for every control you add: 403 for the wrong role, 413 for an oversized body, 429 after the limit, 401 for an expired token. They run in milliseconds and fail the build on exactly the regression a refactor would introduce.

Putting It in the Pipeline

yaml
# .github/workflows/security.yml (excerpt) - run: npm ci --ignore-scripts - run: npm audit --audit-level=high - run: npx gitleaks git --no-banner - run: semgrep scan --config p/nodejs --config p/express --error - run: npm test # includes tests/security.test.js # after deploy to staging: - run: docker run --rm ghcr.io/zaproxy/zaproxy:stable zap-baseline.py -t ${{ vars.STAGING_URL }}

Triage each finding by reachability with untrusted input and by impact; fix at the root, suppress only with a comment explaining why, and review suppressions quarterly.

Quick Quiz
Question 1 of 2

What is the main difference between SAST and DAST?

Key Takeaways

  • Layer SAST, SCA, secret scanning, DAST, security unit tests and periodic manual review.
  • Run Semgrep with the Node.js and Express packs on every pull request; findings block merges.
  • Use the ZAP baseline scan against staging in CI; reserve active scans for authorized targets.
  • Encode every control as a test that asserts the failure case: 403, 401, 413, 429.
  • Triage by reachability and impact, fix at the root, and document every suppression.

Next lesson: Cloud Security Basics: IAM, Storage and Network — the settings that decide whether a cloud account is a fortress or a public folder.

Security Testing: SAST, DAST and OWASP ZAP Basics - Cyber Security | CodeYourCraft | CodeYourCraft