PS Product SecurityKnowledge Base

๐Ÿงช Test Phase โ€” Fast Gates, Deep Tests, and What Still Belongs Out of Band

Intro: The test phase is where many teams either slow delivery to a crawl or fool themselves with green dashboards. Good DevSecOps testing separates fast gates that must happen often from deeper testing that should happen deliberately, and it makes that split explicit.

What this page covers

  • how to structure security testing without breaking delivery speed;
  • what still belongs inside CI and what should run out of band;
  • practical examples for baseline DAST, IaC checks, container scanning, and higher-confidence IAST-style testing;
  • older versus current testing patterns.

The operating model

A useful test strategy has three lanes:

Lane 1 โ€” developer-fast checks

Run on pull request or every merge:

  • secret scanning;
  • OpenAPI linting;
  • IaC scanning;
  • fast dependency or image scanning;
  • baseline web or API checks where startup is cheap.

Lane 2 โ€” acceptance and release checks

Run before promotion to production:

  • smoke tests for auth, routing, and deployment correctness;
  • targeted DAST on critical routes;
  • permission and config assertions;
  • artifact and provenance checks;
  • release evidence collection.

Lane 3 โ€” out-of-band depth

Run on cadence or for high-risk systems:

  • fuzzing;
  • manual penetration testing;
  • deeper DAST coverage;
  • red teaming or game-day scenarios;
  • specialist review for crypto, auth, multi-tenant boundaries, or business logic.

This split is one of the most valuable ideas reinforced by the books: not every useful security test belongs in a PR pipeline.

Older pattern versus current pattern

Older pattern Why it happened Better modern framing
One big โ€œsecurity testโ€ stage Easier to explain Multiple small stages with fail-fast ordering
Weekly or monthly DAST only Scanners were slow and security owned them Baseline DAST in CI plus deeper scheduled or pre-release scans
Manual pen test before every release Traditional release governance Targeted manual testing for high-risk changes, product milestones, or regulated surfaces
Treating IAST as exotic Narrow vendor adoption Use IAST selectively where apps are testable and teams need lower-noise signal
Testing only app code App team owned the release Test contracts, templates, images, permissions, and deployment behavior too

Practical pipeline principle

Put cheap, high-signal checks first. Push slow and expensive checks later, or off the critical path, unless the risk requires otherwise.

Practical snippet โ€” fast security checks in GitLab CI

stages:
  - lint
  - scan
  - test

openapi_lint:
  stage: lint
  image: node:22-alpine
  script:
    - npm install -g @redocly/cli
    - redocly lint openapi.yaml

checkov_iac:
  stage: scan
  image: bridgecrew/checkov:latest
  script:
    - checkov -d infra --quiet

trivy_image:
  stage: scan
  image: aquasec/trivy:latest
  script:
    - trivy image --exit-code 1 --severity HIGH,CRITICAL "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"

zap_baseline:
  stage: test
  image: ghcr.io/zaproxy/zaproxy:stable
  script:
    - zap-baseline.py -t https://review.example.internal -r zap-baseline.html
  artifacts:
    when: always
    paths:
      - zap-baseline.html

Practical snippet โ€” legacy Jenkins-style ZAP example

This style is still understandable and still works in some organizations, especially where Jenkins remains the control plane.

docker run --rm \
  --network host \
  ghcr.io/zaproxy/zaproxy:stable \
  zap-baseline.py -t http://127.0.0.1:8080 -r zap.html

Why it is โ€œlegacy but validโ€

  • good for internal pipelines and lab environments;
  • easy to reason about;
  • still useful for quick baseline checks.

Why many teams now prefer a different packaging model

  • GitLab and GitHub reusable workflows are easier to templatize across teams;
  • containerized jobs integrate better with artifact and report handling;
  • modern pipelines often already have built-in environments and policy stages.

Practical snippet โ€” targeted integration tests for security features

security_functional_tests:
  stage: test
  image: python:3.12-slim
  script:
    - pip install pytest requests
    - pytest tests/security/test_authz.py -q
    - pytest tests/security/test_tenant_isolation.py -q
    - pytest tests/security/test_export_limits.py -q

Use this for business-critical checks that scanners miss.

IAST guidance in plain English

IAST can be useful when:

  • the team has realistic test traffic;
  • scanner noise is too high;
  • the application stack is supported well enough;
  • the team wants runtime context without doing production blocking.

IAST is a good confirmation layer, not a magic replacement for code review or design review.

What still belongs out of band

These should usually not block every merge:

  • full-coverage DAST on a large application;
  • manual pentest;
  • fuzzing campaigns;
  • red-team exercises;
  • broad external audits.

Run them on cadence, before major launches, or when risk materially changes.

Practical checklist for the test phase

  • Are fast checks ordered so that cheap failures happen first?
  • Are auth, authz, tenant isolation, and admin workflows covered by focused tests?
  • Does the pipeline test deployed behavior, not only build output?
  • Are baseline DAST results triaged and tuned instead of ignored?
  • Are high-risk flows covered by at least one human-reviewed test path?

Common mistakes

  • running slow scans on every commit without tuning;
  • trusting a clean DAST run more than focused authorization tests;
  • never testing deployment correctness and secret/permission injection;
  • blocking developers on scanner noise that no one owns;
  • treating โ€œsecurity testingโ€ as a separate track from release readiness.

---Author attribution: Ivan Piskunov, 2026 - Educational and defensive-engineering use.