qa360 2.3.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +155 -262
- package/{cli/dist → dist}/commands/ai.js +1 -1
- package/{cli/dist → dist}/commands/coverage.js +1 -1
- package/{cli/dist → dist}/commands/crawl.js +2 -2
- package/{cli/dist → dist}/commands/doctor.js +2 -2
- package/{cli/dist → dist}/commands/explain.js +2 -2
- package/{cli/dist → dist}/commands/flakiness.js +1 -1
- package/{cli/dist → dist}/commands/generate.js +1 -1
- package/{cli/dist → dist}/commands/history.js +1 -1
- package/{cli/dist → dist}/commands/monitor.js +3 -3
- package/{cli/dist → dist}/commands/ollama.js +1 -1
- package/{cli/dist → dist}/commands/pack.js +2 -2
- package/{cli/dist → dist}/commands/regression.js +1 -1
- package/{cli/dist → dist}/commands/repair.js +1 -1
- package/{cli/dist → dist}/commands/retry.js +1 -1
- package/{cli/dist → dist}/commands/run.d.ts +1 -1
- package/{cli/dist → dist}/commands/run.js +1 -1
- package/{cli/dist → dist}/commands/secrets.js +1 -1
- package/{cli/dist → dist}/commands/serve.js +1 -1
- package/{cli/dist → dist}/commands/slo.js +1 -1
- package/{cli/dist → dist}/commands/verify.js +1 -1
- package/{cli/dist → dist}/core/adapters/playwright-native-api.d.ts +2 -0
- package/{cli/dist → dist}/core/adapters/playwright-native-api.js +20 -1
- package/{cli/dist → dist}/core/adapters/playwright-ui.d.ts +21 -0
- package/dist/core/adapters/playwright-ui.js +2050 -0
- package/{cli/dist → dist}/core/ai/ollama-provider.js +15 -3
- package/{cli/dist → dist}/core/artifacts/ui-artifacts.js +24 -4
- package/dist/core/auth/backup-codes-provider.d.ts +91 -0
- package/dist/core/auth/backup-codes-provider.js +215 -0
- package/{cli/dist → dist}/core/auth/basic-auth-provider.d.ts +6 -0
- package/{cli/dist → dist}/core/auth/basic-auth-provider.js +24 -6
- package/dist/core/auth/digest-auth-provider.d.ts +116 -0
- package/dist/core/auth/digest-auth-provider.js +244 -0
- package/dist/core/auth/hcaptcha-handler.d.ts +103 -0
- package/dist/core/auth/hcaptcha-handler.js +288 -0
- package/{cli/dist → dist}/core/auth/index.d.ts +81 -4
- package/{cli/dist → dist}/core/auth/index.js +15 -1
- package/dist/core/auth/oauth-handler.d.ts +408 -0
- package/dist/core/auth/oauth-handler.js +636 -0
- package/{cli/dist → dist}/core/auth/oauth2-provider.d.ts +9 -0
- package/dist/core/auth/oauth2-provider.js +227 -0
- package/dist/core/auth/otp-provider.d.ts +93 -0
- package/dist/core/auth/otp-provider.js +288 -0
- package/dist/core/auth/recaptcha-handler.d.ts +119 -0
- package/dist/core/auth/recaptcha-handler.js +301 -0
- package/dist/core/auth/remember-me-handler.d.ts +142 -0
- package/dist/core/auth/remember-me-handler.js +255 -0
- package/dist/core/auth/saml-handler.d.ts +173 -0
- package/dist/core/auth/saml-handler.js +364 -0
- package/dist/core/auth/webauthn-handler.d.ts +182 -0
- package/dist/core/auth/webauthn-handler.js +310 -0
- package/dist/core/crawler/advanced-interactions.d.ts +342 -0
- package/dist/core/crawler/advanced-interactions.js +1069 -0
- package/dist/core/crawler/blob-url-download-handler.d.ts +145 -0
- package/dist/core/crawler/blob-url-download-handler.js +392 -0
- package/dist/core/crawler/consent-handler.d.ts +49 -0
- package/dist/core/crawler/consent-handler.js +258 -0
- package/dist/core/crawler/cookie-manager.d.ts +166 -0
- package/dist/core/crawler/cookie-manager.js +353 -0
- package/dist/core/crawler/coop-coep-handler.d.ts +136 -0
- package/dist/core/crawler/coop-coep-handler.js +338 -0
- package/dist/core/crawler/csp-handler.d.ts +151 -0
- package/dist/core/crawler/csp-handler.js +415 -0
- package/dist/core/crawler/download-handler.d.ts +155 -0
- package/dist/core/crawler/download-handler.js +370 -0
- package/dist/core/crawler/email-testing-handler.d.ts +214 -0
- package/dist/core/crawler/email-testing-handler.js +398 -0
- package/dist/core/crawler/error-tracking-handler.d.ts +177 -0
- package/dist/core/crawler/error-tracking-handler.js +378 -0
- package/dist/core/crawler/form-handler.d.ts +100 -0
- package/dist/core/crawler/form-handler.js +465 -0
- package/dist/core/crawler/framework-wait-handler.d.ts +96 -0
- package/dist/core/crawler/framework-wait-handler.js +464 -0
- package/dist/core/crawler/geolocation-handler.d.ts +112 -0
- package/dist/core/crawler/geolocation-handler.js +276 -0
- package/dist/core/crawler/index.d.ts +78 -0
- package/{cli/dist → dist}/core/crawler/index.js +74 -1
- package/dist/core/crawler/intelligent-selector-generator.d.ts +164 -0
- package/dist/core/crawler/intelligent-selector-generator.js +612 -0
- package/{cli/dist → dist}/core/crawler/journey-generator.js +44 -1
- package/{cli/dist → dist}/core/crawler/page-analyzer.d.ts +16 -1
- package/{cli/dist → dist}/core/crawler/page-analyzer.js +469 -17
- package/dist/core/crawler/permissions-handler.d.ts +112 -0
- package/dist/core/crawler/permissions-handler.js +236 -0
- package/dist/core/crawler/permissions-policy-handler.d.ts +113 -0
- package/dist/core/crawler/permissions-policy-handler.js +402 -0
- package/dist/core/crawler/presets.d.ts +100 -0
- package/dist/core/crawler/presets.js +887 -0
- package/dist/core/crawler/repl-debug-handler.d.ts +105 -0
- package/dist/core/crawler/repl-debug-handler.js +552 -0
- package/dist/core/crawler/reporting-api-handler.d.ts +212 -0
- package/dist/core/crawler/reporting-api-handler.js +344 -0
- package/{cli/dist → dist}/core/crawler/selector-generator.d.ts +9 -0
- package/{cli/dist → dist}/core/crawler/selector-generator.js +99 -23
- package/dist/core/crawler/site-profiler.d.ts +89 -0
- package/dist/core/crawler/site-profiler.js +290 -0
- package/dist/core/crawler/sourcemaps-handler.d.ts +144 -0
- package/dist/core/crawler/sourcemaps-handler.js +420 -0
- package/dist/core/crawler/stacked-modals-handler.d.ts +118 -0
- package/dist/core/crawler/stacked-modals-handler.js +429 -0
- package/dist/core/crawler/trusted-types-handler.d.ts +149 -0
- package/dist/core/crawler/trusted-types-handler.js +413 -0
- package/{cli/dist → dist}/core/crawler/types.d.ts +68 -2
- package/dist/core/crawler/wait-strategies.d.ts +108 -0
- package/dist/core/crawler/wait-strategies.js +399 -0
- package/dist/core/fixtures/factories.d.ts +180 -0
- package/dist/core/fixtures/factories.js +279 -0
- package/dist/core/fixtures/index.d.ts +6 -0
- package/dist/core/fixtures/index.js +6 -0
- package/{cli/dist → dist}/core/generation/crawler-pack-generator.d.ts +13 -3
- package/dist/core/generation/crawler-pack-generator.js +232 -0
- package/{cli/dist → dist}/core/generation/index.d.ts +2 -0
- package/{cli/dist → dist}/core/generation/index.js +2 -0
- package/{cli/dist → dist}/core/index.d.ts +2 -0
- package/{cli/dist → dist}/core/index.js +4 -0
- package/dist/core/network/index.d.ts +7 -0
- package/dist/core/network/index.js +7 -0
- package/dist/core/network/network-manager.d.ts +237 -0
- package/dist/core/network/network-manager.js +343 -0
- package/dist/core/network/network-simulator.d.ts +158 -0
- package/dist/core/network/network-simulator.js +261 -0
- package/{cli/dist → dist}/core/pack/validator.js +2 -2
- package/{cli/dist → dist}/core/pack-v2/migrator.d.ts +5 -0
- package/{cli/dist → dist}/core/pack-v2/migrator.js +81 -6
- package/{cli/dist → dist}/core/pack-v2/validator.js +4 -3
- package/{cli/dist → dist}/core/pom/base-page.js +1 -1
- package/{cli/dist → dist}/core/pom/loader.js +1 -1
- package/dist/core/reporting/index.d.ts +9 -0
- package/dist/core/reporting/index.js +10 -0
- package/dist/core/reporting/junit-reporter.d.ts +114 -0
- package/dist/core/reporting/junit-reporter.js +306 -0
- package/{cli/dist → dist}/core/runner/e2e-helpers.d.ts +1 -1
- package/{cli/dist → dist}/core/runner/e2e-helpers.js +2 -2
- package/{cli/dist → dist}/core/runner/phase3-runner.d.ts +3 -0
- package/{cli/dist → dist}/core/runner/phase3-runner.js +45 -14
- package/dist/core/sharding/test-sharding.d.ts +137 -0
- package/dist/core/sharding/test-sharding.js +233 -0
- package/dist/core/storage/cookie-manager.d.ts +160 -0
- package/dist/core/storage/cookie-manager.js +268 -0
- package/dist/core/storage/index.d.ts +7 -0
- package/dist/core/storage/index.js +7 -0
- package/dist/core/storage/storage-helpers.d.ts +138 -0
- package/dist/core/storage/storage-helpers.js +315 -0
- package/dist/core/test-helpers/index.d.ts +6 -0
- package/dist/core/test-helpers/index.js +6 -0
- package/dist/core/test-helpers/state-reset.d.ts +119 -0
- package/dist/core/test-helpers/state-reset.js +234 -0
- package/{cli/dist → dist}/core/types/pack-v1.d.ts +15 -2
- package/{cli/dist → dist}/core/types/pack-v2.d.ts +1 -1
- package/dist/core/upload/chunked-uploader.d.ts +150 -0
- package/dist/core/upload/chunked-uploader.js +289 -0
- package/dist/core/upload/index.d.ts +11 -0
- package/dist/core/upload/index.js +8 -0
- package/dist/core/upload/mime-validator.d.ts +119 -0
- package/dist/core/upload/mime-validator.js +373 -0
- package/dist/core/upload/presigned-uploader.d.ts +118 -0
- package/dist/core/upload/presigned-uploader.js +274 -0
- package/dist/core/utils/device-emulation.d.ts +194 -0
- package/dist/core/utils/device-emulation.js +380 -0
- package/dist/core/utils/index.d.ts +8 -0
- package/dist/core/utils/index.js +8 -0
- package/dist/core/utils/retry.d.ts +145 -0
- package/dist/core/utils/retry.js +242 -0
- package/dist/core/utils/smart-wait.d.ts +133 -0
- package/dist/core/utils/smart-wait.js +417 -0
- package/dist/core/visual/index.d.ts +7 -0
- package/dist/core/visual/index.js +7 -0
- package/dist/core/visual/pixel-diff.d.ts +87 -0
- package/dist/core/visual/pixel-diff.js +213 -0
- package/dist/core/visual/screenshot-helper.d.ts +130 -0
- package/dist/core/visual/screenshot-helper.js +223 -0
- package/{cli/dist → dist}/utils/config.d.ts +1 -1
- package/examples/README.md +160 -0
- package/examples/accessibility.yml +48 -0
- package/examples/api-basic.yml +27 -0
- package/examples/complete.yml +146 -0
- package/examples/crawler.yml +38 -0
- package/examples/fullstack.yml +78 -0
- package/examples/security.yml +58 -0
- package/examples/ui-advanced.yml +49 -0
- package/examples/ui-basic.yml +24 -0
- package/package.json +33 -67
- package/CHANGELOG.md +0 -330
- package/CONTRIBUTING.md +0 -273
- package/QUICK_START.md +0 -191
- package/cli/CHANGELOG.md +0 -84
- package/cli/LICENSE +0 -24
- package/cli/README.md +0 -222
- package/cli/dist/core/adapters/playwright-ui.js +0 -864
- package/cli/dist/core/auth/oauth2-provider.js +0 -114
- package/cli/dist/core/coverage/analyzer.d.ts +0 -101
- package/cli/dist/core/coverage/analyzer.js +0 -415
- package/cli/dist/core/coverage/collector.d.ts +0 -74
- package/cli/dist/core/coverage/collector.js +0 -459
- package/cli/dist/core/coverage/config.d.ts +0 -37
- package/cli/dist/core/coverage/config.js +0 -156
- package/cli/dist/core/coverage/index.d.ts +0 -11
- package/cli/dist/core/coverage/index.js +0 -15
- package/cli/dist/core/coverage/types.d.ts +0 -267
- package/cli/dist/core/coverage/types.js +0 -6
- package/cli/dist/core/coverage/vault.d.ts +0 -95
- package/cli/dist/core/coverage/vault.js +0 -405
- package/cli/dist/core/crawler/index.d.ts +0 -57
- package/cli/dist/core/fixtures/index.d.ts +0 -8
- package/cli/dist/core/fixtures/index.js +0 -8
- package/cli/dist/core/generation/crawler-pack-generator.js +0 -231
- package/cli/dist/core/reporting/index.d.ts +0 -6
- package/cli/dist/core/reporting/index.js +0 -6
- package/cli/dist/core/visual/index.d.ts +0 -6
- package/cli/dist/core/visual/index.js +0 -6
- package/cli/package.json +0 -76
- package/core/LICENSE +0 -24
- package/core/README.md +0 -105
- package/core/package.json +0 -90
- package/core/schemas/pack.schema.json +0 -236
- /package/{cli/bin → bin}/qa360.js +0 -0
- /package/{cli/dist → dist}/cli-minimal.d.ts +0 -0
- /package/{cli/dist → dist}/cli-minimal.js +0 -0
- /package/{cli/dist → dist}/commands/ai.d.ts +0 -0
- /package/{cli/dist → dist}/commands/ask.d.ts +0 -0
- /package/{cli/dist → dist}/commands/ask.js +0 -0
- /package/{cli/dist → dist}/commands/coverage.d.ts +0 -0
- /package/{cli/dist → dist}/commands/crawl.d.ts +0 -0
- /package/{cli/dist → dist}/commands/doctor.d.ts +0 -0
- /package/{cli/dist → dist}/commands/examples.d.ts +0 -0
- /package/{cli/dist → dist}/commands/examples.js +0 -0
- /package/{cli/dist → dist}/commands/explain.d.ts +0 -0
- /package/{cli/dist → dist}/commands/flakiness.d.ts +0 -0
- /package/{cli/dist → dist}/commands/generate.d.ts +0 -0
- /package/{cli/dist → dist}/commands/history.d.ts +0 -0
- /package/{cli/dist → dist}/commands/init.d.ts +0 -0
- /package/{cli/dist → dist}/commands/init.js +0 -0
- /package/{cli/dist → dist}/commands/monitor.d.ts +0 -0
- /package/{cli/dist → dist}/commands/ollama.d.ts +0 -0
- /package/{cli/dist → dist}/commands/pack.d.ts +0 -0
- /package/{cli/dist → dist}/commands/regression.d.ts +0 -0
- /package/{cli/dist → dist}/commands/repair.d.ts +0 -0
- /package/{cli/dist → dist}/commands/report.d.ts +0 -0
- /package/{cli/dist → dist}/commands/report.js +0 -0
- /package/{cli/dist → dist}/commands/retry.d.ts +0 -0
- /package/{cli/dist → dist}/commands/scan.d.ts +0 -0
- /package/{cli/dist → dist}/commands/scan.js +0 -0
- /package/{cli/dist → dist}/commands/secrets.d.ts +0 -0
- /package/{cli/dist → dist}/commands/serve.d.ts +0 -0
- /package/{cli/dist → dist}/commands/slo.d.ts +0 -0
- /package/{cli/dist → dist}/commands/verify.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/gitleaks-secrets.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/gitleaks-secrets.js +0 -0
- /package/{cli/dist → dist}/core/adapters/jest-adapter.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/jest-adapter.js +0 -0
- /package/{cli/dist → dist}/core/adapters/k6-perf.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/k6-perf.js +0 -0
- /package/{cli/dist → dist}/core/adapters/osv-deps.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/osv-deps.js +0 -0
- /package/{cli/dist → dist}/core/adapters/playwright-native-adapter.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/playwright-native-adapter.js +0 -0
- /package/{cli/dist → dist}/core/adapters/pytest-adapter.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/pytest-adapter.js +0 -0
- /package/{cli/dist → dist}/core/adapters/semgrep-sast.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/semgrep-sast.js +0 -0
- /package/{cli/dist → dist}/core/adapters/unit-test-types.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/unit-test-types.js +0 -0
- /package/{cli/dist → dist}/core/adapters/vitest-adapter.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/vitest-adapter.js +0 -0
- /package/{cli/dist → dist}/core/adapters/zap-dast.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/zap-dast.js +0 -0
- /package/{cli/dist → dist}/core/ai/anthropic-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/anthropic-provider.js +0 -0
- /package/{cli/dist → dist}/core/ai/deepseek-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/deepseek-provider.js +0 -0
- /package/{cli/dist → dist}/core/ai/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/index.js +0 -0
- /package/{cli/dist → dist}/core/ai/llm-client.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/llm-client.js +0 -0
- /package/{cli/dist → dist}/core/ai/mock-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/mock-provider.js +0 -0
- /package/{cli/dist → dist}/core/ai/ollama-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/openai-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/openai-provider.js +0 -0
- /package/{cli/dist → dist}/core/ai/provider-factory.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/provider-factory.js +0 -0
- /package/{cli/dist → dist}/core/artifacts/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/artifacts/index.js +0 -0
- /package/{cli/dist → dist}/core/artifacts/ui-artifacts.d.ts +0 -0
- /package/{cli/dist → dist}/core/assertions/engine.d.ts +0 -0
- /package/{cli/dist → dist}/core/assertions/engine.js +0 -0
- /package/{cli/dist → dist}/core/assertions/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/assertions/index.js +0 -0
- /package/{cli/dist → dist}/core/assertions/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/assertions/types.js +0 -0
- /package/{cli/dist → dist}/core/auth/api-key-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/api-key-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/aws-iam-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/aws-iam-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/azure-ad-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/azure-ad-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/gcp-adc-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/gcp-adc-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/jwt-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/jwt-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/manager.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/manager.js +0 -0
- /package/{cli/dist → dist}/core/auth/totp-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/totp-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/ui-login-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/ui-login-provider.js +0 -0
- /package/{cli/dist → dist}/core/cache/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/cache/index.js +0 -0
- /package/{cli/dist → dist}/core/cache/lru-cache.d.ts +0 -0
- /package/{cli/dist → dist}/core/cache/lru-cache.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/analyzer.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/analyzer.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/collector.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/collector.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/config.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/config.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/index.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/index.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/types.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/types.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/vault.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/vault.js +0 -0
- /package/{cli/dist → dist}/core/crawler/journey-generator.d.ts +0 -0
- /package/{cli/dist → dist}/core/crawler/types.js +0 -0
- /package/{cli/dist → dist}/core/dashboard/assets.d.ts +0 -0
- /package/{cli/dist → dist}/core/dashboard/assets.js +0 -0
- /package/{cli/dist → dist}/core/dashboard/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/dashboard/index.js +0 -0
- /package/{cli/dist → dist}/core/dashboard/server.d.ts +0 -0
- /package/{cli/dist → dist}/core/dashboard/server.js +0 -0
- /package/{cli/dist → dist}/core/dashboard/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/dashboard/types.js +0 -0
- /package/{cli/dist → dist}/core/discoverer/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/discoverer/index.js +0 -0
- /package/{cli/dist → dist}/core/fixtures/loader.d.ts +0 -0
- /package/{cli/dist → dist}/core/fixtures/loader.js +0 -0
- /package/{cli/dist → dist}/core/fixtures/resolver.d.ts +0 -0
- /package/{cli/dist → dist}/core/fixtures/resolver.js +0 -0
- /package/{cli/dist → dist}/core/fixtures/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/fixtures/types.js +0 -0
- /package/{cli/dist → dist}/core/flakiness/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/flakiness/index.js +0 -0
- /package/{cli/dist → dist}/core/generation/code-formatter.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/code-formatter.js +0 -0
- /package/{cli/dist → dist}/core/generation/code-generator.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/code-generator.js +0 -0
- /package/{cli/dist → dist}/core/generation/generator.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/generator.js +0 -0
- /package/{cli/dist → dist}/core/generation/pack-generator.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/pack-generator.js +0 -0
- /package/{cli/dist → dist}/core/generation/prompt-builder.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/prompt-builder.js +0 -0
- /package/{cli/dist → dist}/core/generation/source-analyzer.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/source-analyzer.js +0 -0
- /package/{cli/dist → dist}/core/generation/test-optimizer.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/test-optimizer.js +0 -0
- /package/{cli/dist → dist}/core/generation/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/types.js +0 -0
- /package/{cli/dist → dist}/core/hooks/compose.d.ts +0 -0
- /package/{cli/dist → dist}/core/hooks/compose.js +0 -0
- /package/{cli/dist → dist}/core/hooks/runner.d.ts +0 -0
- /package/{cli/dist → dist}/core/hooks/runner.js +0 -0
- /package/{cli/dist → dist}/core/pack/migrator.d.ts +0 -0
- /package/{cli/dist → dist}/core/pack/migrator.js +0 -0
- /package/{cli/dist → dist}/core/pack/validator.d.ts +0 -0
- /package/{cli/dist → dist}/core/pack-v2/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/pack-v2/index.js +0 -0
- /package/{cli/dist → dist}/core/pack-v2/loader.d.ts +0 -0
- /package/{cli/dist → dist}/core/pack-v2/loader.js +0 -0
- /package/{cli/dist → dist}/core/pack-v2/validator.d.ts +0 -0
- /package/{cli/dist → dist}/core/parallel/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/parallel/index.js +0 -0
- /package/{cli/dist → dist}/core/parallel/parallel-runner.d.ts +0 -0
- /package/{cli/dist → dist}/core/parallel/parallel-runner.js +0 -0
- /package/{cli/dist → dist}/core/pom/base-page.d.ts +0 -0
- /package/{cli/dist → dist}/core/pom/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/pom/index.js +0 -0
- /package/{cli/dist → dist}/core/pom/loader.d.ts +0 -0
- /package/{cli/dist → dist}/core/pom/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/pom/types.js +0 -0
- /package/{cli/dist → dist}/core/proof/bundle.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/bundle.js +0 -0
- /package/{cli/dist → dist}/core/proof/canonicalize.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/canonicalize.js +0 -0
- /package/{cli/dist → dist}/core/proof/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/index.js +0 -0
- /package/{cli/dist → dist}/core/proof/schema.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/schema.js +0 -0
- /package/{cli/dist → dist}/core/proof/signer.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/signer.js +0 -0
- /package/{cli/dist → dist}/core/proof/verifier.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/verifier.js +0 -0
- /package/{cli/dist → dist}/core/regression/detector.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/detector.js +0 -0
- /package/{cli/dist → dist}/core/regression/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/index.js +0 -0
- /package/{cli/dist → dist}/core/regression/trend-analyzer.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/trend-analyzer.js +0 -0
- /package/{cli/dist → dist}/core/regression/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/types.js +0 -0
- /package/{cli/dist → dist}/core/regression/vault.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/vault.js +0 -0
- /package/{cli/dist → dist}/core/repair/engine/fixer.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/engine/fixer.js +0 -0
- /package/{cli/dist → dist}/core/repair/engine/suggestion-engine.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/engine/suggestion-engine.js +0 -0
- /package/{cli/dist → dist}/core/repair/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/index.js +0 -0
- /package/{cli/dist → dist}/core/repair/repairer.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/repairer.js +0 -0
- /package/{cli/dist → dist}/core/repair/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/types.js +0 -0
- /package/{cli/dist → dist}/core/repair/utils/error-analyzer.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/utils/error-analyzer.js +0 -0
- /package/{cli/dist → dist}/core/reporting/html-reporter.d.ts +0 -0
- /package/{cli/dist → dist}/core/reporting/html-reporter.js +0 -0
- /package/{cli/dist → dist}/core/retry/flakiness-integration.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/flakiness-integration.js +0 -0
- /package/{cli/dist → dist}/core/retry/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/index.js +0 -0
- /package/{cli/dist → dist}/core/retry/retry-engine.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/retry-engine.js +0 -0
- /package/{cli/dist → dist}/core/retry/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/types.js +0 -0
- /package/{cli/dist → dist}/core/retry/vault.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/vault.js +0 -0
- /package/{cli/dist → dist}/core/schemas/pack.schema.json +0 -0
- /package/{cli/dist → dist}/core/secrets/crypto.d.ts +0 -0
- /package/{cli/dist → dist}/core/secrets/crypto.js +0 -0
- /package/{cli/dist → dist}/core/secrets/manager.d.ts +0 -0
- /package/{cli/dist → dist}/core/secrets/manager.js +0 -0
- /package/{cli/dist → dist}/core/security/redaction-patterns-extended.d.ts +0 -0
- /package/{cli/dist → dist}/core/security/redaction-patterns-extended.js +0 -0
- /package/{cli/dist → dist}/core/security/redactor.d.ts +0 -0
- /package/{cli/dist → dist}/core/security/redactor.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/assertion-healer.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/assertion-healer.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/engine.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/engine.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/index.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/selector-healer.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/selector-healer.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/types.js +0 -0
- /package/{cli/dist → dist}/core/serve/diagnostics-collector.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/diagnostics-collector.js +0 -0
- /package/{cli/dist → dist}/core/serve/health-checker.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/health-checker.js +0 -0
- /package/{cli/dist → dist}/core/serve/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/index.js +0 -0
- /package/{cli/dist → dist}/core/serve/metrics-collector.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/metrics-collector.js +0 -0
- /package/{cli/dist → dist}/core/serve/process-manager.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/process-manager.js +0 -0
- /package/{cli/dist → dist}/core/serve/server.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/server.js +0 -0
- /package/{cli/dist → dist}/core/slo/config.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/config.js +0 -0
- /package/{cli/dist → dist}/core/slo/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/index.js +0 -0
- /package/{cli/dist → dist}/core/slo/sli-calculator.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/sli-calculator.js +0 -0
- /package/{cli/dist → dist}/core/slo/slo-tracker.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/slo-tracker.js +0 -0
- /package/{cli/dist → dist}/core/slo/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/types.js +0 -0
- /package/{cli/dist → dist}/core/slo/vault.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/vault.js +0 -0
- /package/{cli/dist → dist}/core/tui/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/tui/index.js +0 -0
- /package/{cli/dist → dist}/core/tui/monitor.d.ts +0 -0
- /package/{cli/dist → dist}/core/tui/monitor.js +0 -0
- /package/{cli/dist → dist}/core/tui/renderer.d.ts +0 -0
- /package/{cli/dist → dist}/core/tui/renderer.js +0 -0
- /package/{cli/dist → dist}/core/tui/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/tui/types.js +0 -0
- /package/{cli/dist → dist}/core/types/pack-v1.js +0 -0
- /package/{cli/dist → dist}/core/types/pack-v2.js +0 -0
- /package/{cli/dist → dist}/core/types/trust-score.d.ts +0 -0
- /package/{cli/dist → dist}/core/types/trust-score.js +0 -0
- /package/{cli/dist → dist}/core/vault/cas.d.ts +0 -0
- /package/{cli/dist → dist}/core/vault/cas.js +0 -0
- /package/{cli/dist → dist}/core/vault/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/vault/index.js +0 -0
- /package/{cli/dist → dist}/core/visual/visual-regression.d.ts +0 -0
- /package/{cli/dist → dist}/core/visual/visual-regression.js +0 -0
- /package/{cli/dist → dist}/core/watch/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/watch/index.js +0 -0
- /package/{cli/dist → dist}/core/watch/watch-mode.d.ts +0 -0
- /package/{cli/dist → dist}/core/watch/watch-mode.js +0 -0
- /package/{cli/dist → dist}/generators/index.d.ts +0 -0
- /package/{cli/dist → dist}/generators/index.js +0 -0
- /package/{cli/dist → dist}/generators/json-reporter.d.ts +0 -0
- /package/{cli/dist → dist}/generators/json-reporter.js +0 -0
- /package/{cli/dist → dist}/generators/test-generator.d.ts +0 -0
- /package/{cli/dist → dist}/generators/test-generator.js +0 -0
- /package/{cli/dist → dist}/index.d.ts +0 -0
- /package/{cli/dist → dist}/index.js +0 -0
- /package/{cli/dist → dist}/scanners/dom-scanner.d.ts +0 -0
- /package/{cli/dist → dist}/scanners/dom-scanner.js +0 -0
- /package/{cli/dist → dist}/scanners/index.d.ts +0 -0
- /package/{cli/dist → dist}/scanners/index.js +0 -0
- /package/{cli/dist → dist}/schemas/pack.schema.json +0 -0
- /package/{cli/dist → dist}/types/scan.d.ts +0 -0
- /package/{cli/dist → dist}/types/scan.js +0 -0
- /package/{cli/dist → dist}/utils/config.js +0 -0
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSP Handler
|
|
3
|
+
*
|
|
4
|
+
* P1 - Content Security Policy management
|
|
5
|
+
*
|
|
6
|
+
* Supports:
|
|
7
|
+
* - CSP header parsing and validation
|
|
8
|
+
* - CSP directive analysis
|
|
9
|
+
* - CSP violation detection
|
|
10
|
+
* - CSP report-only mode
|
|
11
|
+
* - CSP nonce and hash validation
|
|
12
|
+
*
|
|
13
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* CSP Handler class
|
|
17
|
+
*/
|
|
18
|
+
export class CSPHandler {
|
|
19
|
+
page;
|
|
20
|
+
violations = [];
|
|
21
|
+
constructor(page) {
|
|
22
|
+
this.page = page;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get CSP header from response
|
|
26
|
+
*/
|
|
27
|
+
async getCSPHeader() {
|
|
28
|
+
const response = await this.page.evaluate(() => {
|
|
29
|
+
const metaTags = document.querySelectorAll('meta[http-equiv="Content-Security-Policy"]');
|
|
30
|
+
if (metaTags.length > 0) {
|
|
31
|
+
return metaTags[0].getAttribute('content');
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
});
|
|
35
|
+
if (response)
|
|
36
|
+
return response;
|
|
37
|
+
// Check via cdp (for actual headers)
|
|
38
|
+
try {
|
|
39
|
+
const cdp = this.page.context()?.cdp;
|
|
40
|
+
if (cdp) {
|
|
41
|
+
const headers = await this.page.evaluate(() => {
|
|
42
|
+
// Try to get from fetch
|
|
43
|
+
return fetch(window.location.href)
|
|
44
|
+
.then(r => {
|
|
45
|
+
const csp = r.headers.get('Content-Security-Policy');
|
|
46
|
+
const cspReportOnly = r.headers.get('Content-Security-Policy-Report-Only');
|
|
47
|
+
return csp || cspReportOnly || null;
|
|
48
|
+
})
|
|
49
|
+
.catch(() => null);
|
|
50
|
+
});
|
|
51
|
+
return headers;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// Ignore
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Parse CSP header value
|
|
61
|
+
*/
|
|
62
|
+
parseCSP(cspValue, reportOnly = false) {
|
|
63
|
+
const directives = new Map();
|
|
64
|
+
const parts = cspValue.split(';').map(s => s.trim()).filter(Boolean);
|
|
65
|
+
let reportEndpoint;
|
|
66
|
+
let reportUri;
|
|
67
|
+
for (const part of parts) {
|
|
68
|
+
const spaceIndex = part.indexOf(' ');
|
|
69
|
+
if (spaceIndex === -1)
|
|
70
|
+
continue;
|
|
71
|
+
const name = part.slice(0, spaceIndex).trim();
|
|
72
|
+
const valueStr = part.slice(spaceIndex + 1).trim();
|
|
73
|
+
const values = valueStr.split(/\s+/);
|
|
74
|
+
if (name === 'report-to' || name === 'report-uri') {
|
|
75
|
+
if (name === 'report-to')
|
|
76
|
+
reportEndpoint = valueStr;
|
|
77
|
+
if (name === 'report-uri')
|
|
78
|
+
reportUri = valueStr;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const directive = {
|
|
82
|
+
name,
|
|
83
|
+
values,
|
|
84
|
+
allowsUnsafeInline: values.includes("'unsafe-inline'"),
|
|
85
|
+
allowsUnsafeEval: values.includes("'unsafe-eval'"),
|
|
86
|
+
allowsSelf: values.includes("'self'"),
|
|
87
|
+
allowsWildcard: values.includes('*'),
|
|
88
|
+
hashes: values.filter(v => v.startsWith("'sha256-") || v.startsWith("'sha384-") || v.startsWith("'sha512-")),
|
|
89
|
+
};
|
|
90
|
+
// Extract nonce
|
|
91
|
+
const nonceValue = values.find(v => v.startsWith("'nonce-"));
|
|
92
|
+
if (nonceValue) {
|
|
93
|
+
directive.nonce = nonceValue.slice(7, -1);
|
|
94
|
+
}
|
|
95
|
+
directives.set(name, directive);
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
raw: cspValue,
|
|
99
|
+
directives,
|
|
100
|
+
reportOnly,
|
|
101
|
+
reportEndpoint,
|
|
102
|
+
reportUri,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get CSP policy from page
|
|
107
|
+
*/
|
|
108
|
+
async getCSPPolicy() {
|
|
109
|
+
const cspHeader = await this.getCSPHeader();
|
|
110
|
+
if (!cspHeader)
|
|
111
|
+
return null;
|
|
112
|
+
// Check if it's report-only
|
|
113
|
+
const isReportOnly = cspHeader.includes('report-only') ||
|
|
114
|
+
await this.page.evaluate(() => {
|
|
115
|
+
const meta = document.querySelector('meta[http-equiv="Content-Security-Policy-Report-Only"]');
|
|
116
|
+
return meta !== null;
|
|
117
|
+
});
|
|
118
|
+
return this.parseCSP(cspHeader, isReportOnly);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Validate CSP policy
|
|
122
|
+
*/
|
|
123
|
+
async validateCSP() {
|
|
124
|
+
const policy = await this.getCSPPolicy();
|
|
125
|
+
const issues = [];
|
|
126
|
+
const warnings = [];
|
|
127
|
+
const recommendations = [];
|
|
128
|
+
let score = 100;
|
|
129
|
+
if (!policy) {
|
|
130
|
+
return {
|
|
131
|
+
hasCSP: false,
|
|
132
|
+
securityScore: 0,
|
|
133
|
+
issues: ['No Content-Security-Policy header found'],
|
|
134
|
+
warnings: [],
|
|
135
|
+
recommendations: [
|
|
136
|
+
'Implement a Content-Security-Policy header',
|
|
137
|
+
'Start with report-only mode to test',
|
|
138
|
+
],
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
// Check if report-only mode (good for testing, but not for production)
|
|
142
|
+
if (policy.reportOnly) {
|
|
143
|
+
warnings.push('CSP is in report-only mode (not enforcing)');
|
|
144
|
+
score -= 10;
|
|
145
|
+
}
|
|
146
|
+
// Check for unsafe-inline
|
|
147
|
+
for (const [name, directive] of policy.directives) {
|
|
148
|
+
if (directive.allowsUnsafeInline) {
|
|
149
|
+
if (name === 'script-src') {
|
|
150
|
+
issues.push(`script-src allows 'unsafe-inline' (XSS risk)`);
|
|
151
|
+
score -= 30;
|
|
152
|
+
}
|
|
153
|
+
else if (name === 'style-src') {
|
|
154
|
+
warnings.push(`style-src allows 'unsafe-inline' (consider using nonces)`);
|
|
155
|
+
score -= 10;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (directive.allowsUnsafeEval) {
|
|
159
|
+
issues.push(`${name} allows 'unsafe-eval' (security risk)`);
|
|
160
|
+
score -= 20;
|
|
161
|
+
}
|
|
162
|
+
if (directive.allowsWildcard && name !== 'img-src' && name !== 'media-src') {
|
|
163
|
+
warnings.push(`${name} allows wildcard (*) (consider tightening)`);
|
|
164
|
+
score -= 10;
|
|
165
|
+
}
|
|
166
|
+
if (!directive.allowsSelf && !directive.allowsWildcard && directive.values.length === 0) {
|
|
167
|
+
warnings.push(`${name} has no sources defined`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// Check for default-src
|
|
171
|
+
if (!policy.directives.has('default-src')) {
|
|
172
|
+
recommendations.push('Add default-src directive for fallback protection');
|
|
173
|
+
score -= 15;
|
|
174
|
+
}
|
|
175
|
+
// Check for script-src
|
|
176
|
+
if (!policy.directives.has('script-src')) {
|
|
177
|
+
recommendations.push('Add explicit script-src directive');
|
|
178
|
+
score -= 10;
|
|
179
|
+
}
|
|
180
|
+
// Check for object-src (prevents plugins)
|
|
181
|
+
if (!policy.directives.has('object-src') && !policy.directives.has('default-src')) {
|
|
182
|
+
recommendations.push('Add object-src \'none\' to prevent plugin execution');
|
|
183
|
+
score -= 5;
|
|
184
|
+
}
|
|
185
|
+
// Check for base-uri
|
|
186
|
+
if (!policy.directives.has('base-uri')) {
|
|
187
|
+
recommendations.push('Add base-uri directive to prevent base tag injection');
|
|
188
|
+
}
|
|
189
|
+
// Check for form-action
|
|
190
|
+
if (!policy.directives.has('form-action')) {
|
|
191
|
+
recommendations.push('Add form-action directive to restrict form submissions');
|
|
192
|
+
}
|
|
193
|
+
// Check for frame-ancestors (clickjacking protection)
|
|
194
|
+
if (!policy.directives.has('frame-ancestors')) {
|
|
195
|
+
recommendations.push('Add frame-ancestors directive to prevent clickjacking');
|
|
196
|
+
score -= 5;
|
|
197
|
+
}
|
|
198
|
+
// Check for upgrade-insecure-requests
|
|
199
|
+
if (!policy.directives.has('upgrade-insecure-requests')) {
|
|
200
|
+
recommendations.push('Consider upgrade-insecure-requests for HTTPS migration');
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
hasCSP: true,
|
|
204
|
+
policy,
|
|
205
|
+
securityScore: Math.max(0, score),
|
|
206
|
+
issues,
|
|
207
|
+
warnings,
|
|
208
|
+
recommendations,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Get directive by name
|
|
213
|
+
*/
|
|
214
|
+
async getDirective(directiveName) {
|
|
215
|
+
const policy = await this.getCSPPolicy();
|
|
216
|
+
if (!policy)
|
|
217
|
+
return null;
|
|
218
|
+
return policy.directives.get(directiveName) || null;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Check if a resource would be allowed by CSP
|
|
222
|
+
*/
|
|
223
|
+
async checkResourceAllowed(resourceType, url) {
|
|
224
|
+
const policy = await this.getCSPPolicy();
|
|
225
|
+
if (!policy)
|
|
226
|
+
return true; // No CSP = allowed
|
|
227
|
+
// Find matching directive
|
|
228
|
+
let directive = policy.directives.get(`${resourceType}-src`);
|
|
229
|
+
if (!directive) {
|
|
230
|
+
directive = policy.directives.get('default-src');
|
|
231
|
+
}
|
|
232
|
+
if (!directive)
|
|
233
|
+
return true;
|
|
234
|
+
// Check if URL matches any source
|
|
235
|
+
const parsedUrl = new URL(url);
|
|
236
|
+
// Check 'self'
|
|
237
|
+
const pageUrl = new URL(this.page.url());
|
|
238
|
+
if (directive.allowsSelf && parsedUrl.origin === pageUrl.origin) {
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
// Check wildcard
|
|
242
|
+
if (directive.allowsWildcard) {
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
// Check specific sources
|
|
246
|
+
for (const value of directive.values) {
|
|
247
|
+
if (value.startsWith('http:') || value.startsWith('https:') || value.startsWith('/')) {
|
|
248
|
+
try {
|
|
249
|
+
const sourcePattern = new URL(value);
|
|
250
|
+
if (sourcePattern.origin === parsedUrl.origin) {
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
// Might be a path pattern
|
|
256
|
+
if (value.startsWith('/') && parsedUrl.pathname.startsWith(value)) {
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Setup CSP violation monitoring
|
|
266
|
+
*/
|
|
267
|
+
async setupViolationMonitoring() {
|
|
268
|
+
await this.page.evaluate(() => {
|
|
269
|
+
document.addEventListener('securitypolicyviolation', (event) => {
|
|
270
|
+
const e = event;
|
|
271
|
+
// Store violation for retrieval
|
|
272
|
+
const violations = window.__cspViolations || [];
|
|
273
|
+
violations.push({
|
|
274
|
+
directive: e.violatedDirective,
|
|
275
|
+
blockedURI: e.blockedURI,
|
|
276
|
+
policy: e.originalPolicy,
|
|
277
|
+
sourceFile: e.sourceFile,
|
|
278
|
+
lineNumber: e.lineNumber,
|
|
279
|
+
columnNumber: e.columnNumber,
|
|
280
|
+
timestamp: Date.now(),
|
|
281
|
+
});
|
|
282
|
+
window.__cspViolations = violations;
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
// Listen for console messages about CSP
|
|
286
|
+
this.page.on('console', (msg) => {
|
|
287
|
+
const text = msg.text();
|
|
288
|
+
if (text.includes('Refused to') || text.includes('CSP')) {
|
|
289
|
+
this.violations.push({
|
|
290
|
+
directive: 'unknown',
|
|
291
|
+
timestamp: Date.now(),
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Get collected violations
|
|
298
|
+
*/
|
|
299
|
+
getViolations() {
|
|
300
|
+
return [...this.violations];
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Clear violations
|
|
304
|
+
*/
|
|
305
|
+
clearViolations() {
|
|
306
|
+
this.violations = [];
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Generate a nonce value for inline scripts
|
|
310
|
+
*/
|
|
311
|
+
generateNonce() {
|
|
312
|
+
const array = new Uint8Array(16);
|
|
313
|
+
crypto.getRandomValues(array);
|
|
314
|
+
return Array.from(array, b => b.toString(16).padStart(2, '0')).join('');
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Inject nonce into inline scripts
|
|
318
|
+
*/
|
|
319
|
+
async injectNonces() {
|
|
320
|
+
const nonces = new Map();
|
|
321
|
+
await this.page.evaluate((nonceMap) => {
|
|
322
|
+
const scripts = document.querySelectorAll('script:not([src])');
|
|
323
|
+
scripts.forEach((script, i) => {
|
|
324
|
+
const nonce = 'nonce-' + Math.random().toString(36).substring(7);
|
|
325
|
+
script.setAttribute('nonce', nonce);
|
|
326
|
+
nonceMap[`script-${i}`] = nonce;
|
|
327
|
+
});
|
|
328
|
+
}, {});
|
|
329
|
+
return nonces;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Get all CSP-related meta tags
|
|
333
|
+
*/
|
|
334
|
+
async getMetaTags() {
|
|
335
|
+
return await this.page.evaluate(() => {
|
|
336
|
+
const metaTags = document.querySelectorAll('meta[http-equiv*="Content-Security-Policy" i]');
|
|
337
|
+
return Array.from(metaTags).map(meta => ({
|
|
338
|
+
httpEquiv: meta.getAttribute('http-equiv') || '',
|
|
339
|
+
content: meta.getAttribute('content') || '',
|
|
340
|
+
}));
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Check for common CSP bypass patterns
|
|
345
|
+
*/
|
|
346
|
+
async checkBypassPatterns() {
|
|
347
|
+
const bypasses = [];
|
|
348
|
+
const policy = await this.getCSPPolicy();
|
|
349
|
+
if (!policy)
|
|
350
|
+
return bypasses;
|
|
351
|
+
// Check for unsafe-inline with script-src (XSS risk)
|
|
352
|
+
const scriptSrc = policy.directives.get('script-src');
|
|
353
|
+
if (scriptSrc?.allowsUnsafeInline && !scriptSrc.nonce && scriptSrc.hashes.length === 0) {
|
|
354
|
+
bypasses.push('script-src with unsafe-inline allows arbitrary inline scripts');
|
|
355
|
+
}
|
|
356
|
+
// Check for data: in script-src
|
|
357
|
+
if (scriptSrc?.values.some((v) => v === 'data:')) {
|
|
358
|
+
bypasses.push('script-src allows data: URLs (can execute arbitrary scripts)');
|
|
359
|
+
}
|
|
360
|
+
// Check for unsafe-eval
|
|
361
|
+
if (scriptSrc?.allowsUnsafeEval) {
|
|
362
|
+
bypasses.push('script-src allows eval() (dynamic code execution risk)');
|
|
363
|
+
}
|
|
364
|
+
// Check for missing object-src (fallback to default-src which might be loose)
|
|
365
|
+
if (!policy.directives.has('object-src') && !policy.directives.has('default-src')) {
|
|
366
|
+
bypasses.push('Missing object-src allows plugin execution');
|
|
367
|
+
}
|
|
368
|
+
// Check for frame-src allowing potentially dangerous origins
|
|
369
|
+
const frameSrc = policy.directives.get('frame-src') || policy.directives.get('child-src');
|
|
370
|
+
if (frameSrc?.allowsWildcard) {
|
|
371
|
+
bypasses.push('frame-src allows any origin (iframe injection risk)');
|
|
372
|
+
}
|
|
373
|
+
return bypasses;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Compare two CSP policies
|
|
377
|
+
*/
|
|
378
|
+
comparePolicies(policy1, policy2) {
|
|
379
|
+
const stricter = [];
|
|
380
|
+
const looser = [];
|
|
381
|
+
const onlyIn1 = [];
|
|
382
|
+
const onlyIn2 = [];
|
|
383
|
+
const allDirectives = new Set([
|
|
384
|
+
...policy1.directives.keys(),
|
|
385
|
+
...policy2.directives.keys(),
|
|
386
|
+
]);
|
|
387
|
+
for (const directive of allDirectives) {
|
|
388
|
+
const d1 = policy1.directives.get(directive);
|
|
389
|
+
const d2 = policy2.directives.get(directive);
|
|
390
|
+
if (!d1) {
|
|
391
|
+
onlyIn2.push(directive);
|
|
392
|
+
}
|
|
393
|
+
else if (!d2) {
|
|
394
|
+
onlyIn1.push(directive);
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
// Compare values
|
|
398
|
+
if (d1.values.length < d2.values.length) {
|
|
399
|
+
stricter.push(directive);
|
|
400
|
+
}
|
|
401
|
+
else if (d1.values.length > d2.values.length) {
|
|
402
|
+
looser.push(directive);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return { stricter, looser, onlyIn1, onlyIn2 };
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Factory function to create CSP Handler
|
|
411
|
+
*/
|
|
412
|
+
export function createCSPHandler(page) {
|
|
413
|
+
return new CSPHandler(page);
|
|
414
|
+
}
|
|
415
|
+
export default CSPHandler;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Download Handler
|
|
3
|
+
*
|
|
4
|
+
* P1 - File download management
|
|
5
|
+
*
|
|
6
|
+
* Supports:
|
|
7
|
+
* - Click and wait for download
|
|
8
|
+
* - Download verification
|
|
9
|
+
* - Multiple downloads handling
|
|
10
|
+
* - Download timeout
|
|
11
|
+
* - File size validation
|
|
12
|
+
*
|
|
13
|
+
* @see https://playwright.dev/docs/downloads
|
|
14
|
+
*/
|
|
15
|
+
export interface DownloadConfig {
|
|
16
|
+
/** Download directory */
|
|
17
|
+
downloadDir?: string;
|
|
18
|
+
/** Timeout for download to start (ms) */
|
|
19
|
+
timeout?: number;
|
|
20
|
+
/** Save downloaded files */
|
|
21
|
+
saveFiles?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface DownloadInfo {
|
|
24
|
+
/** Suggested filename */
|
|
25
|
+
filename: string;
|
|
26
|
+
/** Save path (if saved) */
|
|
27
|
+
path?: string;
|
|
28
|
+
/** Download URL */
|
|
29
|
+
url?: string;
|
|
30
|
+
/** File MIME type */
|
|
31
|
+
mimeType?: string;
|
|
32
|
+
/** File size in bytes */
|
|
33
|
+
size?: number;
|
|
34
|
+
/** Download timestamp */
|
|
35
|
+
timestamp: number;
|
|
36
|
+
}
|
|
37
|
+
export interface DownloadActionOptions {
|
|
38
|
+
/** Action to perform before download (click, hover, etc) */
|
|
39
|
+
action?: 'click' | 'dblclick' | 'hover';
|
|
40
|
+
/** Wait for download to complete */
|
|
41
|
+
waitForCompletion?: boolean;
|
|
42
|
+
/** Timeout (ms) */
|
|
43
|
+
timeout?: number;
|
|
44
|
+
}
|
|
45
|
+
export interface DownloadVerification {
|
|
46
|
+
/** Expected filename pattern */
|
|
47
|
+
filenamePattern?: string | RegExp;
|
|
48
|
+
/** Minimum file size (bytes) */
|
|
49
|
+
minSize?: number;
|
|
50
|
+
/** Maximum file size (bytes) */
|
|
51
|
+
maxSize?: number;
|
|
52
|
+
/** Expected MIME type */
|
|
53
|
+
mimeType?: string;
|
|
54
|
+
}
|
|
55
|
+
export interface DownloadResult {
|
|
56
|
+
success: boolean;
|
|
57
|
+
download?: DownloadInfo;
|
|
58
|
+
rawDownload?: any;
|
|
59
|
+
error?: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Download Handler class
|
|
63
|
+
*/
|
|
64
|
+
export declare class DownloadHandler {
|
|
65
|
+
private downloads;
|
|
66
|
+
private downloadDir;
|
|
67
|
+
private defaultTimeout;
|
|
68
|
+
private saveFiles;
|
|
69
|
+
private stats;
|
|
70
|
+
constructor(config?: DownloadConfig);
|
|
71
|
+
private ensureDownloadDir;
|
|
72
|
+
/**
|
|
73
|
+
* Setup download handling for a page
|
|
74
|
+
*/
|
|
75
|
+
setupDownloadHandler(page: any): void;
|
|
76
|
+
/**
|
|
77
|
+
* Click element and wait for download
|
|
78
|
+
*/
|
|
79
|
+
clickAndWaitForDownload(page: any, selector: string, options?: DownloadActionOptions): Promise<DownloadResult & {
|
|
80
|
+
download?: any;
|
|
81
|
+
}>;
|
|
82
|
+
/**
|
|
83
|
+
* Click multiple elements and wait for downloads
|
|
84
|
+
*/
|
|
85
|
+
clickAndWaitForDownloads(page: any, selectors: string[], options?: DownloadActionOptions): Promise<Array<DownloadResult & {
|
|
86
|
+
download?: any;
|
|
87
|
+
}>>;
|
|
88
|
+
/**
|
|
89
|
+
* Wait for download by filename pattern
|
|
90
|
+
*/
|
|
91
|
+
waitForDownload(page: any, filenamePattern: string | RegExp, timeout?: number): Promise<DownloadResult>;
|
|
92
|
+
/**
|
|
93
|
+
* Verify a download
|
|
94
|
+
*/
|
|
95
|
+
verifyDownload(download: any, verification: any): Promise<any>;
|
|
96
|
+
/**
|
|
97
|
+
* Get all downloads
|
|
98
|
+
*/
|
|
99
|
+
getAllDownloads(): DownloadInfo[];
|
|
100
|
+
/**
|
|
101
|
+
* Get download by filename
|
|
102
|
+
*/
|
|
103
|
+
getDownload(filename: string): DownloadInfo | undefined;
|
|
104
|
+
/**
|
|
105
|
+
* Get last download
|
|
106
|
+
*/
|
|
107
|
+
getLastDownload(): DownloadInfo | undefined;
|
|
108
|
+
/**
|
|
109
|
+
* Clear all downloads
|
|
110
|
+
*/
|
|
111
|
+
clearDownloads(): void;
|
|
112
|
+
/**
|
|
113
|
+
* Delete downloaded files
|
|
114
|
+
*/
|
|
115
|
+
clearDownloadFiles(): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Get download directory
|
|
118
|
+
*/
|
|
119
|
+
getDownloadDir(): string;
|
|
120
|
+
/**
|
|
121
|
+
* Set download directory
|
|
122
|
+
*/
|
|
123
|
+
setDownloadDir(dir: string): void;
|
|
124
|
+
/**
|
|
125
|
+
* Get download count
|
|
126
|
+
*/
|
|
127
|
+
get downloadCount(): number;
|
|
128
|
+
/**
|
|
129
|
+
* Assert download exists
|
|
130
|
+
*/
|
|
131
|
+
assertDownloadExists(filenamePattern: string | RegExp): DownloadResult;
|
|
132
|
+
/**
|
|
133
|
+
* Get download statistics
|
|
134
|
+
*/
|
|
135
|
+
getStats(): {
|
|
136
|
+
totalDownloads: number;
|
|
137
|
+
successfulDownloads: number;
|
|
138
|
+
failedDownloads: number;
|
|
139
|
+
totalSize: number;
|
|
140
|
+
averageSize: number;
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Get download history
|
|
144
|
+
*/
|
|
145
|
+
getHistory(): DownloadInfo[];
|
|
146
|
+
/**
|
|
147
|
+
* Reset statistics
|
|
148
|
+
*/
|
|
149
|
+
resetStats(): void;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Factory function to create Download Handler
|
|
153
|
+
*/
|
|
154
|
+
export declare function createDownloadHandler(config?: DownloadConfig): DownloadHandler;
|
|
155
|
+
export default DownloadHandler;
|