wpsecscan 2.6.0__tar.gz → 2.7.0__tar.gz
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.
- {wpsecscan-2.6.0/wpsecscan.egg-info → wpsecscan-2.7.0}/PKG-INFO +2 -2
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/README.md +1 -1
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/pyproject.toml +1 -1
- wpsecscan-2.7.0/wpsecscan/__init__.py +1 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/__main__.py +242 -1
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/ai_assist.py +94 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/auto_pr.py +49 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/__init__.py +8 -0
- wpsecscan-2.7.0/wpsecscan/checks/companion_v14.py +189 -0
- wpsecscan-2.7.0/wpsecscan/checks/headless_vercel_netlify_detect.py +72 -0
- wpsecscan-2.7.0/wpsecscan/checks/perf_of_target.py +183 -0
- wpsecscan-2.7.0/wpsecscan/checks/trellis_yaml_audit.py +64 -0
- wpsecscan-2.7.0/wpsecscan/cli_extras.py +169 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/check_tags.json +5 -1
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/compliance_map.json +20 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/report.html.j2 +13 -0
- wpsecscan-2.7.0/wpsecscan/edu_v27.py +203 -0
- wpsecscan-2.7.0/wpsecscan/gui_v27_extras.py +332 -0
- wpsecscan-2.7.0/wpsecscan/integrations_v27.py +622 -0
- wpsecscan-2.7.0/wpsecscan/marketplace_v27.py +234 -0
- wpsecscan-2.7.0/wpsecscan/mobile_v27.py +146 -0
- wpsecscan-2.7.0/wpsecscan/perf_v27.py +185 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/auditor_pdf.py +15 -3
- wpsecscan-2.7.0/wpsecscan/reporters/d3fend_mapping.py +101 -0
- wpsecscan-2.7.0/wpsecscan/reporters/executive_tldr.py +75 -0
- wpsecscan-2.7.0/wpsecscan/reporters/finding_heatmap.py +124 -0
- wpsecscan-2.7.0/wpsecscan/reporters/gdpr_dsr_report.py +91 -0
- wpsecscan-2.7.0/wpsecscan/reporters/live_sync.py +116 -0
- wpsecscan-2.7.0/wpsecscan/reporters/risk_forecast.py +99 -0
- wpsecscan-2.7.0/wpsecscan/reporters/share_link.py +108 -0
- wpsecscan-2.7.0/wpsecscan/reporters/vex_export.py +90 -0
- wpsecscan-2.7.0/wpsecscan/reporters/xlsx_pivot.py +101 -0
- wpsecscan-2.7.0/wpsecscan/trust_v27.py +153 -0
- wpsecscan-2.7.0/wpsecscan/workflow_cmds.py +593 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0/wpsecscan.egg-info}/PKG-INFO +2 -2
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan.egg-info/SOURCES.txt +23 -1
- wpsecscan-2.6.0/wpsecscan/__init__.py +0 -1
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/LICENSE +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/NOTICE +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/setup.cfg +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_audit_fixes.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_audit_round_r.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_board_one_pager.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_burp_zap_import.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_cache.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_checks.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_confidence_eta_tags.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_creds_vault_cli.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_default_creds.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_diff_agency.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_gh_check_run.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_global_sigs_regression.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_login_throttle.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_login_throttle_deep.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_mobile_api_traversal.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_new_check_inventory.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_new_checks.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_new_checks_aggressive.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_new_checks_quality.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_notify.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_password_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_payloads.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_phase5.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_playbook.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_prove.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_reference_diff.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_reference_diff_traversal.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_risk_score.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_round_54.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_round_55.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_round_56_activity.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_round_57.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_round_58.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_round_59.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_round_60.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_round_61.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_round_62.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_round_63.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_round_64.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_round_65.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_round_q.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_scan_zip.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_scheduler.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_scheduler_cron_dow.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_siem.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_sla.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_slack_app.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_ssh_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/tests/test_user_template.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/_util.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/activity.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/ai_fp_predictor.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/ai_safety.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/ai_triage.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/ai_triage_ui.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/analytics.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/api_server.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/attack_checkpoint.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/attack_scripts.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/auth/__init__.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/auth/approval_workflow.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/auth/audit_log.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/auth/rbac.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/auth/sso_oidc.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/auth/sso_saml.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/auto_update.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/baseline.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/branding.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/bug_report.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/burp_import.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/cache.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/check_health.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/_template.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/a11y_deep.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/a11y_lite.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/a11y_wcag_aaa.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/abuseipdb_lookup.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/admin_ajax_brute_surface.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/admin_invite_link_scan.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/ai_agent_webhook_leak.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/ai_chatbot_endpoint_leak.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/ai_plugin_prompt_storage.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/ai_prompt_injection_passive.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/ajax_surface.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/algolia_elastic_frontend_keys.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/amp_transitional_redirect.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/app_passwords.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/app_passwords_stale_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/auth_modernisation.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/authenticated.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/backup_exposure.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/backup_file_fuzz.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/block_bindings_exposure.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/block_style_variations_url.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/brand_monitor.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/bucket_shadow_takeover.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/cache_headers.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/cache_poisoning.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/cache_poisoning_v2.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/cdn_edge_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/cloud_metadata_ssrf.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/cloudflare_origin_leak.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/companion_advanced.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/companion_v13.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/compliance_frameworks.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/composer_lock_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/composer_npm_typosquat.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/cookie_consent.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/cookie_consent_desync.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/cookies.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/core_checksums.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/core_cves.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/core_tampering.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/core_version.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/cors.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/crlf_location_injection.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/crypto_agility.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/crypto_payment_callback_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/cryptominer_js_injection.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/csp.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/csp_report_endpoint.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/csrf_entropy.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/csrf_nonce.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/csv_export_csp.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/ct_log_recent_certs.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/ct_log_shadow_cert.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/db_admin_login_probe.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/db_trigger_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/debug_leaks.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/debug_log_pii_sniff.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/default_creds.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/dev_params.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/directory_listing.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/dns_deep.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/dns_rebinding.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/dns_security.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/dns_templates.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/dom_xss_headless.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/email_obfuscation_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/email_security_deep.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/env_file_enum.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/error_pages.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/exposed_files.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/favicon_fingerprint.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/file_upload.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/font_library_api_ssrf.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/forced_browse.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/form_builder_upload_bypass.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/gdpr_dsr.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/gdpr_dsr_endpoint_enum.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/git_dir_deep_scan.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/github_actions_workflow_leak.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/github_leak_search.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/graphql_dos.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/graphql_field_authz_deep.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/gtm_inventory.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/gutenberg_blocks.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/header_smuggling_case.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/headless_templates.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/headless_wp_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/heartbeat_abuse.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/heartbeat_frontend.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/helm_compose_leak.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/hibp.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/honeypot_admin.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/host_header_validation.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/host_platform_detect.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/host_recon.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/hosting_platform_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/hostname_collision.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/hpp.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/hsts_preload_eligibility.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/hsts_preload_mismatch.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/html_api_csp_nonce.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/http2_settings.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/http2_smuggling.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/http3_fingerprint.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/http_methods.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/interactivity_api_state_leak.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/js_framework_deep.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/js_libraries.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/js_supply_chain.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/jwt_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/jwt_auth_plugin_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/lead_gen_list_id_enum.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/login.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/login_redirect_http_hop.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/login_throttle.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/login_throttle_deep.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/login_timing.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/magecart_skimmer_patterns.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/mcp_endpoint_exposure.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/mfa_priv_account_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/misc_injection_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/mixed_content.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/mobile_app_endpoints.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/multisite.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/multisite_sso_key_reuse.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/nft_mint_pubapi.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/nonce_freshness.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/nosql_injection.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/oauth_oidc.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/oauth_redirect.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/oauth_redirect_misconfig.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/object_cache_dropin.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/open_redirect.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/open_registration.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/openapi_scanner.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/origin_ip_discovery.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/osint_enrich.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/package_lock_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/page_builder_cve.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/path_bypass.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/path_traversal.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/payment_commerce_deep.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/payment_gateway_test_keys.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/perf_budget.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/permissions_policy.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/php_eol.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/phpinfo_dangerous_directives.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/plugin_archive_fuzz.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/plugin_cemetery.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/plugin_cves.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/plugin_hash_fingerprint.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/plugin_install_rest_race.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/plugin_route_fuzz.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/plugin_specific_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/plugin_typosquat_detection.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/plugins.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/postmeta_stored_xss_scan.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/premium_license_leak.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/privacy_inventory.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/prototype_pollution.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/pwa_service_worker_cache.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/race_condition.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/redirect_chain.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/referenced_buckets.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/rest_api.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/rest_app_passwords_enum.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/rest_fields_dos.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/rest_link_header.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/rest_namespace_leak.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/rest_permission_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/rest_schema_field_leak.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/robots_sitemap.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/rum_beacons.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/s3_bucket_discovery.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/saml_xsw.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/search_highlight_xss.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/secret_leak.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/security_txt.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/sendmail_injection.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/server_stack_reveal.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/server_timing.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/service_exposure.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/service_worker_scope_hijack.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/session_fixation.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/sitemap_cve_probe.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/smuggling_probe.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/solidity_abi_leak.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/source_maps.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/speculation_rules_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/spider_crawl.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/sqli.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/sri_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/sri_pwa_misc.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/ssrf.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/ssti.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/stripe_webhook_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/subdomains.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/tailwind_css_comment_leak.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/theme_cves.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/theme_json_font_ssrf.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/themes.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/timthumb.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/tls_deep.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/tls_headers.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/tls_modern.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/tls_reneg_dos.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/translation_plugin_key_leak.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/turnstile_sitekey_reuse.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/upload_bypass_deep.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/upload_path_predictable.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/uploads_year_listing.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/users.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/users_deep.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/users_me_capability_leak.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/vendor_backdoor_patterns.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/vercel_preview_url_leak.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/waf.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/waf_brand_deep.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/waf_bypass_probe.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/waf_lockout_guard.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/waf_ruleset.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wallet_seed_phrase_leak.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wc_api_key_escalation.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/web3_wallet_connector_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/webdav.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/webhook_signing_secrets.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/webhook_url_fingerprint.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/webhooks.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/websocket_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/websocket_fuzz.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/well_known.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/woo_blocks_checkout_drift.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/woo_subscriptions_renewal_race.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/woocommerce_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/woocommerce_deep.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/woocommerce_order_idor.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/woocommerce_storefront.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wp_builder_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wp_cli_http_exposure.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wp_cli_inject.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wp_commerce_alt_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wp_cron_cpu.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wp_cron_disabled.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wp_cron_dos.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wp_debug_display_via_rest.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wp_engine_misconfig.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wp_fork_detection.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wp_form_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wp_mail_smtp_site_health_leak.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wp_membership_lms_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wp_multisite_deep.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wp_playground_sqlite.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wp_plugin_ecosystem_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wp_query_sqli.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wp_rest_methods.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wp_salts_age.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wpconfig_hardening_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wpcron_suspicious_jobs.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/wpgraphql.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/xmlrpc_amplification.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/xmlrpc_deep.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/xmlrpc_method_brute.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/xss_dom_sinks.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/xss_reflected.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/xxe_upload.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/yaml_templates.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/yaml_workflows.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/checks/yarn_pnpm_lock_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/completion.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/confidence.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/config.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/console_live.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/continuous_monitor.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/crash_submit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/creds_vault.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/daemon/__init__.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/daemon/_legacy.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/daemon/webhook_v2.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/common_paths.txt +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/compliance_extra.json +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/compliance_v2.json +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/dashboard.html.j2 +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/datadog-dashboard.json +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/exploit_playbook.json +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/exploit_signatures.json +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/known_paths.txt +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/marketplace.json +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/newrelic-dashboard.json +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/openapi-scan-report.json +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/payloads.json +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/plugin_cves.json +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/plugin_file_hashes.json +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/quick_fixes.json +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/references.json +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/remediation_videos.json +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/report.schema.json +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/data/security_tutorial.json +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/db.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/demo.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/diff.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/education.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/enterprise/__init__.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/enterprise/billing_stub.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/enterprise/multi_tenant.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/enterprise/quota.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/eta.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/fun/__init__.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/fun/bingo_card.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/gh_check_run.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/gui.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/gui_payloads.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/gui_windows.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/har_replay.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/hardware_keys.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/heatmap.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/history.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/http.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/i18n.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/importers/__init__.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/importers/burp_zap.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/incremental/__init__.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/incremental/_legacy.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/incremental/diff_scan.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/incremental/smart_skip.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/integrations/__init__.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/integrations/cisa_kev.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/integrations/epss.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/integrations/github_issues.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/integrations/osint.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/integrations/sucuri_sitecheck.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/integrations/threat_intel.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/integrations/ticketing.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/integrations/tor_proxy.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/integrations/virustotal.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/integrations/webhooks_chat.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/interactsh.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/issue_push.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/js_plugin.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/kev.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/licensing.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/log.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/marketplace.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/mobile_api.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/mobile_app_discovery.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/models.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/monitors.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/notify.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/observability.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/password_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/payloads.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/perf/__init__.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/perf/_legacy.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/perf/connection_pool.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/perf/parallel_sites.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/playbook.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/policy.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/pr_inspector.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/prove.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/py.typed +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/recommend.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reference_diff.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/region_egress.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/remediation_videos.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/report_query.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/__init__.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/attestation.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/badge_svg.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/board_one_pager.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/bounty_format.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/burp_export.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/comparison_two_sites.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/compliance_attestation.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/console.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/csv_out.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/dashboard.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/diff_agency.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/diff_viewer.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/docx_report.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/eli5_toggle.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/exec_pdf.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/executive_pack.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/html.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/issue_export.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/json_out.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/markdown.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/org_dashboard.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/pdf_custom_branding.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/public_page.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/sarif.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/snapshot_compare.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/translated_summary.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/trend_over_time.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/user_template.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/reporters/xlsx_out.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/risk.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/risk_weights.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/sbom.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/scan_zip.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/scanner.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/scheduler.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/siem.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/sites.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/sla.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/slack_app.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/spider.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/ssh_audit.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/tags.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/template_engine.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/template_signature.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/threat_intel_v2.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/tray.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/turbo_engine.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/ua_rotation.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/ux_extras.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/waf_rules.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/watchers.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan/workflow.py +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan.egg-info/dependency_links.txt +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan.egg-info/entry_points.txt +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan.egg-info/requires.txt +0 -0
- {wpsecscan-2.6.0 → wpsecscan-2.7.0}/wpsecscan.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wpsecscan
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.7.0
|
|
4
4
|
Summary: Defensive WordPress security scanner. 200+ checks, 8-source nightly CVE aggregator, AI-assisted remediation (BYO key), 15 compliance frameworks (OWASP/PCI/NIST/ISO/HIPAA/SOC2/HITRUST/CMMC), Sigstore-signed releases with SLSA L3 provenance, 10 threat-intel feeds (KEV/EPSS/Exploit-DB/ATT&CK/STIX/MISP/OTX/GreyNoise), continuous monitors, consent-gated exploit verification, multi-tenant RBAC/SSO/audit-log enterprise mode, 12 report formats. Authorized testing only.
|
|
5
5
|
Author-email: Bryan <bryaninbangkok@gmail.com>
|
|
6
6
|
License: GNU AFFERO GENERAL PUBLIC LICENSE
|
|
@@ -730,7 +730,7 @@ Dynamic: license-file
|
|
|
730
730
|
[](https://github.com/bryanflowers/wpsecscan/releases/latest)
|
|
731
731
|
[](https://github.com/bryanflowers/wpsecscan/releases)
|
|
732
732
|
[](https://www.python.org/)
|
|
733
|
-
[](FEATURES.md)
|
|
734
734
|
[](docs/data-sources.md)
|
|
735
735
|
[](tests/)
|
|
736
736
|
[](https://pypi.org/project/wpsecscan/)
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://github.com/bryanflowers/wpsecscan/releases/latest)
|
|
7
7
|
[](https://github.com/bryanflowers/wpsecscan/releases)
|
|
8
8
|
[](https://www.python.org/)
|
|
9
|
-
[](FEATURES.md)
|
|
10
10
|
[](docs/data-sources.md)
|
|
11
11
|
[](tests/)
|
|
12
12
|
[](https://pypi.org/project/wpsecscan/)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "wpsecscan"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.7.0"
|
|
8
8
|
description = "Defensive WordPress security scanner. 200+ checks, 8-source nightly CVE aggregator, AI-assisted remediation (BYO key), 15 compliance frameworks (OWASP/PCI/NIST/ISO/HIPAA/SOC2/HITRUST/CMMC), Sigstore-signed releases with SLSA L3 provenance, 10 threat-intel feeds (KEV/EPSS/Exploit-DB/ATT&CK/STIX/MISP/OTX/GreyNoise), continuous monitors, consent-gated exploit verification, multi-tenant RBAC/SSO/audit-log enterprise mode, 12 report formats. Authorized testing only."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.7.0"
|
|
@@ -397,6 +397,114 @@ async def _scan_one(target: str, args, console: Console):
|
|
|
397
397
|
if not args.no_console:
|
|
398
398
|
console.print(f"[green]✓[/green] Board 1-pager: [bold]{bp_p}[/bold]")
|
|
399
399
|
|
|
400
|
+
# C49 — per-finding share link
|
|
401
|
+
if getattr(args, "share_finding", None):
|
|
402
|
+
try:
|
|
403
|
+
cid, idx_str = args.share_finding.split("#", 1)
|
|
404
|
+
idx = int(idx_str)
|
|
405
|
+
from .reporters import share_link as _sl
|
|
406
|
+
share_p = out_dir / f"{stem}-{cid}-{idx}.share.json"
|
|
407
|
+
_sl.write(report, cid, idx, share_p)
|
|
408
|
+
if not args.no_console:
|
|
409
|
+
console.print(f"[green]✓[/green] Share-link: [bold]{share_p}[/bold]")
|
|
410
|
+
except (ValueError, Exception) as e: # noqa: BLE001
|
|
411
|
+
console.print(f"[yellow]--share-finding failed: {e}[/yellow]")
|
|
412
|
+
|
|
413
|
+
# C54 — risk-score forecast
|
|
414
|
+
if getattr(args, "risk_forecast", False):
|
|
415
|
+
from .reporters import risk_forecast as _rf
|
|
416
|
+
fc = _rf.forecast(report.target)
|
|
417
|
+
if not args.no_console:
|
|
418
|
+
console.print(f"[cyan]{_rf.render_text(fc)}[/cyan]")
|
|
419
|
+
(out_dir / f"{stem}-forecast.json").write_text(
|
|
420
|
+
__import__("json").dumps(fc, indent=2), encoding="utf-8",
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
# C55 — finding heatmap SVG
|
|
424
|
+
if getattr(args, "heatmap_svg", False):
|
|
425
|
+
from .reporters import finding_heatmap as _fh
|
|
426
|
+
hm_p = out_dir / f"{stem}-heatmap.svg"
|
|
427
|
+
_fh.write(report.target, hm_p)
|
|
428
|
+
if not args.no_console:
|
|
429
|
+
console.print(f"[green]✓[/green] Finding heatmap SVG: [bold]{hm_p}[/bold]")
|
|
430
|
+
|
|
431
|
+
# C53 — xlsx with pre-built pivot tables
|
|
432
|
+
if getattr(args, "xlsx_pivot", False):
|
|
433
|
+
from .reporters import xlsx_pivot as _xp
|
|
434
|
+
xp_p = out_dir / f"{stem}-pivot.xlsx"
|
|
435
|
+
_xp.write(report, xp_p)
|
|
436
|
+
if not args.no_console:
|
|
437
|
+
console.print(f"[green]✓[/green] xlsx with pivots: [bold]{xp_p}[/bold]")
|
|
438
|
+
|
|
439
|
+
# C56 — OpenVEX export
|
|
440
|
+
if getattr(args, "vex_export", False):
|
|
441
|
+
from .reporters import vex_export as _vex
|
|
442
|
+
vex_p = out_dir / f"{stem}-vex.json"
|
|
443
|
+
_vex.write(report, vex_p)
|
|
444
|
+
if not args.no_console:
|
|
445
|
+
console.print(f"[green]✓[/green] OpenVEX: [bold]{vex_p}[/bold]")
|
|
446
|
+
|
|
447
|
+
# C59 — D3FEND mapping
|
|
448
|
+
if getattr(args, "d3fend_mapping", False):
|
|
449
|
+
from .reporters import d3fend_mapping as _d3
|
|
450
|
+
d3_p = out_dir / f"{stem}-d3fend.html"
|
|
451
|
+
_d3.write(report, d3_p)
|
|
452
|
+
if not args.no_console:
|
|
453
|
+
console.print(f"[green]✓[/green] D3FEND mapping: [bold]{d3_p}[/bold]")
|
|
454
|
+
|
|
455
|
+
# C60 — GDPR DSR-ready user-data report
|
|
456
|
+
if getattr(args, "gdpr_dsr_report", False):
|
|
457
|
+
from .reporters import gdpr_dsr_report as _gdpr
|
|
458
|
+
g_p = out_dir / f"{stem}-dsr.md"
|
|
459
|
+
_gdpr.write(report, g_p)
|
|
460
|
+
if not args.no_console:
|
|
461
|
+
console.print(f"[green]✓[/green] GDPR DSR report: [bold]{g_p}[/bold]")
|
|
462
|
+
|
|
463
|
+
# C57 — executive TL;DR
|
|
464
|
+
if getattr(args, "executive_tldr", False):
|
|
465
|
+
from .reporters import executive_tldr as _et
|
|
466
|
+
t_p = out_dir / f"{stem}-tldr.txt"
|
|
467
|
+
_et.write(report, t_p)
|
|
468
|
+
if not args.no_console:
|
|
469
|
+
console.print(f"[cyan]TL;DR:[/cyan] {_et.build(report)}")
|
|
470
|
+
|
|
471
|
+
# C50 — one-liner patches alongside auto-PR script
|
|
472
|
+
if getattr(args, "auto_pr_patches", False):
|
|
473
|
+
from . import auto_pr as _ap
|
|
474
|
+
patches_dir = out_dir / f"{stem}-patches"
|
|
475
|
+
n = _ap.write_one_liner_patches(report, patches_dir,
|
|
476
|
+
min_sev=getattr(args, "push_min_sev", "medium"))
|
|
477
|
+
if not args.no_console:
|
|
478
|
+
if n:
|
|
479
|
+
console.print(f"[green]✓[/green] Auto-PR one-liner patches: {n} files in {patches_dir}")
|
|
480
|
+
else:
|
|
481
|
+
console.print("[yellow]--auto-pr-patches: no eligible one-liner findings or AI backend missing[/yellow]")
|
|
482
|
+
|
|
483
|
+
# C51 — Confluence / Notion live page sync
|
|
484
|
+
if getattr(args, "live_sync", None):
|
|
485
|
+
from .reporters import live_sync as _ls
|
|
486
|
+
backends = (args.live_sync or "").lower()
|
|
487
|
+
if backends in ("confluence", "both"):
|
|
488
|
+
# Best body = the HTML report if available, else a tiny summary
|
|
489
|
+
html_body = ""
|
|
490
|
+
try:
|
|
491
|
+
html_body = (out_dir / f"{stem}.html").read_text(encoding="utf-8")
|
|
492
|
+
except OSError:
|
|
493
|
+
html_body = f"<p>WPSecScan score: {report.risk_score}/100 at {report.scanned_at}</p>"
|
|
494
|
+
ok, msg = _ls.sync_confluence(html_body)
|
|
495
|
+
if not args.no_console:
|
|
496
|
+
console.print(f"[cyan]live-sync confluence: {msg}[/cyan]")
|
|
497
|
+
if backends in ("notion", "both"):
|
|
498
|
+
text = (
|
|
499
|
+
f"WPSecScan — {report.target}\n"
|
|
500
|
+
f"Scanned: {report.scanned_at}\n"
|
|
501
|
+
f"Risk score: {report.risk_score}/100\n"
|
|
502
|
+
f"Findings: {len(report.all_findings)}"
|
|
503
|
+
)
|
|
504
|
+
ok, msg = _ls.sync_notion(text)
|
|
505
|
+
if not args.no_console:
|
|
506
|
+
console.print(f"[cyan]live-sync notion: {msg}[/cyan]")
|
|
507
|
+
|
|
400
508
|
# #61 — live SIEM forwarders (Splunk HEC / Datadog Logs / Loki / Beats)
|
|
401
509
|
if (getattr(args, "siem_splunk", None) or getattr(args, "siem_datadog", None)
|
|
402
510
|
or getattr(args, "siem_loki", None) or getattr(args, "siem_beats", None)
|
|
@@ -852,6 +960,14 @@ def _apply_config_and_profile(parser, args) -> None:
|
|
|
852
960
|
|
|
853
961
|
|
|
854
962
|
def main() -> None:
|
|
963
|
+
# F83 (v2.7.0): enable VT-mode ANSI on legacy cmd.exe / PowerShell so
|
|
964
|
+
# rich's colours render natively (no-op on macOS / Linux + on modern
|
|
965
|
+
# Windows Terminal where VT is already on).
|
|
966
|
+
try:
|
|
967
|
+
from .cli_extras import enable_win_ansi
|
|
968
|
+
enable_win_ansi()
|
|
969
|
+
except ImportError:
|
|
970
|
+
pass
|
|
855
971
|
# ---- Subcommand dispatch (round-60): keep before argparse so existing
|
|
856
972
|
# `wpsecscan <url>` invocations stay backward-compatible. The list of
|
|
857
973
|
# subcommand names is centralised in SUBCOMMAND_NAMES so it can never
|
|
@@ -1014,6 +1130,8 @@ def main() -> None:
|
|
|
1014
1130
|
help="G90: predict P(false-positive) per finding from the operator's "
|
|
1015
1131
|
"snooze history; decorates extra.fp_score on every finding. "
|
|
1016
1132
|
"No-op when ~/.wpsecscan/snoozes.json is empty.")
|
|
1133
|
+
p.add_argument("--quiet", "-q", dest="no_console", action="store_true",
|
|
1134
|
+
help="F82: alias for --no-console; suppress per-check console output.")
|
|
1017
1135
|
p.add_argument("--tldr", action="store_true",
|
|
1018
1136
|
help="Item #81: print a one-line summary (score/worst-sev/finding-count) "
|
|
1019
1137
|
"to stdout and suppress all other output. Exit code = worst severity "
|
|
@@ -1053,6 +1171,36 @@ def main() -> None:
|
|
|
1053
1171
|
p.add_argument("--board-1pager", action="store_true",
|
|
1054
1172
|
help="#52: write a single-landscape-page board-room risk dashboard "
|
|
1055
1173
|
"(three big numbers, three sentences, three actions to ratify).")
|
|
1174
|
+
p.add_argument("--share-finding", default=None, metavar="CHECK_ID#INDEX",
|
|
1175
|
+
help="C49: write a per-finding share-link JSON-LD blob with HMAC signature. "
|
|
1176
|
+
"Example: --share-finding headers#0 writes the first finding from "
|
|
1177
|
+
"the 'headers' check.")
|
|
1178
|
+
p.add_argument("--live-sync", default=None, metavar="confluence|notion|both",
|
|
1179
|
+
help="C51: push the agency dashboard to Confluence and/or Notion on each "
|
|
1180
|
+
"scan. Reads WPSECSCAN_CONFLUENCE_* and WPSECSCAN_NOTION_* env vars.")
|
|
1181
|
+
p.add_argument("--risk-forecast", action="store_true",
|
|
1182
|
+
help="C54: print a 30/60/90-day risk-score projection from snapshot history.")
|
|
1183
|
+
p.add_argument("--heatmap-svg", action="store_true",
|
|
1184
|
+
help="C55: write a per-finding heatmap SVG showing presence across recent scans.")
|
|
1185
|
+
p.add_argument("--xlsx-pivot", action="store_true",
|
|
1186
|
+
help="C53: write an .xlsx with pre-built pivot sheets (by-severity, "
|
|
1187
|
+
"by-check, severity×check_id heatmap).")
|
|
1188
|
+
p.add_argument("--vex-export", action="store_true",
|
|
1189
|
+
help="C56: write an OpenVEX 0.2 document mapping CVE findings to "
|
|
1190
|
+
"affected/fixed/not_affected status. Complements --sbom.")
|
|
1191
|
+
p.add_argument("--d3fend-mapping", action="store_true",
|
|
1192
|
+
help="C59: write an HTML view grouping findings by MITRE D3FEND "
|
|
1193
|
+
"defensive-technique ID.")
|
|
1194
|
+
p.add_argument("--gdpr-dsr-report", action="store_true",
|
|
1195
|
+
help="C60: write a markdown SAR/DSR-ready audit-trail of findings "
|
|
1196
|
+
"that touched user-data fields.")
|
|
1197
|
+
p.add_argument("--executive-tldr", action="store_true",
|
|
1198
|
+
help="C57: print + write a deterministic 3-sentence executive "
|
|
1199
|
+
"summary suitable for an email subject/body.")
|
|
1200
|
+
p.add_argument("--auto-pr-patches", action="store_true",
|
|
1201
|
+
help="C50: ALONGSIDE the existing --auto-pr-repo gh-command script, "
|
|
1202
|
+
"write unified-diff .patch files for one-liner fixes "
|
|
1203
|
+
"(.htaccess / wp-config.php / header.php). Needs AI backend.")
|
|
1056
1204
|
p.add_argument("--print-openapi", action="store_true",
|
|
1057
1205
|
help="#53: print the OpenAPI 3.1 schema for the WPSecScan JSON output to "
|
|
1058
1206
|
"stdout, then exit. Pipe to openapi-typescript / openapi-generator to "
|
|
@@ -1101,8 +1249,28 @@ def main() -> None:
|
|
|
1101
1249
|
help="Diff scan-in-progress against the most recent saved snapshot older than WINDOW "
|
|
1102
1250
|
"(e.g. `7d`, `24h`, `2w`). Composes with the scan; outputs the delta after the scan completes.")
|
|
1103
1251
|
p.add_argument("--debug", action="store_true", help="Verbose logging to ~/.wpsecscan/logs/")
|
|
1104
|
-
|
|
1252
|
+
# K124 — third-party audit link in --version output
|
|
1253
|
+
try:
|
|
1254
|
+
from .trust_v27 import third_party_audit_url as _audit_url
|
|
1255
|
+
_audit = _audit_url()
|
|
1256
|
+
except ImportError:
|
|
1257
|
+
_audit = ""
|
|
1258
|
+
p.add_argument(
|
|
1259
|
+
"--version", action="version",
|
|
1260
|
+
version=(f"%(prog)s {__version__}"
|
|
1261
|
+
+ (f"\nThird-party audit: {_audit}" if _audit else "")),
|
|
1262
|
+
)
|
|
1263
|
+
p.add_argument("--deterministic", action="store_true",
|
|
1264
|
+
help="K125: pin all randomness so two runs of the same target "
|
|
1265
|
+
"produce byte-identical reports.")
|
|
1105
1266
|
args = p.parse_args()
|
|
1267
|
+
# K125 — apply deterministic seed BEFORE any other module fires.
|
|
1268
|
+
if getattr(args, "deterministic", False):
|
|
1269
|
+
try:
|
|
1270
|
+
from .trust_v27 import set_deterministic_seed
|
|
1271
|
+
set_deterministic_seed()
|
|
1272
|
+
except ImportError:
|
|
1273
|
+
pass
|
|
1106
1274
|
|
|
1107
1275
|
# #33 / #34 — merge config file + named profile into args BEFORE any
|
|
1108
1276
|
# downstream code reads them. CLI args always win over file / profile
|
|
@@ -1481,6 +1649,25 @@ SUBCOMMAND_HELP: tuple[tuple[str, str], ...] = (
|
|
|
1481
1649
|
("mobile-api", "installable PWA + REST for phones (item #80)"),
|
|
1482
1650
|
# v2.6.0
|
|
1483
1651
|
("kev URL", "CISA KEV-only fast scan (item #67)"),
|
|
1652
|
+
# v2.7.0
|
|
1653
|
+
("compare-portfolios OLD NEW", "diff two sites.json portfolios (item #61)"),
|
|
1654
|
+
("changelog URL", "human-readable site-change log (--since DATE, item #63)"),
|
|
1655
|
+
("replay HAR.json", "browse a recorded HTTP Archive (item #64)"),
|
|
1656
|
+
("freeze URL", "snapshot a site as .tar.gz for offline compare (item #65)"),
|
|
1657
|
+
("attest URL", "Sigstore-signed scan attestation, --keyless (item #66)"),
|
|
1658
|
+
("compliance audit URL", "single-framework gap analysis, --framework F (item #68)"),
|
|
1659
|
+
("tournament URL A B", "bake-off two scan configs (item #62)"),
|
|
1660
|
+
("ai-agent URL", "AI-recommended follow-up probes (item #69)"),
|
|
1661
|
+
("triage interactive URL", "TUI walk-through of recent findings (item #70)"),
|
|
1662
|
+
("rotation N LIST", "split portfolio into N daily-bucket cron entries (item #71)"),
|
|
1663
|
+
("install-completion", "install shell completion to the right rc path (item #86)"),
|
|
1664
|
+
("replay-prompt URL", "TUI walking high-sev findings (item #85)"),
|
|
1665
|
+
("undo", "print the last config-mutating action + revert command (item #87)"),
|
|
1666
|
+
("worker", "Redis-queue distributed-scan worker (item #110)"),
|
|
1667
|
+
("learn", "interactive tutorial mode, no scan (item #116)"),
|
|
1668
|
+
("audio-summary URL", "TTS MP3 of the exec summary (item #118)"),
|
|
1669
|
+
("marketplace", "marketplace list/search/install/verify/stars/authors/leaderboard (L126-L130)"),
|
|
1670
|
+
("submit-cve SLUG CVE", "queue community CVE-DB contribution (L129)"),
|
|
1484
1671
|
)
|
|
1485
1672
|
|
|
1486
1673
|
SUBCOMMAND_NAMES: tuple[str, ...] = tuple(
|
|
@@ -1568,6 +1755,60 @@ def _dispatch_subcommand(cmd: str, args: list[str]) -> None:
|
|
|
1568
1755
|
_cmd_mobile_api(args)
|
|
1569
1756
|
elif cmd == "kev":
|
|
1570
1757
|
_cmd_kev(args)
|
|
1758
|
+
elif cmd == "compare-portfolios":
|
|
1759
|
+
from .workflow_cmds import cmd_compare_portfolios
|
|
1760
|
+
cmd_compare_portfolios(args)
|
|
1761
|
+
elif cmd == "changelog":
|
|
1762
|
+
from .workflow_cmds import cmd_changelog
|
|
1763
|
+
cmd_changelog(args)
|
|
1764
|
+
elif cmd == "replay":
|
|
1765
|
+
from .workflow_cmds import cmd_replay
|
|
1766
|
+
cmd_replay(args)
|
|
1767
|
+
elif cmd == "freeze":
|
|
1768
|
+
from .workflow_cmds import cmd_freeze
|
|
1769
|
+
cmd_freeze(args)
|
|
1770
|
+
elif cmd == "attest":
|
|
1771
|
+
from .workflow_cmds import cmd_attest
|
|
1772
|
+
cmd_attest(args)
|
|
1773
|
+
elif cmd == "compliance":
|
|
1774
|
+
from .workflow_cmds import cmd_compliance_audit
|
|
1775
|
+
cmd_compliance_audit(args)
|
|
1776
|
+
elif cmd == "tournament":
|
|
1777
|
+
from .workflow_cmds import cmd_tournament
|
|
1778
|
+
cmd_tournament(args)
|
|
1779
|
+
elif cmd == "ai-agent":
|
|
1780
|
+
from .workflow_cmds import cmd_ai_agent
|
|
1781
|
+
cmd_ai_agent(args)
|
|
1782
|
+
elif cmd == "triage":
|
|
1783
|
+
from .workflow_cmds import cmd_triage
|
|
1784
|
+
cmd_triage(args)
|
|
1785
|
+
elif cmd == "rotation":
|
|
1786
|
+
from .workflow_cmds import cmd_rotation
|
|
1787
|
+
cmd_rotation(args)
|
|
1788
|
+
elif cmd == "install-completion":
|
|
1789
|
+
from .cli_extras import cmd_install_completion
|
|
1790
|
+
cmd_install_completion(args)
|
|
1791
|
+
elif cmd == "replay-prompt":
|
|
1792
|
+
from .cli_extras import cmd_replay_prompt
|
|
1793
|
+
cmd_replay_prompt(args)
|
|
1794
|
+
elif cmd == "undo":
|
|
1795
|
+
from .cli_extras import cmd_undo
|
|
1796
|
+
cmd_undo(args)
|
|
1797
|
+
elif cmd == "worker":
|
|
1798
|
+
from .perf_v27 import cmd_worker
|
|
1799
|
+
cmd_worker(args)
|
|
1800
|
+
elif cmd == "learn":
|
|
1801
|
+
from .edu_v27 import cmd_learn
|
|
1802
|
+
cmd_learn(args)
|
|
1803
|
+
elif cmd == "audio-summary":
|
|
1804
|
+
from .edu_v27 import cmd_audio_summary
|
|
1805
|
+
cmd_audio_summary(args)
|
|
1806
|
+
elif cmd == "marketplace":
|
|
1807
|
+
from .marketplace_v27 import cmd_marketplace
|
|
1808
|
+
cmd_marketplace(args)
|
|
1809
|
+
elif cmd == "submit-cve":
|
|
1810
|
+
from .marketplace_v27 import cmd_submit_cve
|
|
1811
|
+
cmd_submit_cve(args)
|
|
1571
1812
|
else:
|
|
1572
1813
|
print(f"unknown subcommand: {cmd}", file=sys.stderr)
|
|
1573
1814
|
sys.exit(2)
|
|
@@ -210,6 +210,100 @@ def fix_pr_body(finding) -> str:
|
|
|
210
210
|
system=sys_msg, max_tokens=500)
|
|
211
211
|
|
|
212
212
|
|
|
213
|
+
def evidence_summary(finding) -> str:
|
|
214
|
+
"""G91 (v2.7.0) — one-sentence summary of finding.evidence.
|
|
215
|
+
|
|
216
|
+
For long evidence (raw JS-library version list etc.), produces a
|
|
217
|
+
summary line the reporter shows above the raw evidence.
|
|
218
|
+
"""
|
|
219
|
+
import os as _os
|
|
220
|
+
if _os.environ.get("WPSECSCAN_NO_AI") or not is_configured():
|
|
221
|
+
return ""
|
|
222
|
+
if not finding.evidence or len(finding.evidence) < 80:
|
|
223
|
+
return ""
|
|
224
|
+
sys_msg = (
|
|
225
|
+
"Summarise the following WPSecScan finding evidence in EXACTLY ONE "
|
|
226
|
+
"sentence (max 30 words). State the concrete observation; no "
|
|
227
|
+
"speculation. Output the sentence only — no preface."
|
|
228
|
+
)
|
|
229
|
+
return llm(finding.evidence[:2000], system=sys_msg, max_tokens=60).strip()
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def threat_model_js(js_bundle: str) -> str:
|
|
233
|
+
"""G92 (v2.7.0) — AI threat-model the given JS bundle."""
|
|
234
|
+
import os as _os
|
|
235
|
+
if _os.environ.get("WPSECSCAN_NO_AI") or not is_configured():
|
|
236
|
+
return ""
|
|
237
|
+
if not js_bundle:
|
|
238
|
+
return ""
|
|
239
|
+
sys_msg = (
|
|
240
|
+
"You are a defensive security engineer. Read the JS code below and "
|
|
241
|
+
"list every attack surface it EXPOSES to a remote attacker: API "
|
|
242
|
+
"endpoints, auth tokens in localStorage, innerHTML/eval usages, "
|
|
243
|
+
"third-party CDN/script-src dependencies. Bullet points, ranked by "
|
|
244
|
+
"severity. Max 250 words."
|
|
245
|
+
)
|
|
246
|
+
return llm(js_bundle[:8000], system=sys_msg, max_tokens=600)
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def answer_compliance_question(question: str, report_dict: dict) -> str:
|
|
250
|
+
"""G93 (v2.7.0) — answer a compliance question from the scan JSON."""
|
|
251
|
+
import json as _json
|
|
252
|
+
import os as _os
|
|
253
|
+
if _os.environ.get("WPSECSCAN_NO_AI") or not is_configured():
|
|
254
|
+
return ""
|
|
255
|
+
sys_msg = (
|
|
256
|
+
"You are a compliance auditor. Given a JSON wpsecscan scan report, "
|
|
257
|
+
"answer the question with a single Yes/No/Partial verdict, then a "
|
|
258
|
+
"one-paragraph rationale citing specific check_ids from the report. "
|
|
259
|
+
"If the report doesn't contain the relevant evidence, say so."
|
|
260
|
+
)
|
|
261
|
+
slim = {
|
|
262
|
+
"target": report_dict.get("target"),
|
|
263
|
+
"scanned_at": report_dict.get("scanned_at"),
|
|
264
|
+
"risk_score": report_dict.get("risk_score"),
|
|
265
|
+
"summary": report_dict.get("summary"),
|
|
266
|
+
"results": [{
|
|
267
|
+
"check_id": r.get("check_id"),
|
|
268
|
+
"findings": [{"severity": f.get("severity"), "title": f.get("title")}
|
|
269
|
+
for f in (r.get("findings") or [])],
|
|
270
|
+
} for r in (report_dict.get("results") or [])],
|
|
271
|
+
}
|
|
272
|
+
prompt = f"Report:\n{_json.dumps(slim, indent=2)[:8000]}\n\nQuestion: {question}"
|
|
273
|
+
return llm(prompt, system=sys_msg, max_tokens=400)
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def changelog_narrator(old_report: dict, new_report: dict) -> str:
|
|
277
|
+
"""G94 (v2.7.0) — natural-language summary of what changed between
|
|
278
|
+
two scan reports."""
|
|
279
|
+
import json as _json
|
|
280
|
+
import os as _os
|
|
281
|
+
if _os.environ.get("WPSECSCAN_NO_AI") or not is_configured():
|
|
282
|
+
return ""
|
|
283
|
+
sys_msg = (
|
|
284
|
+
"You are a security analyst. Write a SHORT (3-5 sentence) prose "
|
|
285
|
+
"summary of how this WordPress install changed between two "
|
|
286
|
+
"wpsecscan reports. Mention only NET-NEW issues, fixes, and "
|
|
287
|
+
"score deltas. Plain prose, no bullets, no tables."
|
|
288
|
+
)
|
|
289
|
+
def _slim(rep: dict) -> dict:
|
|
290
|
+
return {
|
|
291
|
+
"scanned_at": rep.get("scanned_at"),
|
|
292
|
+
"risk_score": rep.get("risk_score"),
|
|
293
|
+
"summary": rep.get("summary"),
|
|
294
|
+
"findings": [
|
|
295
|
+
(r.get("check_id"), f.get("severity"), f.get("title"))
|
|
296
|
+
for r in (rep.get("results") or [])
|
|
297
|
+
for f in (r.get("findings") or [])
|
|
298
|
+
],
|
|
299
|
+
}
|
|
300
|
+
prompt = (
|
|
301
|
+
"OLD:\n" + _json.dumps(_slim(old_report))[:3000] + "\n\n"
|
|
302
|
+
"NEW:\n" + _json.dumps(_slim(new_report))[:3000]
|
|
303
|
+
)
|
|
304
|
+
return llm(prompt, system=sys_msg, max_tokens=400)
|
|
305
|
+
|
|
306
|
+
|
|
213
307
|
def fix_pr_diff(finding) -> str:
|
|
214
308
|
"""G89 (v2.6.0) — draft a unified-diff patch alongside the PR body.
|
|
215
309
|
|
|
@@ -169,3 +169,52 @@ def write_script(report: ScanReport, path, *, repo: str, min_sev: str = "medium"
|
|
|
169
169
|
_act.emit("artifact", f"auto-PR script: {len(fixes)} fix(es) → {Path(path).name}")
|
|
170
170
|
except ImportError:
|
|
171
171
|
pass
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
# C50 (v2.7.0) — for one-liner fixes (.htaccess / wp-config.php / header.php),
|
|
175
|
+
# write a unified-diff patch alongside the shell script so the operator can
|
|
176
|
+
# `git apply` directly instead of pasting `gh` commands.
|
|
177
|
+
|
|
178
|
+
_ONE_LINER_HINT_FILES = ("wp-config.php", ".htaccess", "wp-content/themes/*/header.php",
|
|
179
|
+
"wp-content/themes/*/functions.php")
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def _looks_like_one_liner(finding) -> bool:
|
|
183
|
+
"""Heuristic: the remediation field references a single config file?"""
|
|
184
|
+
rem = (finding.remediation or "").lower()
|
|
185
|
+
return any(p.split("/")[-1].lower() in rem for p in _ONE_LINER_HINT_FILES)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def write_one_liner_patches(report: ScanReport, out_dir, *, min_sev: str = "medium") -> int:
|
|
189
|
+
"""C50 — for each one-liner-fixable finding, ask the AI to draft a
|
|
190
|
+
unified diff + write `<out_dir>/<check_id>-<idx>-fix.patch`. Returns
|
|
191
|
+
the count of patches written. No-op if no AI backend or no matches."""
|
|
192
|
+
from pathlib import Path
|
|
193
|
+
try:
|
|
194
|
+
from . import ai_assist as _ai
|
|
195
|
+
except ImportError:
|
|
196
|
+
return 0
|
|
197
|
+
if not _ai.is_configured():
|
|
198
|
+
return 0
|
|
199
|
+
out_dir = Path(out_dir)
|
|
200
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
201
|
+
sev_rank = {"info": 0, "low": 1, "medium": 2, "high": 3, "critical": 4}
|
|
202
|
+
min_n = sev_rank.get(min_sev, 2)
|
|
203
|
+
n = 0
|
|
204
|
+
for r in report.results:
|
|
205
|
+
for idx, f in enumerate(r.findings):
|
|
206
|
+
if sev_rank.get(f.severity, 0) < min_n:
|
|
207
|
+
continue
|
|
208
|
+
if not _looks_like_one_liner(f):
|
|
209
|
+
continue
|
|
210
|
+
diff = _ai.fix_pr_diff(f)
|
|
211
|
+
if not diff or len(diff) < 30:
|
|
212
|
+
continue
|
|
213
|
+
patch_path = out_dir / f"{r.check_id}-{idx}-fix.patch"
|
|
214
|
+
body_path = out_dir / f"{r.check_id}-{idx}-fix.md"
|
|
215
|
+
patch_path.write_text(diff + "\n", encoding="utf-8")
|
|
216
|
+
body = _ai.fix_pr_body(f)
|
|
217
|
+
if body:
|
|
218
|
+
body_path.write_text(body + "\n", encoding="utf-8")
|
|
219
|
+
n += 1
|
|
220
|
+
return n
|
|
@@ -296,6 +296,10 @@ from .rest_schema_field_leak import check as rest_schema_field_leak
|
|
|
296
296
|
from .block_style_variations_url import check as block_style_variations_url
|
|
297
297
|
from .companion_v13 import check as companion_v13
|
|
298
298
|
from .host_platform_detect import check as host_platform_detect
|
|
299
|
+
from .companion_v14 import check as companion_v14
|
|
300
|
+
from .trellis_yaml_audit import check as trellis_yaml_audit
|
|
301
|
+
from .headless_vercel_netlify_detect import check as headless_vercel_netlify_detect
|
|
302
|
+
from .perf_of_target import check as perf_of_target
|
|
299
303
|
|
|
300
304
|
# Authenticated — only when creds are provided
|
|
301
305
|
from .authenticated import check as authenticated
|
|
@@ -586,6 +590,10 @@ ALL_CHECKS = [
|
|
|
586
590
|
("block_style_variations_url","Block-style URL-prop SSRF (O145)", block_style_variations_url, False),
|
|
587
591
|
("companion_v13", "Companion v1.3 endpoint consumers (B36-B47)", companion_v13, False),
|
|
588
592
|
("host_platform_detect", "Host stack / platform fingerprint (N136/N139/N140)", host_platform_detect, False),
|
|
593
|
+
("companion_v14", "Companion v1.4 endpoint consumers (B38-B45)", companion_v14, False),
|
|
594
|
+
("trellis_yaml_audit", "Roots Trellis YAML exposure (N137)", trellis_yaml_audit, False),
|
|
595
|
+
("headless_vercel_netlify_detect", "Headless WP on Vercel/Netlify with reachable REST (N138)", headless_vercel_netlify_detect, False),
|
|
596
|
+
("perf_of_target", "Operational perf audit: TTFB / Lighthouse / DB-queries / cache-hit / cold-start (P146-P150)", perf_of_target, False),
|
|
589
597
|
# ---- Round-58 aggressive checks ----
|
|
590
598
|
("wp_query_sqli", "WP_Query/wpdb-specific SQLi (#4)", wp_query_sqli, True),
|
|
591
599
|
("http2_smuggling", "HTTP/2 CRLF smuggling probe (#24)", http2_smuggling, True),
|