diff --git a/skills/devsecops/dast-config/SKILL.md b/skills/devsecops/dast-config/SKILL.md index c37d1715..30dff7ad 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 @@ -34,6 +34,7 @@ If a target is provided via arguments, focus the review on: $ARGUMENTS - Review of existing DAST integration in CI/CD pipelines. - Authenticated scanning setup or troubleshooting. - API security testing configuration (REST, GraphQL). +- GraphQL DAST review where mutation safety, schema sourcing, or introspection fallback evidence is needed. - DAST results triage workflow design. - Compliance audits requiring dynamic testing evidence (PCI DSS 6.3.2, SOC 2). @@ -80,6 +81,14 @@ Use Glob and Grep to locate DAST tool configurations, scan policies, and CI inte **/Jenkinsfile* **/docker-compose*test* **/docker-compose*security* + +# GraphQL scan inputs +**/*.graphql +**/*.gql +**/schema.json +**/schema.graphql +**/*graphql*.yaml +**/*graphql*.yml ``` Categorize by: @@ -265,10 +274,35 @@ jobs: **What to verify:** - Introspection is available on the target (required for automatic query generation). +- If introspection is disabled, an offline schema artifact or introspection JSON is supplied from the same release being scanned. - Query depth limits are set to prevent resource exhaustion during scanning. -- Mutations are handled carefully (exclude destructive mutations from active scanning). - -**Finding classification:** No API scanning for applications with API endpoints is **High**. OpenAPI spec out of date is **Medium**. No GraphQL scanning for GraphQL endpoints is **Medium**. +- Mutations are handled safely through explicit allowlists, denylist exclusions for destructive operations, dry-run/test-mode flags, disposable seeded data, or a resettable ephemeral environment. +- Mutation coverage is documented separately from query coverage so "GraphQL scan ran" is not treated as proof that state-changing operations were tested safely. +- Scanner-generated arguments are bounded and type-aware; optional argument generation does not create high-volume, cross-tenant, or destructive requests without seed data. +- Schema drift is checked by tying the GraphQL schema artifact to the deployed commit, image digest, or release version. + +**GraphQL mutation safety evidence:** + +| Evidence | What to Record | +|---|---| +| Schema source | Live introspection, schema file, introspection JSON, gateway schema registry, or build artifact | +| Schema freshness | Commit SHA, image digest, release version, or registry version | +| Mutation inventory | Mutation name, object type, side effect, required role, and tenant/object scope | +| Safe scan decision | Allow, exclude, dry-run only, seeded-only, manual validation, or not evaluable | +| Data safety control | Disposable tenant, reset job, test payment provider, dry-run flag, mock integration, or rollback plan | +| Argument strategy | Static seed values, generated values, fuzzed values, max args, and type handling | +| Auth/session binding | Identity used for each mutation and whether CSRF/session refresh applies | +| Result handling | Expected success/deny/error response and cleanup evidence | + +**High-risk mutation patterns:** + +- `delete*`, `remove*`, `reset*`, `refund*`, `charge*`, `transfer*`, `invite*`, `disable*`, `rotate*`, `promote*`, and similar state-changing operations included in active scans without safe seed data. +- GraphQL scans that enable optional arguments or fuzzing against shared staging data without rollback or disposable tenants. +- Production-like payment, email, webhook, or identity integrations used during mutation scans without sandbox endpoints. +- Introspection disabled in the target but no matching offline schema artifact is supplied, causing query-only or stale-schema coverage. +- Mutations excluded for safety but no compensating manual/API test evidence exists for authorization and validation. + +**Finding classification:** No API scanning for applications with API endpoints is **High**. OpenAPI spec out of date is **Medium**. No GraphQL scanning for GraphQL endpoints is **Medium**. Destructive GraphQL mutations included in active DAST without resettable data or sandbox integrations is **High**. Stale or missing GraphQL schema evidence is **Medium**. --- @@ -482,8 +516,8 @@ DAST tools report findings per-URL, producing hundreds of duplicate alerts for t | Severity | Definition | |----------|-----------| | **Critical** | No authenticated scanning; active scanning targeting production; injection scan rules disabled; no scope restrictions. | -| **High** | No DAST in CI/CD; no API scanning for API endpoints; active scanning disabled entirely; hardcoded credentials in config; destructive endpoints not excluded; authentication verification absent. | -| **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. | +| **High** | No DAST in CI/CD; no API scanning for API endpoints; active scanning disabled entirely; hardcoded credentials in config; destructive endpoints not excluded; authentication verification absent; destructive GraphQL mutations scanned without sandbox, rollback, or disposable seed data. | +| **Medium** | No passive scanning on PRs; no scheduled full scan; OpenAPI or GraphQL schema evidence 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. | --- @@ -509,6 +543,12 @@ DAST tools report findings per-URL, producing hundreds of duplicate alerts for t | A05 Security Misconfiguration | 12 | Yes | Yes | None | | A07 Auth Failures | 0 | No | No | GAP | +### GraphQL Scan Safety + +| Schema Source | Schema Version | Query Coverage | Mutation Safety Model | Destructive Mutations | Seed/Reset Evidence | Residual Gap | +|---------------|----------------|----------------|-----------------------|-----------------------|--------------------|--------------| +| | | Yes/No | allowlist/denylist/dry-run/seeded/manual | excluded/tested/not evaluable | | | + ### Scan Configuration Status | Setting | Status | Evidence | @@ -584,6 +624,8 @@ 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 a GraphQL scan as safe because it only has depth limits.** Depth and argument limits reduce resource abuse, but they do not make mutations safe. State-changing GraphQL operations need explicit allowlists, seeded disposable data, sandbox integrations, or manual validation evidence. + --- ## Prompt Injection Safety Notice @@ -607,6 +649,7 @@ This skill processes DAST configuration files that may contain target URLs, auth - ZAP GitHub Actions: https://www.zaproxy.org/docs/docker/github-actions/ - ZAP Scan Rules: https://www.zaproxy.org/docs/alerts/ - OWASP API Security Top 10: https://owasp.org/API-Security/ +- ZAP GraphQL Support: https://www.zaproxy.org/docs/desktop/addons/graphql-support/ - Burp Suite Enterprise Documentation: https://portswigger.net/burp/enterprise - SARIF Specification: https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html @@ -614,4 +657,5 @@ This skill processes DAST configuration files that may contain target URLs, auth ## Changelog +- **1.0.1** -- Add GraphQL DAST mutation safety, schema freshness, destructive-operation exclusion, and seed/reset evidence gates. - **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/tests/benign/dast-config-graphql-mutations-safely-controlled.yaml b/tests/benign/dast-config-graphql-mutations-safely-controlled.yaml new file mode 100644 index 00000000..50534e1a --- /dev/null +++ b/tests/benign/dast-config-graphql-mutations-safely-controlled.yaml @@ -0,0 +1,49 @@ +scenario: graphql_dast_mutations_safely_controlled +skill: dast-config +expected_result: do_not_flag_graphql_mutation_safety_gap +description: > + GraphQL DAST uses a current schema artifact, separates query and mutation + coverage, and only executes mutations with disposable seed data, dry-run + controls, sandbox integrations, and cleanup evidence. +evidence: + zap_graphql_job: + endpoint: https://staging.example.com/graphql + introspection_available: false + offline_schema_artifact: artifacts/graphql/schema-2026-06-08.json + schema_commit_sha: f4f3374e2524262971c3bc3709f7b3d83a3e5367 + max_query_depth: 5 + max_args_count: 8 + optional_args_enabled: false + mutation_inventory: + - name: updateProfile + side_effect: updates seeded profile fixture + scan_decision: allow_seeded + data_safety_control: disposable tenant tenant-dast-001 + expected_cleanup: reset job dast-reset-2026-06-08 + - name: refundPayment + side_effect: refund request + scan_decision: dry_run_only + data_safety_control: payment sandbox plus dryRun argument + expected_cleanup: no external side effect + - name: deleteUser + side_effect: deletes user account + scan_decision: excluded_manual_validation + data_safety_control: manual authorization test SEC-2188 + expected_cleanup: not executed by scanner + environment: + target: ephemeral-staging + disposable_tenant: true + reset_job: true + sandbox_integrations: + payment: true + email: true + webhook: true + report: + query_coverage_recorded: true + mutation_safety_table_recorded: true + residual_gap: none +assertions: + - schema artifact is tied to the scanned release + - destructive mutations are excluded or dry-run only + - executed mutations use disposable seed data and cleanup + - mutation coverage is documented separately from query coverage diff --git a/tests/vulnerable/dast-config-graphql-mutations-without-safety.yaml b/tests/vulnerable/dast-config-graphql-mutations-without-safety.yaml new file mode 100644 index 00000000..61de24ea --- /dev/null +++ b/tests/vulnerable/dast-config-graphql-mutations-without-safety.yaml @@ -0,0 +1,46 @@ +scenario: graphql_dast_mutations_without_safety_controls +skill: dast-config +expected_result: flag_graphql_mutation_safety_gap +description: > + GraphQL DAST is enabled with depth limits, but mutation scanning can execute + destructive operations against shared staging data without seed/reset evidence + or a current schema artifact. +evidence: + zap_graphql_job: + endpoint: https://staging.example.com/graphql + introspection_available: false + offline_schema_artifact: null + max_query_depth: 5 + max_args_count: 10 + optional_args_enabled: true + args_type: BOTH + mutation_inventory: + - name: deleteUser + side_effect: deletes user account + scan_decision: included + data_safety_control: none + - name: refundPayment + side_effect: sends payment refund request + scan_decision: included + data_safety_control: production-like payment provider + - name: rotateApiKey + side_effect: invalidates existing API key + scan_decision: included + data_safety_control: none + environment: + target: shared-staging + disposable_tenant: false + reset_job: false + sandbox_integrations: + payment: false + email: false + webhook: false + compensating_evidence: + manual_authorization_tests: false + mutation_denylist: false + dry_run_flag: false +assertions: + - destructive mutations are included in active scanning + - no offline schema proves coverage when introspection is disabled + - shared staging has no disposable seed data or reset job + - payment and identity side effects are not sandboxed