From 1ebc5775f09a28b06b69b0ab3d11453f00168939 Mon Sep 17 00:00:00 2001 From: DENGXUELIN <37065511+DENGXUELIN@users.noreply.github.com> Date: Tue, 9 Jun 2026 10:47:19 +0800 Subject: [PATCH] Add DAST auth session evidence fixtures --- skills/devsecops/dast-config/SKILL.md | 43 ++++++++++++- .../fresh-authenticated-scan-evidence.json | 63 +++++++++++++++++++ .../stale-cookie-csrf-coverage-unknown.json | 59 +++++++++++++++++ 3 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 skills/devsecops/dast-config/tests/benign/fresh-authenticated-scan-evidence.json create mode 100644 skills/devsecops/dast-config/tests/vulnerable/stale-cookie-csrf-coverage-unknown.json diff --git a/skills/devsecops/dast-config/SKILL.md b/skills/devsecops/dast-config/SKILL.md index c37d1715..51e811b3 100644 --- a/skills/devsecops/dast-config/SKILL.md +++ b/skills/devsecops/dast-config/SKILL.md @@ -12,7 +12,7 @@ phase: [build, deploy] frameworks: [OWASP-Top-10-2021, OWASP-Testing-Guide-v4.2] difficulty: intermediate time_estimate: "30-60min" -version: "1.0.0" +version: "1.0.1" author: unitoneai license: MIT allowed-tools: Read, Grep, Glob @@ -331,6 +331,25 @@ env: --- +#### 4.2 Authenticated Session Freshness and State Evidence + +Authentication configured at scan startup is not enough. Require phase-level evidence that the scanner remained authenticated during spider, Ajax spider, OpenAPI/GraphQL import, and active-scan phases, and that CSRF/state-changing routes were handled safely. + +| Gate | Evidence Required | Fail / Not Evaluable When | +|------|-------------------|---------------------------| +| `DAST-AUTH-EVID-01` Session source | Browser/script/API login or short-lived token minted by the pipeline, with no copied human browser cookie | Static cookie, copied bearer token, or manually pasted CSRF token is used | +| `DAST-AUTH-EVID-02` Phase freshness | Logged-in and logged-out checks during spider, Ajax spider, API import, and active scan; re-auth triggers recorded | Auth is checked only before the first request or session expiry is not measured | +| `DAST-AUTH-EVID-03` Authenticated coverage count | Authenticated URLs, anonymous URLs, excluded URLs, and auth-required URLs by scan phase | Report cannot separate authenticated coverage from public crawl coverage | +| `DAST-AUTH-EVID-04` CSRF / state token refresh | Token extraction/refresh evidence for form, SPA, and API state-changing requests | Active scan replays stale CSRF tokens, nonces, or anti-forgery headers | +| `DAST-AUTH-EVID-05` Logout / destructive route controls | Explicit exclusions or disposable seeded data for logout, lockout, account deletion, password reset, billing, admin, and destructive endpoints | Spider can log itself out or mutate shared staging data | +| `DAST-AUTH-EVID-06` Role / tenant isolation | Role, tenant, seeded user, and fixture cleanup evidence for every authenticated context | Admin-only or single-tenant scan is claimed as broad authenticated coverage | +| `DAST-AUTH-EVID-07` WAF / rate-limit constraints | Blocked request count, throttling evidence, retry policy, and WAF allowlist or scan window | Missing findings are treated as clean while the scanner was blocked or throttled | +| `DAST-AUTH-EVID-08` State reset / cleanup | Snapshot restore, fixture cleanup, tenant reset, or disposable environment evidence after active scan | Active scanning can leave persistent test data or broken workflows | + +Classify authenticated DAST evidence as **Fresh Authenticated**, **Stale Session**, **CSRF Unsafe**, **Coverage Unknown**, **State Unsafe**, or **Not Evaluable**. A clean report with missing `DAST-AUTH-EVID-*` evidence is not proof that authenticated attack surface was tested. + +--- + ### Step 5: CI/CD DAST Integration #### 5.1 Pipeline Integration Patterns @@ -486,6 +505,12 @@ DAST tools report findings per-URL, producing hundreds of duplicate alerts for t | **Medium** | No passive scanning on PRs; no scheduled full scan; OpenAPI spec out of date; no triage workflow; no deduplication; ZAP action unpinned; missing GraphQL scanning; missing security header rules. | | **Low** | Suboptimal scan duration settings; cosmetic report formatting; non-critical passive rules disabled. | +**Authenticated-session evidence classification:** + +- **High:** Static copied session/CSRF token, stale session during active scan, destructive route reachable, or authenticated coverage count unknown. +- **Medium:** Session is fresh but role/tenant coverage, WAF evidence, or state reset evidence is incomplete. +- **Low:** Auth evidence is complete but scan cadence, reporting, or cleanup documentation needs improvement. + --- ## Output Format @@ -520,6 +545,17 @@ DAST tools report findings per-URL, producing hundreds of duplicate alerts for t | API scanning | Yes/No | | | Results deduplication | Yes/No | | +### Authenticated Session Evidence +| Evidence Area | Status | Spider | Ajax / API | Active Scan | Limitations | +|---------------|--------|--------|------------|-------------|-------------| +| Session Source | Pass / Fail / Not Evaluable | | | | | +| Session Freshness | Pass / Fail / Not Evaluable | | | | | +| Authenticated Coverage Count | Pass / Fail / Not Evaluable | | | | | +| CSRF / State Token Refresh | Pass / Fail / Not Evaluable | | | | | +| Logout / Destructive Controls | Pass / Fail / Not Evaluable | | | | | +| WAF / Rate-limit Constraints | Pass / Fail / Not Evaluable | | | | | +| State Reset / Cleanup | Pass / Fail / Not Evaluable | | | | | + ### Findings #### [F-001] @@ -584,6 +620,10 @@ DAST tools report findings per-URL, producing hundreds of duplicate alerts for t 5. **Running only scheduled weekly scans instead of integrating into CI.** Weekly scans create a feedback loop measured in days. Passive baseline scans in CI (on every PR) give developers immediate feedback on security header regressions and configuration issues, while weekly full scans provide comprehensive active testing coverage. +6. **Treating authentication configured as authenticated coverage.** Static cookies, copied bearer tokens, and one-time login checks can expire before active scanning. Require phase-level freshness and authenticated URL counts. + +7. **Ignoring CSRF and scan state cleanup.** Active scans can fail CSRF-protected requests or mutate seeded data. Require token refresh evidence, destructive-route exclusions, and reset/cleanup proof. + --- ## Prompt Injection Safety Notice @@ -614,4 +654,5 @@ This skill processes DAST configuration files that may contain target URLs, auth ## Changelog +- **1.0.1** -- Added authenticated session freshness and state evidence gates, authenticated coverage output, CSRF refresh checks, WAF/rate-limit evidence, and state reset requirements. - **1.0.0** -- Initial release. Full coverage of DAST configuration review against OWASP Top 10:2021 and OWASP Testing Guide v4.2, with ZAP-specific patterns. diff --git a/skills/devsecops/dast-config/tests/benign/fresh-authenticated-scan-evidence.json b/skills/devsecops/dast-config/tests/benign/fresh-authenticated-scan-evidence.json new file mode 100644 index 00000000..61d217d6 --- /dev/null +++ b/skills/devsecops/dast-config/tests/benign/fresh-authenticated-scan-evidence.json @@ -0,0 +1,63 @@ +{ + "fixture": "fresh-authenticated-scan-evidence", + "expected_skill_decision": { + "decision": "Fresh Authenticated", + "risk_level": "low", + "reason": "The scan minted short-lived credentials in CI, verified authenticated state in each phase, refreshed CSRF tokens, excluded destructive routes, measured coverage, and reset seeded test state." + }, + "dast_auth_evidence": { + "tool": "zap-automation-framework", + "environment": "ephemeral-staging", + "session_source": "pipeline_login_script", + "credential_source": "ci_secret_reference", + "human_cookie_reused": false + }, + "phase_freshness": { + "spider": { + "logged_in_checks": 12, + "logged_out_checks": 12, + "reauth_triggers": 1, + "authenticated_urls": 184, + "anonymous_urls": 17 + }, + "ajax_spider": { + "logged_in_checks": 9, + "logged_out_checks": 9, + "reauth_triggers": 0, + "authenticated_urls": 92, + "anonymous_urls": 11 + }, + "active_scan": { + "logged_in_checks": 18, + "logged_out_checks": 18, + "reauth_triggers": 2, + "authenticated_urls": 143, + "anonymous_urls": 0 + } + }, + "csrf_state_controls": { + "csrf_refresh_enabled": true, + "nonce_refresh_enabled": true, + "destructive_routes_excluded": [ + "/logout", + "/account/delete", + "/billing/cancel" + ], + "seeded_tenant": "dast-tenant-2026-06-08", + "state_reset_evidence": "snapshot-restored" + }, + "role_tenant_coverage": { + "roles_tested": [ + "standard-user", + "tenant-admin" + ], + "tenant_isolation_checked": true, + "fixture_cleanup_passed": true + }, + "waf_rate_limit": { + "blocked_requests": 0, + "throttled_requests": 3, + "retry_policy_configured": true, + "scan_window_approved": true + } +} diff --git a/skills/devsecops/dast-config/tests/vulnerable/stale-cookie-csrf-coverage-unknown.json b/skills/devsecops/dast-config/tests/vulnerable/stale-cookie-csrf-coverage-unknown.json new file mode 100644 index 00000000..bc55b111 --- /dev/null +++ b/skills/devsecops/dast-config/tests/vulnerable/stale-cookie-csrf-coverage-unknown.json @@ -0,0 +1,59 @@ +{ + "fixture": "stale-cookie-csrf-coverage-unknown", + "expected_skill_decision": { + "decision": "Coverage Unknown", + "risk_level": "high", + "reason": "The scan uses copied cookies and static CSRF tokens, checks login only once, cannot separate authenticated from anonymous coverage, and leaves destructive routes in scope." + }, + "dast_auth_evidence": { + "tool": "zap-automation-framework", + "environment": "shared-staging", + "session_source": "copied_browser_cookie", + "credential_source": "manual", + "human_cookie_reused": true + }, + "phase_freshness": { + "spider": { + "logged_in_checks": 1, + "logged_out_checks": 0, + "reauth_triggers": 0, + "authenticated_urls": null, + "anonymous_urls": null + }, + "ajax_spider": { + "logged_in_checks": 0, + "logged_out_checks": 0, + "reauth_triggers": 0, + "authenticated_urls": null, + "anonymous_urls": null + }, + "active_scan": { + "logged_in_checks": 0, + "logged_out_checks": 0, + "reauth_triggers": 0, + "authenticated_urls": null, + "anonymous_urls": null + } + }, + "csrf_state_controls": { + "csrf_refresh_enabled": false, + "nonce_refresh_enabled": false, + "static_token_reused": true, + "destructive_routes_excluded": [], + "seeded_tenant": null, + "state_reset_evidence": null + }, + "role_tenant_coverage": { + "roles_tested": [ + "admin" + ], + "tenant_isolation_checked": false, + "fixture_cleanup_passed": false + }, + "waf_rate_limit": { + "blocked_requests": 187, + "throttled_requests": 94, + "retry_policy_configured": false, + "scan_window_approved": false + } +}