Security Testing
What it is
Section titled “What it is”Security testing finds ways the system can be abused before an attacker does. It is layered, and each layer sees a different class of flaw.
source ──► SAST ──►┐ deps ──► SCA ──►├──► CI gate ──► build ──► DAST / pen test git ──► secrets ►┘ (running app)
SAST: code you wrote SCA: code you imported DAST: behaviour when runningThe goal is not a clean scanner report — it is a threat model: who attacks this, what they gain, and which control stops them (OWASP Top 10 is a useful starting map).
When to use it / when to avoid it
Section titled “When to use it / when to avoid it”Use it for
- Every commit: SAST and secret scanning are cheap and catch mistakes early
- Every dependency change: SCA flags known CVEs in your supply chain
- Before release: DAST against a running staging environment
- Anything touching auth, payments, PII or file uploads: threat-model it explicitly
Avoid or reduce it when
- You treat a scanner as proof of safety — it only finds known patterns
- You run an expensive full DAST scan on every push instead of a fast subset
- You gate on raw finding counts without triaging real exploitability
- You scan a build artifact that is not what you actually ship
Frameworks & tools
Section titled “Frameworks & tools”| Tool | Ecosystem | Notes |
|---|---|---|
| Semgrep | Multi | Fast SAST, custom rules as YAML |
| CodeQL | Multi | Deep semantic analysis, free for OSS on GitHub |
| Snyk | Multi | SCA plus SAST and container scanning |
| Trivy | Containers / IaC / SCA | One binary, scans images, filesystems and config |
| OWASP ZAP | Web DAST | Open source, scriptable, CI-friendly |
| Burp Suite | Web DAST | Industry-standard proxy and scanner |
| Gitleaks | Secrets | Detects secrets in git history and code |
| Dependabot | GitHub | Automated dependency update PRs |
Quick setup
Section titled “Quick setup”# SAST with Semgrepdocker run --rm -v "$PWD:/src" returntocorp/semgrep \ semgrep scan --config=auto /src
# DAST with OWASP ZAP baseline scandocker run --rm -t ghcr.io/zaproxy/zaproxy:stable \ zap-baseline.py -t https://staging.example.com
# Secrets with Gitleaksdocker run --rm -v "$PWD:/repo" zricethezav/gitleaks:latest \ detect --source=/repo --verbosenpm install -D @typescript-eslint/eslint-plugin eslint-plugin-securitynpx snyk test # SCA for npm dependenciespip install bandit pip-audit semgrepbandit -r src/ # SASTpip-audit # SCA for PyPIgo install github.com/securego/gosec/v2/cmd/gosec@latestgosec ./...govulncheck ./... # SCA for Go modules<!-- Maven: OWASP Dependency-Check --><plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> <version>9.2.0</version> <executions><execution><goals><goal>check</goal></goals></execution></executions></plugin>dotnet add package Microsoft.CodeAnalysis.NetAnalyzersdotnet list package --vulnerable --include-transitiveExample
Section titled “Example”# .github/workflows/security.yml (excerpt)- name: Scan container image run: | trivy image --exit-code 1 --severity HIGH,CRITICAL ghcr.io/acme/api:ci- name: Secret scan run: gitleaks detect --redact --exit-code 1# semgrep rule: flag eval on user inputrules: - id: no-eval-on-input languages: [javascript] severity: ERROR message: Do not eval untrusted input. pattern: eval($X)# bandit-friendly: parameterised query, never string-built SQLcursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))// gosec G401: use SHA-256+ for hashing, not MD5import "crypto/sha256"
sum := sha256.Sum256([]byte(token))_ = sum// CodeQL-friendly: never build SQL by concatenationvar query = entityManager.createQuery( "SELECT u FROM User u WHERE u.id = :id", User.class);query.setParameter("id", userId);// Use parameterised commands instead of string concatenationusing var cmd = new SqlCommand("SELECT * FROM Users WHERE Id = @id", conn);cmd.Parameters.AddWithValue("@id", userId);Anti-patterns & best practices
Section titled “Anti-patterns & best practices”- Layer the scanners. SAST, SCA, secrets and DAST catch different things; no single tool is sufficient.
- Gate on severity, triage the rest. Fail the build on exploitable HIGH/CRITICAL, review the rest instead of ignoring everything or blocking on noise.
- Scan the artifact you ship. A clean source tree does not mean a clean container.
- Keep secrets out of git. Run a secret scanner in CI and rotate anything that leaks — history is forever.
- Automate dependency patching. Dependabot or Renovate beats quarterly panic updates.
- Threat-model, do not just scan. A scanner cannot reason about business logic flaws such as broken access control.
Self-assessment quiz
Section titled “Self-assessment quiz”Self-assessment quiz
Pick one answer per question, then press Check answers.