haris 0.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.
- haris-0.7.0/LICENSE +21 -0
- haris-0.7.0/PKG-INFO +253 -0
- haris-0.7.0/README.md +212 -0
- haris-0.7.0/pyproject.toml +138 -0
- haris-0.7.0/setup.cfg +4 -0
- haris-0.7.0/src/haris/__init__.py +6 -0
- haris-0.7.0/src/haris/__main__.py +5 -0
- haris-0.7.0/src/haris/agent/__init__.py +21 -0
- haris-0.7.0/src/haris/agent/audit.py +67 -0
- haris-0.7.0/src/haris/agent/budget.py +52 -0
- haris-0.7.0/src/haris/agent/coordinator.py +253 -0
- haris-0.7.0/src/haris/agent/docker_runtime.py +403 -0
- haris-0.7.0/src/haris/agent/guardrails.py +176 -0
- haris-0.7.0/src/haris/agent/models.py +43 -0
- haris-0.7.0/src/haris/agent/policy.py +127 -0
- haris-0.7.0/src/haris/agent/prompts.py +17 -0
- haris-0.7.0/src/haris/agent/proxy.py +309 -0
- haris-0.7.0/src/haris/agent/proxy_auth.py +26 -0
- haris-0.7.0/src/haris/agent/runtime.py +133 -0
- haris-0.7.0/src/haris/agent/settings.py +45 -0
- haris-0.7.0/src/haris/agent/stages.py +5 -0
- haris-0.7.0/src/haris/agent/turn.py +118 -0
- haris-0.7.0/src/haris/agent/validator.py +121 -0
- haris-0.7.0/src/haris/ai_security/__init__.py +3 -0
- haris-0.7.0/src/haris/ai_security/active.py +294 -0
- haris-0.7.0/src/haris/ai_security/adapters.py +151 -0
- haris-0.7.0/src/haris/ai_security/body_validators.py +174 -0
- haris-0.7.0/src/haris/ai_security/bundles.py +47 -0
- haris-0.7.0/src/haris/ai_security/discovery.py +94 -0
- haris-0.7.0/src/haris/ai_security/findings.py +81 -0
- haris-0.7.0/src/haris/ai_security/mcp_probe.py +133 -0
- haris-0.7.0/src/haris/ai_security/mcp_static.py +169 -0
- haris-0.7.0/src/haris/ai_security/options.py +37 -0
- haris-0.7.0/src/haris/ai_security/owasp_ai.py +86 -0
- haris-0.7.0/src/haris/ai_security/passive.py +275 -0
- haris-0.7.0/src/haris/ai_security/probes.py +82 -0
- haris-0.7.0/src/haris/ai_security/rpc.py +64 -0
- haris-0.7.0/src/haris/ai_security/scanner.py +70 -0
- haris-0.7.0/src/haris/ai_security/signatures.py +67 -0
- haris-0.7.0/src/haris/auth/__init__.py +0 -0
- haris-0.7.0/src/haris/auth/api_tokens.py +63 -0
- haris-0.7.0/src/haris/auth/audit.py +54 -0
- haris-0.7.0/src/haris/auth/bearer.py +57 -0
- haris-0.7.0/src/haris/auth/bootstrap.py +37 -0
- haris-0.7.0/src/haris/auth/config.py +87 -0
- haris-0.7.0/src/haris/auth/cookies.py +47 -0
- haris-0.7.0/src/haris/auth/csrf.py +65 -0
- haris-0.7.0/src/haris/auth/database.py +49 -0
- haris-0.7.0/src/haris/auth/email.py +100 -0
- haris-0.7.0/src/haris/auth/middleware.py +75 -0
- haris-0.7.0/src/haris/auth/models.py +104 -0
- haris-0.7.0/src/haris/auth/oidc.py +115 -0
- haris-0.7.0/src/haris/auth/public.py +16 -0
- haris-0.7.0/src/haris/auth/redirects.py +38 -0
- haris-0.7.0/src/haris/auth/security_headers.py +72 -0
- haris-0.7.0/src/haris/auth/service.py +276 -0
- haris-0.7.0/src/haris/auth/tokens.py +5 -0
- haris-0.7.0/src/haris/auth/users.py +167 -0
- haris-0.7.0/src/haris/auth/verification.py +94 -0
- haris-0.7.0/src/haris/bench/__init__.py +0 -0
- haris-0.7.0/src/haris/bench/__main__.py +49 -0
- haris-0.7.0/src/haris/bench/render.py +34 -0
- haris-0.7.0/src/haris/bench/score.py +205 -0
- haris-0.7.0/src/haris/bench/truth.py +87 -0
- haris-0.7.0/src/haris/checks/__init__.py +35 -0
- haris-0.7.0/src/haris/checks/baseline.py +243 -0
- haris-0.7.0/src/haris/checks/cache_checks.py +67 -0
- haris-0.7.0/src/haris/checks/cookie_checks.py +259 -0
- haris-0.7.0/src/haris/checks/cookie_policy.py +79 -0
- haris-0.7.0/src/haris/checks/dns_checks.py +164 -0
- haris-0.7.0/src/haris/checks/dns_wire.py +123 -0
- haris-0.7.0/src/haris/checks/findings.py +30 -0
- haris-0.7.0/src/haris/checks/graphql_checks.py +82 -0
- haris-0.7.0/src/haris/checks/header_checks.py +231 -0
- haris-0.7.0/src/haris/checks/header_policy.py +175 -0
- haris-0.7.0/src/haris/checks/info_disclosure.py +229 -0
- haris-0.7.0/src/haris/checks/info_patterns.py +142 -0
- haris-0.7.0/src/haris/checks/listing_checks.py +75 -0
- haris-0.7.0/src/haris/checks/method_checks.py +76 -0
- haris-0.7.0/src/haris/checks/misc_checks.py +239 -0
- haris-0.7.0/src/haris/checks/openapi_checks.py +67 -0
- haris-0.7.0/src/haris/checks/path_probe.py +50 -0
- haris-0.7.0/src/haris/checks/probe_scanner.py +26 -0
- haris-0.7.0/src/haris/checks/redirect_checks.py +80 -0
- haris-0.7.0/src/haris/checks/requesting.py +66 -0
- haris-0.7.0/src/haris/checks/sri_checks.py +87 -0
- haris-0.7.0/src/haris/checks/tls_checks.py +218 -0
- haris-0.7.0/src/haris/checks/tls_probe.py +150 -0
- haris-0.7.0/src/haris/checks/validators.py +173 -0
- haris-0.7.0/src/haris/cli.py +648 -0
- haris-0.7.0/src/haris/config/__init__.py +6 -0
- haris-0.7.0/src/haris/config/loader.py +201 -0
- haris-0.7.0/src/haris/config/paths.py +14 -0
- haris-0.7.0/src/haris/core/__init__.py +71 -0
- haris-0.7.0/src/haris/core/confidence.py +76 -0
- haris-0.7.0/src/haris/core/context_extract.py +89 -0
- haris-0.7.0/src/haris/core/correlator.py +64 -0
- haris-0.7.0/src/haris/core/decorators.py +105 -0
- haris-0.7.0/src/haris/core/engine.py +378 -0
- haris-0.7.0/src/haris/core/exit_codes.py +24 -0
- haris-0.7.0/src/haris/core/identity.py +93 -0
- haris-0.7.0/src/haris/core/llm_enrichment.py +83 -0
- haris-0.7.0/src/haris/core/owasp.py +222 -0
- haris-0.7.0/src/haris/core/profiles.py +193 -0
- haris-0.7.0/src/haris/core/remediation.py +119 -0
- haris-0.7.0/src/haris/core/risk.py +221 -0
- haris-0.7.0/src/haris/core/runner.py +218 -0
- haris-0.7.0/src/haris/core/scanner.py +141 -0
- haris-0.7.0/src/haris/core/tool_vet.py +35 -0
- haris-0.7.0/src/haris/core/vuln_class.py +66 -0
- haris-0.7.0/src/haris/data/__init__.py +1 -0
- haris-0.7.0/src/haris/data/scanner_config.py +305 -0
- haris-0.7.0/src/haris/db/__init__.py +5 -0
- haris-0.7.0/src/haris/db/api_tokens.py +86 -0
- haris-0.7.0/src/haris/db/baseline.py +236 -0
- haris-0.7.0/src/haris/db/connection.py +22 -0
- haris-0.7.0/src/haris/db/findings.py +48 -0
- haris-0.7.0/src/haris/db/jobs.py +166 -0
- haris-0.7.0/src/haris/db/llm_data.py +119 -0
- haris-0.7.0/src/haris/db/migrate.py +70 -0
- haris-0.7.0/src/haris/db/migrations/0001_baseline.py +5 -0
- haris-0.7.0/src/haris/db/migrations/0002_hash_tokens.py +21 -0
- haris-0.7.0/src/haris/db/migrations/0003_finding_identity.py +77 -0
- haris-0.7.0/src/haris/db/migrations/0004_scan_owner_state.py +33 -0
- haris-0.7.0/src/haris/db/migrations/0005_api_tokens.py +30 -0
- haris-0.7.0/src/haris/db/migrations/0006_authorized_targets.py +26 -0
- haris-0.7.0/src/haris/db/migrations/0007_job_queue.py +29 -0
- haris-0.7.0/src/haris/db/migrations/0008_agent_fields.py +20 -0
- haris-0.7.0/src/haris/db/scans.py +162 -0
- haris-0.7.0/src/haris/db/session_read.py +180 -0
- haris-0.7.0/src/haris/db/session_write.py +163 -0
- haris-0.7.0/src/haris/db/store.py +149 -0
- haris-0.7.0/src/haris/db/targets.py +73 -0
- haris-0.7.0/src/haris/db/template_defaults.py +144 -0
- haris-0.7.0/src/haris/db/templates.py +157 -0
- haris-0.7.0/src/haris/db/websites.py +194 -0
- haris-0.7.0/src/haris/diff.py +154 -0
- haris-0.7.0/src/haris/ignore.py +111 -0
- haris-0.7.0/src/haris/llm/__init__.py +28 -0
- haris-0.7.0/src/haris/llm/backend.py +239 -0
- haris-0.7.0/src/haris/llm/base.py +88 -0
- haris-0.7.0/src/haris/llm/budget.py +106 -0
- haris-0.7.0/src/haris/llm/catalog.py +86 -0
- haris-0.7.0/src/haris/llm/correlation.py +77 -0
- haris-0.7.0/src/haris/llm/enrichment.py +117 -0
- haris-0.7.0/src/haris/llm/enrichment_prompts.py +86 -0
- haris-0.7.0/src/haris/llm/parsing.py +84 -0
- haris-0.7.0/src/haris/llm/prompts.py +253 -0
- haris-0.7.0/src/haris/llm/providers.py +221 -0
- haris-0.7.0/src/haris/llm/qa.py +249 -0
- haris-0.7.0/src/haris/llm/redaction.py +75 -0
- haris-0.7.0/src/haris/llm/retriever.py +113 -0
- haris-0.7.0/src/haris/llm/retry.py +92 -0
- haris-0.7.0/src/haris/llm/router.py +70 -0
- haris-0.7.0/src/haris/llm/schemas.py +91 -0
- haris-0.7.0/src/haris/llm/settings.py +98 -0
- haris-0.7.0/src/haris/llm/structured.py +117 -0
- haris-0.7.0/src/haris/llm/template_loader.py +47 -0
- haris-0.7.0/src/haris/llm/templates/enrichment/assess_false_positives.j2 +22 -0
- haris-0.7.0/src/haris/llm/templates/enrichment/enrich_finding.j2 +33 -0
- haris-0.7.0/src/haris/llm/templates/enrichment/identify_attack_chains.j2 +23 -0
- haris-0.7.0/src/haris/llm/templates/enrichment/suggest_variants.j2 +26 -0
- haris-0.7.0/src/haris/llm/templates/enrichment/system.j2 +7 -0
- haris-0.7.0/src/haris/llm/templates/enrichment/triage_findings.j2 +24 -0
- haris-0.7.0/src/haris/llm/templates/qa/explain_finding.j2 +12 -0
- haris-0.7.0/src/haris/llm/templates/qa/filter_and_explain.j2 +12 -0
- haris-0.7.0/src/haris/llm/templates/qa/freeform_question.j2 +6 -0
- haris-0.7.0/src/haris/llm/templates/qa/generate_test_cases.j2 +12 -0
- haris-0.7.0/src/haris/llm/templates/qa/remediation_plan.j2 +4 -0
- haris-0.7.0/src/haris/llm/templates/qa/suggest_mitigations.j2 +12 -0
- haris-0.7.0/src/haris/llm/templates/qa/summarize_report.j2 +4 -0
- haris-0.7.0/src/haris/llm/templates/qa/system.j2 +8 -0
- haris-0.7.0/src/haris/llm/triage.py +97 -0
- haris-0.7.0/src/haris/llm/variant_analysis.py +76 -0
- haris-0.7.0/src/haris/models/__init__.py +89 -0
- haris-0.7.0/src/haris/models/chat.py +41 -0
- haris-0.7.0/src/haris/models/config.py +62 -0
- haris-0.7.0/src/haris/models/correlator.py +25 -0
- haris-0.7.0/src/haris/models/enrichment.py +69 -0
- haris-0.7.0/src/haris/models/enums.py +131 -0
- haris-0.7.0/src/haris/models/finding.py +131 -0
- haris-0.7.0/src/haris/models/llm.py +18 -0
- haris-0.7.0/src/haris/models/owasp.py +67 -0
- haris-0.7.0/src/haris/models/profiles.py +18 -0
- haris-0.7.0/src/haris/models/remediation.py +36 -0
- haris-0.7.0/src/haris/models/risk.py +12 -0
- haris-0.7.0/src/haris/models/scan_config_template.py +60 -0
- haris-0.7.0/src/haris/models/scan_context.py +63 -0
- haris-0.7.0/src/haris/models/scanner.py +21 -0
- haris-0.7.0/src/haris/models/session.py +121 -0
- haris-0.7.0/src/haris/models/target.py +230 -0
- haris-0.7.0/src/haris/models/templates.py +82 -0
- haris-0.7.0/src/haris/models/verification.py +69 -0
- haris-0.7.0/src/haris/net/__init__.py +26 -0
- haris-0.7.0/src/haris/net/errors.py +18 -0
- haris-0.7.0/src/haris/net/policy.py +22 -0
- haris-0.7.0/src/haris/net/ratelimit.py +53 -0
- haris-0.7.0/src/haris/net/redact.py +16 -0
- haris-0.7.0/src/haris/net/requestlog.py +76 -0
- haris-0.7.0/src/haris/net/retry.py +20 -0
- haris-0.7.0/src/haris/net/scoped_client.py +348 -0
- haris-0.7.0/src/haris/net/ssrf.py +86 -0
- haris-0.7.0/src/haris/net/transport.py +108 -0
- haris-0.7.0/src/haris/reporting/__init__.py +65 -0
- haris-0.7.0/src/haris/reporting/base.py +28 -0
- haris-0.7.0/src/haris/reporting/csv_report.py +59 -0
- haris-0.7.0/src/haris/reporting/escape.py +43 -0
- haris-0.7.0/src/haris/reporting/findings.py +33 -0
- haris-0.7.0/src/haris/reporting/html_report.py +126 -0
- haris-0.7.0/src/haris/reporting/json_report.py +48 -0
- haris-0.7.0/src/haris/reporting/junit_report.py +62 -0
- haris-0.7.0/src/haris/reporting/markdown_report.py +236 -0
- haris-0.7.0/src/haris/reporting/report_schema.py +92 -0
- haris-0.7.0/src/haris/reporting/sarif_report.py +192 -0
- haris-0.7.0/src/haris/resources/__init__.py +0 -0
- haris-0.7.0/src/haris/resources/config/agent.yaml +24 -0
- haris-0.7.0/src/haris/resources/config/ai_mappings.yaml +221 -0
- haris-0.7.0/src/haris/resources/config/ai_probes.yaml +47 -0
- haris-0.7.0/src/haris/resources/config/ai_signatures.yaml +168 -0
- haris-0.7.0/src/haris/resources/config/confidence.yaml +73 -0
- haris-0.7.0/src/haris/resources/config/default_config.yaml +159 -0
- haris-0.7.0/src/haris/resources/config/llm_models.yaml +68 -0
- haris-0.7.0/src/haris/resources/config/scanner_data.yaml +43 -0
- haris-0.7.0/src/haris/resources/config/scanners/garak.yaml +14 -0
- haris-0.7.0/src/haris/resources/config/scanners/nikto.yaml +116 -0
- haris-0.7.0/src/haris/resources/config/scanners/nmap.yaml +48 -0
- haris-0.7.0/src/haris/resources/config/scanners/nuclei.yaml +361 -0
- haris-0.7.0/src/haris/resources/config/scanners/promptfoo.yaml +23 -0
- haris-0.7.0/src/haris/resources/config/scanners/sslyze.yaml +64 -0
- haris-0.7.0/src/haris/resources/config/scanners/wapiti.yaml +83 -0
- haris-0.7.0/src/haris/resources/config/scanners/zap.yaml +22 -0
- haris-0.7.0/src/haris/resources/config/verify.yaml +56 -0
- haris-0.7.0/src/haris/resources/config/vuln_classes.yaml +356 -0
- haris-0.7.0/src/haris/resources/schema/report.schema.json +670 -0
- haris-0.7.0/src/haris/scan_files.py +30 -0
- haris-0.7.0/src/haris/scanners/__init__.py +44 -0
- haris-0.7.0/src/haris/scanners/argv_policy.py +47 -0
- haris-0.7.0/src/haris/scanners/base.py +76 -0
- haris-0.7.0/src/haris/scanners/garak_scanner.py +183 -0
- haris-0.7.0/src/haris/scanners/nikto_scanner.py +258 -0
- haris-0.7.0/src/haris/scanners/nmap_scanner.py +261 -0
- haris-0.7.0/src/haris/scanners/nuclei_results.py +239 -0
- haris-0.7.0/src/haris/scanners/nuclei_scanner.py +470 -0
- haris-0.7.0/src/haris/scanners/nuclei_templates.py +26 -0
- haris-0.7.0/src/haris/scanners/nuclei_urls.py +55 -0
- haris-0.7.0/src/haris/scanners/option_policy.py +242 -0
- haris-0.7.0/src/haris/scanners/option_values.py +74 -0
- haris-0.7.0/src/haris/scanners/process.py +60 -0
- haris-0.7.0/src/haris/scanners/promptfoo_scanner.py +247 -0
- haris-0.7.0/src/haris/scanners/redaction.py +57 -0
- haris-0.7.0/src/haris/scanners/sslyze_scanner.py +244 -0
- haris-0.7.0/src/haris/scanners/wapiti_exclude.py +27 -0
- haris-0.7.0/src/haris/scanners/wapiti_scanner.py +264 -0
- haris-0.7.0/src/haris/scanners/wapiti_session.py +104 -0
- haris-0.7.0/src/haris/scanners/zap_plan.py +155 -0
- haris-0.7.0/src/haris/scanners/zap_scanner.py +244 -0
- haris-0.7.0/src/haris/templates/__init__.py +9 -0
- haris-0.7.0/src/haris/templates/adapters.py +336 -0
- haris-0.7.0/src/haris/templates/manager.py +174 -0
- haris-0.7.0/src/haris/templates/report.py +49 -0
- haris-0.7.0/src/haris/templates/updater.py +201 -0
- haris-0.7.0/src/haris/verify/__init__.py +15 -0
- haris-0.7.0/src/haris/verify/evidence.py +41 -0
- haris-0.7.0/src/haris/verify/llm_verdict.py +148 -0
- haris-0.7.0/src/haris/verify/oracles.py +150 -0
- haris-0.7.0/src/haris/verify/oracles_baseline.py +54 -0
- haris-0.7.0/src/haris/verify/pipeline.py +66 -0
- haris-0.7.0/src/haris/verify/probe.py +88 -0
- haris-0.7.0/src/haris/verify/replay.py +142 -0
- haris-0.7.0/src/haris/verify/settings.py +71 -0
- haris-0.7.0/src/haris/verify/timing.py +63 -0
- haris-0.7.0/src/haris/verify/verdict_prompt.py +72 -0
- haris-0.7.0/src/haris/web/__init__.py +1 -0
- haris-0.7.0/src/haris/web/access.py +64 -0
- haris-0.7.0/src/haris/web/agent_gate.py +158 -0
- haris-0.7.0/src/haris/web/app.py +108 -0
- haris-0.7.0/src/haris/web/conversations.py +51 -0
- haris-0.7.0/src/haris/web/job_queue.py +148 -0
- haris-0.7.0/src/haris/web/llm_support.py +43 -0
- haris-0.7.0/src/haris/web/logging_setup.py +23 -0
- haris-0.7.0/src/haris/web/page_data.py +19 -0
- haris-0.7.0/src/haris/web/routers/__init__.py +43 -0
- haris-0.7.0/src/haris/web/routers/account.py +88 -0
- haris-0.7.0/src/haris/web/routers/admin.py +153 -0
- haris-0.7.0/src/haris/web/routers/admin_api.py +15 -0
- haris-0.7.0/src/haris/web/routers/auth_login.py +309 -0
- haris-0.7.0/src/haris/web/routers/health.py +8 -0
- haris-0.7.0/src/haris/web/routers/llm_chat.py +159 -0
- haris-0.7.0/src/haris/web/routers/llm_scan.py +96 -0
- haris-0.7.0/src/haris/web/routers/oidc.py +76 -0
- haris-0.7.0/src/haris/web/routers/pages.py +146 -0
- haris-0.7.0/src/haris/web/routers/scan_data.py +92 -0
- haris-0.7.0/src/haris/web/routers/scan_templates.py +106 -0
- haris-0.7.0/src/haris/web/routers/scans.py +93 -0
- haris-0.7.0/src/haris/web/routers/scans_api.py +334 -0
- haris-0.7.0/src/haris/web/routers/targets.py +85 -0
- haris-0.7.0/src/haris/web/routers/templates_api.py +226 -0
- haris-0.7.0/src/haris/web/routers/tokens.py +78 -0
- haris-0.7.0/src/haris/web/routers/websites.py +58 -0
- haris-0.7.0/src/haris/web/routers/websites_api.py +50 -0
- haris-0.7.0/src/haris/web/routing.py +80 -0
- haris-0.7.0/src/haris/web/scan_runtime.py +169 -0
- haris-0.7.0/src/haris/web/scanner_info.py +32 -0
- haris-0.7.0/src/haris/web/schemas/__init__.py +0 -0
- haris-0.7.0/src/haris/web/schemas/access.py +46 -0
- haris-0.7.0/src/haris/web/schemas/llm.py +99 -0
- haris-0.7.0/src/haris/web/schemas/scans.py +58 -0
- haris-0.7.0/src/haris/web/schemas/sites.py +77 -0
- haris-0.7.0/src/haris/web/settings.py +46 -0
- haris-0.7.0/src/haris/web/state.py +40 -0
- haris-0.7.0/src/haris/web/static/css/findings.css +248 -0
- haris-0.7.0/src/haris/web/static/css/fonts.css +28 -0
- haris-0.7.0/src/haris/web/static/css/layout.css +241 -0
- haris-0.7.0/src/haris/web/static/css/pages.css +220 -0
- haris-0.7.0/src/haris/web/static/css/template_form.css +54 -0
- haris-0.7.0/src/haris/web/static/favicon.svg +4 -0
- haris-0.7.0/src/haris/web/static/haris_logo.png +0 -0
- haris-0.7.0/src/haris/web/static/js/dashboard.js +12 -0
- haris-0.7.0/src/haris/web/static/js/login.js +4 -0
- haris-0.7.0/src/haris/web/static/js/password_form.js +25 -0
- haris-0.7.0/src/haris/web/static/js/profile.js +16 -0
- haris-0.7.0/src/haris/web/static/js/reload.js +1 -0
- haris-0.7.0/src/haris/web/static/js/scan_detail.js +161 -0
- haris-0.7.0/src/haris/web/static/js/scan_new.js +97 -0
- haris-0.7.0/src/haris/web/static/js/scans.js +8 -0
- haris-0.7.0/src/haris/web/static/js/template_form.js +303 -0
- haris-0.7.0/src/haris/web/static/js/templates_page.js +102 -0
- haris-0.7.0/src/haris/web/static/js/users.js +44 -0
- haris-0.7.0/src/haris/web/static/js/website_detail.js +98 -0
- haris-0.7.0/src/haris/web/static/main.js +135 -0
- haris-0.7.0/src/haris/web/static/style.css +335 -0
- haris-0.7.0/src/haris/web/static/theme-init.js +4 -0
- haris-0.7.0/src/haris/web/static/vendor/LICENSE.chartjs +9 -0
- haris-0.7.0/src/haris/web/static/vendor/LICENSE.dompurify +202 -0
- haris-0.7.0/src/haris/web/static/vendor/LICENSE.htmx +13 -0
- haris-0.7.0/src/haris/web/static/vendor/LICENSE.inter +93 -0
- haris-0.7.0/src/haris/web/static/vendor/LICENSE.marked +44 -0
- haris-0.7.0/src/haris/web/static/vendor/README +32 -0
- haris-0.7.0/src/haris/web/static/vendor/chart.umd.min.js +14 -0
- haris-0.7.0/src/haris/web/static/vendor/fonts/inter-latin-400-normal.woff2 +0 -0
- haris-0.7.0/src/haris/web/static/vendor/fonts/inter-latin-500-normal.woff2 +0 -0
- haris-0.7.0/src/haris/web/static/vendor/fonts/inter-latin-600-normal.woff2 +0 -0
- haris-0.7.0/src/haris/web/static/vendor/fonts/inter-latin-700-normal.woff2 +0 -0
- haris-0.7.0/src/haris/web/static/vendor/htmx.min.js +1 -0
- haris-0.7.0/src/haris/web/static/vendor/marked.umd.js +86 -0
- haris-0.7.0/src/haris/web/static/vendor/purify.min.js +7 -0
- haris-0.7.0/src/haris/web/targets.py +190 -0
- haris-0.7.0/src/haris/web/templates/_scan_rows.html +43 -0
- haris-0.7.0/src/haris/web/templates/auth/audit_log.html +107 -0
- haris-0.7.0/src/haris/web/templates/auth/login.html +101 -0
- haris-0.7.0/src/haris/web/templates/auth/profile.html +165 -0
- haris-0.7.0/src/haris/web/templates/auth/register.html +85 -0
- haris-0.7.0/src/haris/web/templates/auth/setup.html +88 -0
- haris-0.7.0/src/haris/web/templates/auth/users.html +155 -0
- haris-0.7.0/src/haris/web/templates/auth/verify_email.html +54 -0
- haris-0.7.0/src/haris/web/templates/base.html +121 -0
- haris-0.7.0/src/haris/web/templates/dashboard.html +113 -0
- haris-0.7.0/src/haris/web/templates/licenses.html +82 -0
- haris-0.7.0/src/haris/web/templates/partials/scan_ai_insights.html +82 -0
- haris-0.7.0/src/haris/web/templates/partials/template_form_scanners_b.html +198 -0
- haris-0.7.0/src/haris/web/templates/scan_detail.html +332 -0
- haris-0.7.0/src/haris/web/templates/scan_new.html +147 -0
- haris-0.7.0/src/haris/web/templates/scans.html +89 -0
- haris-0.7.0/src/haris/web/templates/settings.html +54 -0
- haris-0.7.0/src/haris/web/templates/template_form.html +321 -0
- haris-0.7.0/src/haris/web/templates/templates.html +190 -0
- haris-0.7.0/src/haris/web/templates/website_detail.html +111 -0
- haris-0.7.0/src/haris/web/templates/websites.html +42 -0
- haris-0.7.0/src/haris/web/templating.py +38 -0
- haris-0.7.0/src/haris.egg-info/PKG-INFO +253 -0
- haris-0.7.0/src/haris.egg-info/SOURCES.txt +503 -0
- haris-0.7.0/src/haris.egg-info/dependency_links.txt +1 -0
- haris-0.7.0/src/haris.egg-info/entry_points.txt +2 -0
- haris-0.7.0/src/haris.egg-info/requires.txt +24 -0
- haris-0.7.0/src/haris.egg-info/top_level.txt +1 -0
- haris-0.7.0/tests/test_agent_budget.py +183 -0
- haris-0.7.0/tests/test_agent_docker.py +191 -0
- haris-0.7.0/tests/test_agent_fields.py +102 -0
- haris-0.7.0/tests/test_agent_guardrails.py +137 -0
- haris-0.7.0/tests/test_agent_injection.py +110 -0
- haris-0.7.0/tests/test_agent_policy.py +153 -0
- haris-0.7.0/tests/test_agent_post_reexec.py +277 -0
- haris-0.7.0/tests/test_agent_proxy.py +245 -0
- haris-0.7.0/tests/test_agent_runtime.py +60 -0
- haris-0.7.0/tests/test_agent_sandbox_probe.py +48 -0
- haris-0.7.0/tests/test_agent_stage.py +89 -0
- haris-0.7.0/tests/test_agent_tunnel.py +44 -0
- haris-0.7.0/tests/test_agent_validator.py +208 -0
- haris-0.7.0/tests/test_ai_active.py +325 -0
- haris-0.7.0/tests/test_ai_adapter_gate.py +46 -0
- haris-0.7.0/tests/test_ai_adapter_preflight.py +157 -0
- haris-0.7.0/tests/test_ai_classes.py +33 -0
- haris-0.7.0/tests/test_ai_cli.py +79 -0
- haris-0.7.0/tests/test_ai_discovery.py +127 -0
- haris-0.7.0/tests/test_ai_garak.py +169 -0
- haris-0.7.0/tests/test_ai_mcp.py +245 -0
- haris-0.7.0/tests/test_ai_owasp.py +131 -0
- haris-0.7.0/tests/test_ai_passive.py +197 -0
- haris-0.7.0/tests/test_ai_promptfoo.py +199 -0
- haris-0.7.0/tests/test_ai_sse.py +48 -0
- haris-0.7.0/tests/test_auth_email.py +350 -0
- haris-0.7.0/tests/test_auth_fixes.py +181 -0
- haris-0.7.0/tests/test_auth_oidc.py +186 -0
- haris-0.7.0/tests/test_auth_service.py +570 -0
- haris-0.7.0/tests/test_bench_callback.py +213 -0
- haris-0.7.0/tests/test_bench_fixtures.py +175 -0
- haris-0.7.0/tests/test_bench_ground_truth.py +146 -0
- haris-0.7.0/tests/test_bench_login.py +283 -0
- haris-0.7.0/tests/test_bench_run.py +227 -0
- haris-0.7.0/tests/test_bench_scanner_args.py +113 -0
- haris-0.7.0/tests/test_bench_score.py +418 -0
- haris-0.7.0/tests/test_chat.py +163 -0
- haris-0.7.0/tests/test_checks_baseline.py +252 -0
- haris-0.7.0/tests/test_checks_cookies.py +187 -0
- haris-0.7.0/tests/test_checks_dns.py +145 -0
- haris-0.7.0/tests/test_checks_exposure.py +151 -0
- haris-0.7.0/tests/test_checks_headers.py +205 -0
- haris-0.7.0/tests/test_checks_info.py +173 -0
- haris-0.7.0/tests/test_checks_probes.py +229 -0
- haris-0.7.0/tests/test_checks_registry.py +43 -0
- haris-0.7.0/tests/test_checks_tls.py +128 -0
- haris-0.7.0/tests/test_cli_exit.py +146 -0
- haris-0.7.0/tests/test_cli_web.py +24 -0
- haris-0.7.0/tests/test_config_paths.py +24 -0
- haris-0.7.0/tests/test_config_scope.py +14 -0
- haris-0.7.0/tests/test_correlator.py +146 -0
- haris-0.7.0/tests/test_db.py +333 -0
- haris-0.7.0/tests/test_db_identity.py +160 -0
- haris-0.7.0/tests/test_db_jobs.py +68 -0
- haris-0.7.0/tests/test_db_ownership.py +104 -0
- haris-0.7.0/tests/test_db_rollback.py +69 -0
- haris-0.7.0/tests/test_db_scope.py +96 -0
- haris-0.7.0/tests/test_docker_exec.py +149 -0
- haris-0.7.0/tests/test_engine.py +453 -0
- haris-0.7.0/tests/test_engine_pipeline.py +293 -0
- haris-0.7.0/tests/test_enrichment.py +344 -0
- haris-0.7.0/tests/test_excluded_paths_syntax.py +55 -0
- haris-0.7.0/tests/test_finding.py +189 -0
- haris-0.7.0/tests/test_identity.py +177 -0
- haris-0.7.0/tests/test_ignore_diff.py +252 -0
- haris-0.7.0/tests/test_l6_jsonrpc.py +8 -0
- haris-0.7.0/tests/test_llm.py +238 -0
- haris-0.7.0/tests/test_llm_budget.py +155 -0
- haris-0.7.0/tests/test_llm_catalog.py +160 -0
- haris-0.7.0/tests/test_llm_injection.py +142 -0
- haris-0.7.0/tests/test_llm_parsing.py +93 -0
- haris-0.7.0/tests/test_llm_redaction.py +98 -0
- haris-0.7.0/tests/test_llm_retry.py +97 -0
- haris-0.7.0/tests/test_migrations.py +148 -0
- haris-0.7.0/tests/test_nuclei_phases.py +319 -0
- haris-0.7.0/tests/test_nuclei_scanner.py +844 -0
- haris-0.7.0/tests/test_option_policy.py +159 -0
- haris-0.7.0/tests/test_owasp.py +72 -0
- haris-0.7.0/tests/test_profiles.py +40 -0
- haris-0.7.0/tests/test_ratelimit.py +50 -0
- haris-0.7.0/tests/test_remediation.py +101 -0
- haris-0.7.0/tests/test_report_escape.py +132 -0
- haris-0.7.0/tests/test_report_integrations.py +23 -0
- haris-0.7.0/tests/test_report_sarif.py +97 -0
- haris-0.7.0/tests/test_report_schema.py +73 -0
- haris-0.7.0/tests/test_report_tabular.py +75 -0
- haris-0.7.0/tests/test_reporting.py +165 -0
- haris-0.7.0/tests/test_retriever.py +360 -0
- haris-0.7.0/tests/test_risk.py +104 -0
- haris-0.7.0/tests/test_router.py +170 -0
- haris-0.7.0/tests/test_runner.py +194 -0
- haris-0.7.0/tests/test_scan_config_templates.py +613 -0
- haris-0.7.0/tests/test_scan_context.py +106 -0
- haris-0.7.0/tests/test_scanner_config.py +66 -0
- haris-0.7.0/tests/test_scanner_golden.py +367 -0
- haris-0.7.0/tests/test_scanner_runtime.py +250 -0
- haris-0.7.0/tests/test_schema_v6.py +225 -0
- haris-0.7.0/tests/test_scoped_client.py +362 -0
- haris-0.7.0/tests/test_scoped_stream.py +197 -0
- haris-0.7.0/tests/test_session_revoke.py +32 -0
- haris-0.7.0/tests/test_ssrf.py +151 -0
- haris-0.7.0/tests/test_target.py +174 -0
- haris-0.7.0/tests/test_templates.py +543 -0
- haris-0.7.0/tests/test_tool_vet.py +67 -0
- haris-0.7.0/tests/test_verify_baseline_oracles.py +249 -0
- haris-0.7.0/tests/test_verify_llm.py +324 -0
- haris-0.7.0/tests/test_verify_oracles.py +287 -0
- haris-0.7.0/tests/test_verify_pipeline.py +207 -0
- haris-0.7.0/tests/test_verify_unclassified_external.py +124 -0
- haris-0.7.0/tests/test_vuln_class_external_aliases.py +178 -0
- haris-0.7.0/tests/test_vuln_class_wapiti.py +70 -0
- haris-0.7.0/tests/test_wapiti_argv.py +161 -0
- haris-0.7.0/tests/test_wapiti_session.py +210 -0
- haris-0.7.0/tests/test_web_agent.py +283 -0
- haris-0.7.0/tests/test_web_agent_gate_audit.py +146 -0
- haris-0.7.0/tests/test_web_auth_fixes.py +390 -0
- haris-0.7.0/tests/test_web_csrf.py +236 -0
- haris-0.7.0/tests/test_web_env.py +277 -0
- haris-0.7.0/tests/test_web_execute.py +172 -0
- haris-0.7.0/tests/test_web_llm.py +195 -0
- haris-0.7.0/tests/test_web_ownership.py +249 -0
- haris-0.7.0/tests/test_web_proofs.py +250 -0
- haris-0.7.0/tests/test_web_queue.py +294 -0
- haris-0.7.0/tests/test_web_routes.py +246 -0
- haris-0.7.0/tests/test_web_scanner_options.py +123 -0
- haris-0.7.0/tests/test_web_targets.py +140 -0
- haris-0.7.0/tests/test_web_templates.py +294 -0
- haris-0.7.0/tests/test_web_tokens.py +338 -0
- haris-0.7.0/tests/test_web_verify.py +166 -0
- haris-0.7.0/tests/test_zap_scanner.py +315 -0
haris-0.7.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 HARIS contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
haris-0.7.0/PKG-INFO
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: haris
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Summary: Black-box web application security audit framework
|
|
5
|
+
Author: HARIS contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: security,audit,pentest,owasp,vulnerability-scanner
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Intended Audience :: Information Technology
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
15
|
+
Classifier: Topic :: Security
|
|
16
|
+
Requires-Python: >=3.13
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: pydantic>=2.14.3
|
|
20
|
+
Requires-Dist: requests>=2.34.2
|
|
21
|
+
Requires-Dist: pyyaml>=6.0.3
|
|
22
|
+
Requires-Dist: jinja2>=3.1.6
|
|
23
|
+
Requires-Dist: openai>=3.46.0
|
|
24
|
+
Requires-Dist: anthropic>=2.6.0
|
|
25
|
+
Requires-Dist: bcrypt>=5.0.0
|
|
26
|
+
Requires-Dist: starlette>=1.10.0
|
|
27
|
+
Requires-Dist: yoyo-migrations>=9.0.0
|
|
28
|
+
Provides-Extra: web
|
|
29
|
+
Requires-Dist: fastapi>=0.162.2; extra == "web"
|
|
30
|
+
Requires-Dist: uvicorn[standard]>=0.54.0; extra == "web"
|
|
31
|
+
Requires-Dist: python-multipart>=0.0.33; extra == "web"
|
|
32
|
+
Requires-Dist: authlib>=1.9.5; extra == "web"
|
|
33
|
+
Requires-Dist: httpx>=0.28.1; extra == "web"
|
|
34
|
+
Requires-Dist: itsdangerous>=2.2.0; extra == "web"
|
|
35
|
+
Requires-Dist: dnspython>=2.8.0; extra == "web"
|
|
36
|
+
Provides-Extra: reporting
|
|
37
|
+
Requires-Dist: markdown>=3.11.3; extra == "reporting"
|
|
38
|
+
Provides-Extra: all
|
|
39
|
+
Requires-Dist: haris[reporting,web]; extra == "all"
|
|
40
|
+
Dynamic: license-file
|
|
41
|
+
|
|
42
|
+
<p align="center">
|
|
43
|
+
<img src="assets/haris_logo.png" alt="HARIS" width="400"><br>
|
|
44
|
+
<em>Black-box web security audit framework. Scan, correlate, prioritise, remediate.</em><br><br>
|
|
45
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License"></a>
|
|
46
|
+
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.13+-blue.svg" alt="Python"></a>
|
|
47
|
+
<a href="https://owasp.org/www-project-top-ten/"><img src="https://img.shields.io/badge/OWASP-Top%2010%202025-red.svg" alt="OWASP"></a>
|
|
48
|
+
</p>
|
|
49
|
+
|
|
50
|
+
Orchestrates security scanners, correlates findings, and writes one prioritised report. LLM analysis is optional.
|
|
51
|
+
|
|
52
|
+
## What this does
|
|
53
|
+
|
|
54
|
+
1. **Cross-tool correlation.** Findings that share a fingerprint become one finding. The score combines the scanners that reported it.
|
|
55
|
+
2. **Cross-scanner context.** Built-in checks and nmap fill a `ScanContext`. Later scanners read it. Nuclei uses detected technologies in phase 2b.
|
|
56
|
+
3. **Business-risk text.** Plain-language impact sits next to the technical finding.
|
|
57
|
+
4. **Prioritised remediation.** Fixes are grouped and ordered by impact and effort.
|
|
58
|
+
5. **Profiles.** `quick`, `pre-launch`, `full`, `ai-security`, `regression`, `compliance`.
|
|
59
|
+
6. **Scan templates.** Named presets with per-scanner overrides, stored and reused from the web UI.
|
|
60
|
+
7. **LLM analysis.** Q&A, Jira text, test cases and enrichment, from the scan data.
|
|
61
|
+
8. **OWASP Top 10 (2025).** Findings are mapped, including Software Supply Chain Failures and Mishandling of Exceptional Conditions.
|
|
62
|
+
9. **Verification.** Replay oracles, an optional LLM verdict, and an opt-in agent. A refuted finding stays in the report. See [`docs/verification.md`](docs/verification.md).
|
|
63
|
+
|
|
64
|
+
## Scanners
|
|
65
|
+
|
|
66
|
+
| Scanner | What it tests | Install | Version recorded |
|
|
67
|
+
| ------- | ------------- | ------- | ---------------- |
|
|
68
|
+
| Wapiti | SQLi, XSS, SSRF, command injection, CRLF, XXE | `pipx install wapiti3` | 3.3 |
|
|
69
|
+
| SSLyze | TLS protocols, cipher suites, certificate chain, Heartbleed, ROBOT | `pipx install sslyze` | 6.x |
|
|
70
|
+
| Nmap | Open ports, service versions, exposed databases | system package manager | 7.x |
|
|
71
|
+
| Nikto | Web server misconfigurations, outdated software, dangerous files | `brew install nikto` | 2.x |
|
|
72
|
+
| Nuclei | CVE checks, default credentials, exposed panels, tech fingerprint (phase 1, 2a, 2b) | `brew install nuclei` | 3.x |
|
|
73
|
+
| ZAP | Active and passive web scan. Off by default and in no profile. `--scanners zap` | [ZAP download](https://www.zaproxy.org/download/) | 2.16 |
|
|
74
|
+
| garak | Injection and leakage probes on a discovered chat route. Runs only with `--ai-active` and `--i-have-authorization` | install the binary | 0.17 |
|
|
75
|
+
| promptfoo | Red-team plugins on a discovered chat route. Same flags as garak | install the binary | 0.125 |
|
|
76
|
+
|
|
77
|
+
The version column is the adapter `version` attribute. The Wapiti docstring names 3.3.2. The Nikto docstring names 2.6. Nuclei fixtures in `tests/fixtures/scanners/README.md` are 3.7.1. `garak.yaml` comments 0.17.1 and `promptfoo.yaml` comments 0.125.1. HARIS does not check the tool version at runtime.
|
|
78
|
+
|
|
79
|
+
Install Wapiti and SSLyze with `pipx`, outside the HARIS environment.
|
|
80
|
+
|
|
81
|
+
## Built-in checks
|
|
82
|
+
|
|
83
|
+
Fourteen checks. `quick` runs every check except `ai_security`.
|
|
84
|
+
|
|
85
|
+
| Check | What it tests |
|
|
86
|
+
| ----- | ------------- |
|
|
87
|
+
| `header_checks` | Six headers: HSTS, CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy. Also weak CSP or HSTS, a versioned Server banner, and any X-Powered-By header |
|
|
88
|
+
| `tls_checks` | Certificate and TLS basics |
|
|
89
|
+
| `misc_checks` | CORS, HTTP to HTTPS redirect, 14 sensitive paths |
|
|
90
|
+
| `info_disclosure` | Error pages, debug endpoints, HTML comments |
|
|
91
|
+
| `cookie_checks` | Session cookie flags, scope, expiry and name |
|
|
92
|
+
| `sri_checks` | Subresource Integrity on third-party resources |
|
|
93
|
+
| `cache_checks` | Cache-Control on login, account and session-setting responses |
|
|
94
|
+
| `method_checks` | OPTIONS advertisement and TRACE |
|
|
95
|
+
| `redirect_checks` | Open redirect via common redirect parameters |
|
|
96
|
+
| `graphql_checks` | GraphQL introspection |
|
|
97
|
+
| `openapi_checks` | Exposed OpenAPI or Swagger documents |
|
|
98
|
+
| `listing_checks` | Directory listing |
|
|
99
|
+
| `dns_checks` | CAA, SPF and DMARC |
|
|
100
|
+
| `ai_security` | AI endpoints and MCP servers. Prompts only with `--ai-active` and `--i-have-authorization`. See [`docs/ai_security.md`](docs/ai_security.md) |
|
|
101
|
+
|
|
102
|
+
The 14 sensitive paths are `/.env`, `/.git/config`, `/robots.txt`, `/sitemap.xml`, `/.well-known/security.txt`, `/wp-login.php`, `/admin`, `/phpmyadmin`, `/server-status`, `/server-info`, `/.DS_Store`, `/crossdomain.xml`, `/elmah.axd` and `/trace.axd`.
|
|
103
|
+
|
|
104
|
+
## Setup
|
|
105
|
+
|
|
106
|
+
The console script is `haris`, entry point `haris.cli:main`.
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
git clone https://github.com/calghar/HARIS
|
|
110
|
+
cd HARIS
|
|
111
|
+
uv sync --extra web --extra reporting
|
|
112
|
+
uv run haris --help
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Nmap, Nikto, Nuclei, SSLyze, Wapiti and optional ZAP, garak and promptfoo are separate programs. For LLM features set `ANTHROPIC_API_KEY` or `OPENAI_API_KEY`. Ollama needs no key. Its client uses `http://localhost:11434` unless the backend is constructed with another base URL.
|
|
116
|
+
|
|
117
|
+
## Authentication
|
|
118
|
+
|
|
119
|
+
The web dashboard requires login. On first start an admin account is created from:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
HARIS_ADMIN_EMAIL=admin@example.com
|
|
123
|
+
HARIS_ADMIN_PASSWORD=changeme123
|
|
124
|
+
HARIS_SECRET_KEY=<random-32-char-string> # python -c "import secrets; print(secrets.token_hex(32))"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Startup creates that admin when both `HARIS_ADMIN_EMAIL` and `HARIS_ADMIN_PASSWORD` are set and the user table is empty. `/auth/setup` answers 404 until `HARIS_SETUP_TOKEN` is set, and once a user exists.
|
|
128
|
+
|
|
129
|
+
Self-registration uses `HARIS_ALLOWED_EMAIL_DOMAINS`. New accounts need email verification, or an admin activates them when SMTP is off.
|
|
130
|
+
|
|
131
|
+
Roles are `admin` and `user`. An admin manages users, settings, and any user's scans and templates. A user scans, and views and deletes their own scans, and uses Q&A.
|
|
132
|
+
|
|
133
|
+
OIDC uses `HARIS_OIDC_ENABLED=true` plus `HARIS_OIDC_ISSUER`, `HARIS_OIDC_CLIENT_ID` and `HARIS_OIDC_CLIENT_SECRET`. See [`docs/authentication.md`](docs/authentication.md).
|
|
134
|
+
|
|
135
|
+
## Usage
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
# CLI. --verify defaults to replay (off, replay, llm).
|
|
139
|
+
uv run haris --url https://example.com --profile quick --yes
|
|
140
|
+
uv run haris --list-profiles
|
|
141
|
+
|
|
142
|
+
# Web dashboard. Bind defaults are 127.0.0.1 and port 8000.
|
|
143
|
+
uv run haris --web
|
|
144
|
+
|
|
145
|
+
# Docker
|
|
146
|
+
docker compose up
|
|
147
|
+
docker compose run --rm cli --url https://example.com --profile quick --yes
|
|
148
|
+
make reload
|
|
149
|
+
|
|
150
|
+
# LLM analysis after a scan
|
|
151
|
+
uv run haris llm ask --scan-id <id> --question "Top 3 risks for an exec"
|
|
152
|
+
uv run haris llm remediate --scan-id <id> --format jira
|
|
153
|
+
uv run haris llm summarize --scan-id <id> --audience developer
|
|
154
|
+
|
|
155
|
+
# In-pipeline LLM enrichment
|
|
156
|
+
uv run haris --url https://example.com --profile quick --yes --llm-enrich
|
|
157
|
+
|
|
158
|
+
# Scanner template updates
|
|
159
|
+
uv run haris update-templates
|
|
160
|
+
uv run haris update-templates --scanner nuclei --list
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Scan profiles
|
|
164
|
+
|
|
165
|
+
Estimates are the `estimated_duration` strings on each profile.
|
|
166
|
+
|
|
167
|
+
| Profile | Scanners | Use |
|
|
168
|
+
| ------- | -------- | --- |
|
|
169
|
+
| `quick` | The 13 built-in checks other than `ai_security` | First look. 1-3 minutes |
|
|
170
|
+
| `pre-launch` | `quick` plus `nmap`, `sslyze`, `wapiti` | Before production. 10-30 minutes |
|
|
171
|
+
| `full` | `pre-launch` plus `nikto`, `nuclei` | Full audit. 20-30 minutes. ZAP, garak and promptfoo are absent |
|
|
172
|
+
| `ai-security` | `header_checks`, `tls_checks`, `info_disclosure`, `ai_security`, `garak`, `promptfoo` | AI endpoints. 1-10 minutes |
|
|
173
|
+
| `regression` | `header_checks`, `tls_checks`, `misc_checks` | CI gate. 30-60 seconds |
|
|
174
|
+
| `compliance` | `header_checks`, `tls_checks`, `misc_checks`, `info_disclosure`, `cookie_checks`, `nmap`, `sslyze` | TLS, headers, cookies, disclosure, ports. 5-15 minutes |
|
|
175
|
+
|
|
176
|
+
## Configuration
|
|
177
|
+
|
|
178
|
+
Copy `.env.example` to `.env`. The option file is `src/haris/resources/config/default_config.yaml`. Override it with `HARIS_CONFIG` or `./config/default_config.yaml` in the working directory.
|
|
179
|
+
|
|
180
|
+
| Variable | Purpose |
|
|
181
|
+
| -------- | ------- |
|
|
182
|
+
| `HARIS_ADMIN_EMAIL` | Bootstrap admin email, used on first start when no users exist |
|
|
183
|
+
| `HARIS_ADMIN_PASSWORD` | Bootstrap admin password |
|
|
184
|
+
| `HARIS_SECRET_KEY` | Session signing secret |
|
|
185
|
+
| `HARIS_TARGET_URL` | Default scan target |
|
|
186
|
+
| `HARIS_PROFILE` | Default scan profile |
|
|
187
|
+
| `HARIS_AUTH_HEADER` | Auth header value for the target |
|
|
188
|
+
| `HARIS_AUTH_COOKIE` | Auth cookie value for the target |
|
|
189
|
+
| `HARIS_AUTH_USERNAME` | Auth username for the target |
|
|
190
|
+
| `HARIS_AUTH_PASSWORD` | Auth password for the target |
|
|
191
|
+
| `ANTHROPIC_API_KEY` | Anthropic LLM backend |
|
|
192
|
+
| `OPENAI_API_KEY` | OpenAI LLM backend |
|
|
193
|
+
| `HARIS_OIDC_CLIENT_SECRET` | OIDC client secret |
|
|
194
|
+
| `HARIS_SMTP_USERNAME` | SMTP username for email verification |
|
|
195
|
+
| `HARIS_SMTP_PASSWORD` | SMTP password |
|
|
196
|
+
|
|
197
|
+
`OLLAMA_BASE_URL` is not read. The Ollama client default is the constructor argument above.
|
|
198
|
+
|
|
199
|
+
Web server variables. Flags accept `1`, `true` or `yes`, except where noted.
|
|
200
|
+
|
|
201
|
+
| Variable | Default | Effect |
|
|
202
|
+
| -------- | ------- | ------ |
|
|
203
|
+
| `HARIS_WEB_VERIFY_DEFAULT` | `replay` | Verification mode for web scans when the request sets none: `off`, `replay` or `llm` |
|
|
204
|
+
| `HARIS_TARGET_ALLOWLIST` | empty | Comma-separated host globs that skip ownership proof |
|
|
205
|
+
| `HARIS_ALLOW_PRIVATE_TARGETS` | `false` | Allow private and loopback target addresses. Only the value `true` enables it |
|
|
206
|
+
| `HARIS_SHARE_SCANS_ORG_WIDE` | `false` | Every user can read all scans. Only owners and admins can change them |
|
|
207
|
+
| `HARIS_AGENT_DISABLED` | unset | The value `1` stops the agent from running on any scan |
|
|
208
|
+
| `HARIS_MAX_CONCURRENT_SCANS` | `2` | Scans that run at once. At least 1 |
|
|
209
|
+
| `HARIS_FORCE_HTTPS` | `false` | Redirect `http://` requests to `https://` |
|
|
210
|
+
| `HARIS_ALLOWED_EMAIL_DOMAINS` | `techforpalestine.org` | Comma-separated registration domains. Empty allows any |
|
|
211
|
+
| `HARIS_OIDC_ENABLED` | `false` | Turn on OIDC sign-in |
|
|
212
|
+
| `HARIS_OIDC_ISSUER`, `HARIS_OIDC_CLIENT_ID` | empty | OIDC provider issuer URL and client ID |
|
|
213
|
+
| `HARIS_SMTP_ENABLED` | `false` | Send verification email. Otherwise the link is logged |
|
|
214
|
+
| `HARIS_SMTP_HOST`, `HARIS_SMTP_PORT` | `localhost`, `587` | SMTP server |
|
|
215
|
+
| `HARIS_SMTP_USE_TLS` | `true` | Any value other than `false` keeps TLS on |
|
|
216
|
+
| `HARIS_SMTP_FROM`, `HARIS_SMTP_FROM_NAME` | `noreply@techforpalestine.org`, `HARIS Security Platform` | Sender address and name |
|
|
217
|
+
| `HARIS_PUBLIC_URL` | unset | When set, the only base for emailed verification links. When unset, SMTP does not send and the link is logged from the request base URL |
|
|
218
|
+
| `HARIS_ALLOWED_HOSTS` | unset | Comma-separated hosts. When set, any other Host header is rejected and www redirect is off. When unset, there is no host check |
|
|
219
|
+
| `HARIS_COOKIE_SECURE` | `auto` | `true` forces the Secure flag and `false` omits it. Any other value, including `1` and `yes`, follows the request scheme. Session cookie and CSRF seed cookie |
|
|
220
|
+
| `HARIS_SETUP_TOKEN` | unset | `/auth/setup` answers 404 until this is set, and once a user exists. The form field `setup_token` is compared with this value |
|
|
221
|
+
|
|
222
|
+
## Documentation
|
|
223
|
+
|
|
224
|
+
- Architecture: [`docs/architecture.md`](docs/architecture.md)
|
|
225
|
+
- Methodology: [`docs/methodology.md`](docs/methodology.md)
|
|
226
|
+
- Verification: [`docs/verification.md`](docs/verification.md)
|
|
227
|
+
- Benchmarks: [`docs/benchmarks.md`](docs/benchmarks.md)
|
|
228
|
+
- Agent safety: [`docs/agent_safety.md`](docs/agent_safety.md)
|
|
229
|
+
- AI security: [`docs/ai_security.md`](docs/ai_security.md)
|
|
230
|
+
- Authentication: [`docs/authentication.md`](docs/authentication.md)
|
|
231
|
+
- LLM integration: [`docs/llm_integration.md`](docs/llm_integration.md)
|
|
232
|
+
- CI integrations: [`docs/integrations.md`](docs/integrations.md)
|
|
233
|
+
- Writing a check: [`docs/writing_checks.md`](docs/writing_checks.md)
|
|
234
|
+
- Integrating a tool: [`docs/integrating_tools.md`](docs/integrating_tools.md)
|
|
235
|
+
|
|
236
|
+
A new scanner subclasses `BaseScanner` and uses `@register_scanner`. A new check uses `@register_check`. A report subclasses `BaseReporter` and implements `generate()`. An LLM backend subclasses `BaseLLMBackend` and implements `complete()`.
|
|
237
|
+
|
|
238
|
+
## Limitations
|
|
239
|
+
|
|
240
|
+
- Black-box only. No source code analysis.
|
|
241
|
+
- Target auth methods on `AuthConfig` are `none`, `cookie`, `header` and `form`.
|
|
242
|
+
- LLM features need an API key and have a cost. They are optional.
|
|
243
|
+
- Email verification needs SMTP. Without it, an admin activates accounts.
|
|
244
|
+
- A security professional should confirm a finding before anyone acts on it.
|
|
245
|
+
- External scanner results depend on those tools being installed.
|
|
246
|
+
|
|
247
|
+
## Legal
|
|
248
|
+
|
|
249
|
+
For authorised testing only. See [LEGAL_NOTICE.md](LEGAL_NOTICE.md).
|
|
250
|
+
|
|
251
|
+
## License
|
|
252
|
+
|
|
253
|
+
MIT. See [LICENSE](LICENSE).
|
haris-0.7.0/README.md
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/haris_logo.png" alt="HARIS" width="400"><br>
|
|
3
|
+
<em>Black-box web security audit framework. Scan, correlate, prioritise, remediate.</em><br><br>
|
|
4
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License"></a>
|
|
5
|
+
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.13+-blue.svg" alt="Python"></a>
|
|
6
|
+
<a href="https://owasp.org/www-project-top-ten/"><img src="https://img.shields.io/badge/OWASP-Top%2010%202025-red.svg" alt="OWASP"></a>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
Orchestrates security scanners, correlates findings, and writes one prioritised report. LLM analysis is optional.
|
|
10
|
+
|
|
11
|
+
## What this does
|
|
12
|
+
|
|
13
|
+
1. **Cross-tool correlation.** Findings that share a fingerprint become one finding. The score combines the scanners that reported it.
|
|
14
|
+
2. **Cross-scanner context.** Built-in checks and nmap fill a `ScanContext`. Later scanners read it. Nuclei uses detected technologies in phase 2b.
|
|
15
|
+
3. **Business-risk text.** Plain-language impact sits next to the technical finding.
|
|
16
|
+
4. **Prioritised remediation.** Fixes are grouped and ordered by impact and effort.
|
|
17
|
+
5. **Profiles.** `quick`, `pre-launch`, `full`, `ai-security`, `regression`, `compliance`.
|
|
18
|
+
6. **Scan templates.** Named presets with per-scanner overrides, stored and reused from the web UI.
|
|
19
|
+
7. **LLM analysis.** Q&A, Jira text, test cases and enrichment, from the scan data.
|
|
20
|
+
8. **OWASP Top 10 (2025).** Findings are mapped, including Software Supply Chain Failures and Mishandling of Exceptional Conditions.
|
|
21
|
+
9. **Verification.** Replay oracles, an optional LLM verdict, and an opt-in agent. A refuted finding stays in the report. See [`docs/verification.md`](docs/verification.md).
|
|
22
|
+
|
|
23
|
+
## Scanners
|
|
24
|
+
|
|
25
|
+
| Scanner | What it tests | Install | Version recorded |
|
|
26
|
+
| ------- | ------------- | ------- | ---------------- |
|
|
27
|
+
| Wapiti | SQLi, XSS, SSRF, command injection, CRLF, XXE | `pipx install wapiti3` | 3.3 |
|
|
28
|
+
| SSLyze | TLS protocols, cipher suites, certificate chain, Heartbleed, ROBOT | `pipx install sslyze` | 6.x |
|
|
29
|
+
| Nmap | Open ports, service versions, exposed databases | system package manager | 7.x |
|
|
30
|
+
| Nikto | Web server misconfigurations, outdated software, dangerous files | `brew install nikto` | 2.x |
|
|
31
|
+
| Nuclei | CVE checks, default credentials, exposed panels, tech fingerprint (phase 1, 2a, 2b) | `brew install nuclei` | 3.x |
|
|
32
|
+
| ZAP | Active and passive web scan. Off by default and in no profile. `--scanners zap` | [ZAP download](https://www.zaproxy.org/download/) | 2.16 |
|
|
33
|
+
| garak | Injection and leakage probes on a discovered chat route. Runs only with `--ai-active` and `--i-have-authorization` | install the binary | 0.17 |
|
|
34
|
+
| promptfoo | Red-team plugins on a discovered chat route. Same flags as garak | install the binary | 0.125 |
|
|
35
|
+
|
|
36
|
+
The version column is the adapter `version` attribute. The Wapiti docstring names 3.3.2. The Nikto docstring names 2.6. Nuclei fixtures in `tests/fixtures/scanners/README.md` are 3.7.1. `garak.yaml` comments 0.17.1 and `promptfoo.yaml` comments 0.125.1. HARIS does not check the tool version at runtime.
|
|
37
|
+
|
|
38
|
+
Install Wapiti and SSLyze with `pipx`, outside the HARIS environment.
|
|
39
|
+
|
|
40
|
+
## Built-in checks
|
|
41
|
+
|
|
42
|
+
Fourteen checks. `quick` runs every check except `ai_security`.
|
|
43
|
+
|
|
44
|
+
| Check | What it tests |
|
|
45
|
+
| ----- | ------------- |
|
|
46
|
+
| `header_checks` | Six headers: HSTS, CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy. Also weak CSP or HSTS, a versioned Server banner, and any X-Powered-By header |
|
|
47
|
+
| `tls_checks` | Certificate and TLS basics |
|
|
48
|
+
| `misc_checks` | CORS, HTTP to HTTPS redirect, 14 sensitive paths |
|
|
49
|
+
| `info_disclosure` | Error pages, debug endpoints, HTML comments |
|
|
50
|
+
| `cookie_checks` | Session cookie flags, scope, expiry and name |
|
|
51
|
+
| `sri_checks` | Subresource Integrity on third-party resources |
|
|
52
|
+
| `cache_checks` | Cache-Control on login, account and session-setting responses |
|
|
53
|
+
| `method_checks` | OPTIONS advertisement and TRACE |
|
|
54
|
+
| `redirect_checks` | Open redirect via common redirect parameters |
|
|
55
|
+
| `graphql_checks` | GraphQL introspection |
|
|
56
|
+
| `openapi_checks` | Exposed OpenAPI or Swagger documents |
|
|
57
|
+
| `listing_checks` | Directory listing |
|
|
58
|
+
| `dns_checks` | CAA, SPF and DMARC |
|
|
59
|
+
| `ai_security` | AI endpoints and MCP servers. Prompts only with `--ai-active` and `--i-have-authorization`. See [`docs/ai_security.md`](docs/ai_security.md) |
|
|
60
|
+
|
|
61
|
+
The 14 sensitive paths are `/.env`, `/.git/config`, `/robots.txt`, `/sitemap.xml`, `/.well-known/security.txt`, `/wp-login.php`, `/admin`, `/phpmyadmin`, `/server-status`, `/server-info`, `/.DS_Store`, `/crossdomain.xml`, `/elmah.axd` and `/trace.axd`.
|
|
62
|
+
|
|
63
|
+
## Setup
|
|
64
|
+
|
|
65
|
+
The console script is `haris`, entry point `haris.cli:main`.
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
git clone https://github.com/calghar/HARIS
|
|
69
|
+
cd HARIS
|
|
70
|
+
uv sync --extra web --extra reporting
|
|
71
|
+
uv run haris --help
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Nmap, Nikto, Nuclei, SSLyze, Wapiti and optional ZAP, garak and promptfoo are separate programs. For LLM features set `ANTHROPIC_API_KEY` or `OPENAI_API_KEY`. Ollama needs no key. Its client uses `http://localhost:11434` unless the backend is constructed with another base URL.
|
|
75
|
+
|
|
76
|
+
## Authentication
|
|
77
|
+
|
|
78
|
+
The web dashboard requires login. On first start an admin account is created from:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
HARIS_ADMIN_EMAIL=admin@example.com
|
|
82
|
+
HARIS_ADMIN_PASSWORD=changeme123
|
|
83
|
+
HARIS_SECRET_KEY=<random-32-char-string> # python -c "import secrets; print(secrets.token_hex(32))"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Startup creates that admin when both `HARIS_ADMIN_EMAIL` and `HARIS_ADMIN_PASSWORD` are set and the user table is empty. `/auth/setup` answers 404 until `HARIS_SETUP_TOKEN` is set, and once a user exists.
|
|
87
|
+
|
|
88
|
+
Self-registration uses `HARIS_ALLOWED_EMAIL_DOMAINS`. New accounts need email verification, or an admin activates them when SMTP is off.
|
|
89
|
+
|
|
90
|
+
Roles are `admin` and `user`. An admin manages users, settings, and any user's scans and templates. A user scans, and views and deletes their own scans, and uses Q&A.
|
|
91
|
+
|
|
92
|
+
OIDC uses `HARIS_OIDC_ENABLED=true` plus `HARIS_OIDC_ISSUER`, `HARIS_OIDC_CLIENT_ID` and `HARIS_OIDC_CLIENT_SECRET`. See [`docs/authentication.md`](docs/authentication.md).
|
|
93
|
+
|
|
94
|
+
## Usage
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# CLI. --verify defaults to replay (off, replay, llm).
|
|
98
|
+
uv run haris --url https://example.com --profile quick --yes
|
|
99
|
+
uv run haris --list-profiles
|
|
100
|
+
|
|
101
|
+
# Web dashboard. Bind defaults are 127.0.0.1 and port 8000.
|
|
102
|
+
uv run haris --web
|
|
103
|
+
|
|
104
|
+
# Docker
|
|
105
|
+
docker compose up
|
|
106
|
+
docker compose run --rm cli --url https://example.com --profile quick --yes
|
|
107
|
+
make reload
|
|
108
|
+
|
|
109
|
+
# LLM analysis after a scan
|
|
110
|
+
uv run haris llm ask --scan-id <id> --question "Top 3 risks for an exec"
|
|
111
|
+
uv run haris llm remediate --scan-id <id> --format jira
|
|
112
|
+
uv run haris llm summarize --scan-id <id> --audience developer
|
|
113
|
+
|
|
114
|
+
# In-pipeline LLM enrichment
|
|
115
|
+
uv run haris --url https://example.com --profile quick --yes --llm-enrich
|
|
116
|
+
|
|
117
|
+
# Scanner template updates
|
|
118
|
+
uv run haris update-templates
|
|
119
|
+
uv run haris update-templates --scanner nuclei --list
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Scan profiles
|
|
123
|
+
|
|
124
|
+
Estimates are the `estimated_duration` strings on each profile.
|
|
125
|
+
|
|
126
|
+
| Profile | Scanners | Use |
|
|
127
|
+
| ------- | -------- | --- |
|
|
128
|
+
| `quick` | The 13 built-in checks other than `ai_security` | First look. 1-3 minutes |
|
|
129
|
+
| `pre-launch` | `quick` plus `nmap`, `sslyze`, `wapiti` | Before production. 10-30 minutes |
|
|
130
|
+
| `full` | `pre-launch` plus `nikto`, `nuclei` | Full audit. 20-30 minutes. ZAP, garak and promptfoo are absent |
|
|
131
|
+
| `ai-security` | `header_checks`, `tls_checks`, `info_disclosure`, `ai_security`, `garak`, `promptfoo` | AI endpoints. 1-10 minutes |
|
|
132
|
+
| `regression` | `header_checks`, `tls_checks`, `misc_checks` | CI gate. 30-60 seconds |
|
|
133
|
+
| `compliance` | `header_checks`, `tls_checks`, `misc_checks`, `info_disclosure`, `cookie_checks`, `nmap`, `sslyze` | TLS, headers, cookies, disclosure, ports. 5-15 minutes |
|
|
134
|
+
|
|
135
|
+
## Configuration
|
|
136
|
+
|
|
137
|
+
Copy `.env.example` to `.env`. The option file is `src/haris/resources/config/default_config.yaml`. Override it with `HARIS_CONFIG` or `./config/default_config.yaml` in the working directory.
|
|
138
|
+
|
|
139
|
+
| Variable | Purpose |
|
|
140
|
+
| -------- | ------- |
|
|
141
|
+
| `HARIS_ADMIN_EMAIL` | Bootstrap admin email, used on first start when no users exist |
|
|
142
|
+
| `HARIS_ADMIN_PASSWORD` | Bootstrap admin password |
|
|
143
|
+
| `HARIS_SECRET_KEY` | Session signing secret |
|
|
144
|
+
| `HARIS_TARGET_URL` | Default scan target |
|
|
145
|
+
| `HARIS_PROFILE` | Default scan profile |
|
|
146
|
+
| `HARIS_AUTH_HEADER` | Auth header value for the target |
|
|
147
|
+
| `HARIS_AUTH_COOKIE` | Auth cookie value for the target |
|
|
148
|
+
| `HARIS_AUTH_USERNAME` | Auth username for the target |
|
|
149
|
+
| `HARIS_AUTH_PASSWORD` | Auth password for the target |
|
|
150
|
+
| `ANTHROPIC_API_KEY` | Anthropic LLM backend |
|
|
151
|
+
| `OPENAI_API_KEY` | OpenAI LLM backend |
|
|
152
|
+
| `HARIS_OIDC_CLIENT_SECRET` | OIDC client secret |
|
|
153
|
+
| `HARIS_SMTP_USERNAME` | SMTP username for email verification |
|
|
154
|
+
| `HARIS_SMTP_PASSWORD` | SMTP password |
|
|
155
|
+
|
|
156
|
+
`OLLAMA_BASE_URL` is not read. The Ollama client default is the constructor argument above.
|
|
157
|
+
|
|
158
|
+
Web server variables. Flags accept `1`, `true` or `yes`, except where noted.
|
|
159
|
+
|
|
160
|
+
| Variable | Default | Effect |
|
|
161
|
+
| -------- | ------- | ------ |
|
|
162
|
+
| `HARIS_WEB_VERIFY_DEFAULT` | `replay` | Verification mode for web scans when the request sets none: `off`, `replay` or `llm` |
|
|
163
|
+
| `HARIS_TARGET_ALLOWLIST` | empty | Comma-separated host globs that skip ownership proof |
|
|
164
|
+
| `HARIS_ALLOW_PRIVATE_TARGETS` | `false` | Allow private and loopback target addresses. Only the value `true` enables it |
|
|
165
|
+
| `HARIS_SHARE_SCANS_ORG_WIDE` | `false` | Every user can read all scans. Only owners and admins can change them |
|
|
166
|
+
| `HARIS_AGENT_DISABLED` | unset | The value `1` stops the agent from running on any scan |
|
|
167
|
+
| `HARIS_MAX_CONCURRENT_SCANS` | `2` | Scans that run at once. At least 1 |
|
|
168
|
+
| `HARIS_FORCE_HTTPS` | `false` | Redirect `http://` requests to `https://` |
|
|
169
|
+
| `HARIS_ALLOWED_EMAIL_DOMAINS` | `techforpalestine.org` | Comma-separated registration domains. Empty allows any |
|
|
170
|
+
| `HARIS_OIDC_ENABLED` | `false` | Turn on OIDC sign-in |
|
|
171
|
+
| `HARIS_OIDC_ISSUER`, `HARIS_OIDC_CLIENT_ID` | empty | OIDC provider issuer URL and client ID |
|
|
172
|
+
| `HARIS_SMTP_ENABLED` | `false` | Send verification email. Otherwise the link is logged |
|
|
173
|
+
| `HARIS_SMTP_HOST`, `HARIS_SMTP_PORT` | `localhost`, `587` | SMTP server |
|
|
174
|
+
| `HARIS_SMTP_USE_TLS` | `true` | Any value other than `false` keeps TLS on |
|
|
175
|
+
| `HARIS_SMTP_FROM`, `HARIS_SMTP_FROM_NAME` | `noreply@techforpalestine.org`, `HARIS Security Platform` | Sender address and name |
|
|
176
|
+
| `HARIS_PUBLIC_URL` | unset | When set, the only base for emailed verification links. When unset, SMTP does not send and the link is logged from the request base URL |
|
|
177
|
+
| `HARIS_ALLOWED_HOSTS` | unset | Comma-separated hosts. When set, any other Host header is rejected and www redirect is off. When unset, there is no host check |
|
|
178
|
+
| `HARIS_COOKIE_SECURE` | `auto` | `true` forces the Secure flag and `false` omits it. Any other value, including `1` and `yes`, follows the request scheme. Session cookie and CSRF seed cookie |
|
|
179
|
+
| `HARIS_SETUP_TOKEN` | unset | `/auth/setup` answers 404 until this is set, and once a user exists. The form field `setup_token` is compared with this value |
|
|
180
|
+
|
|
181
|
+
## Documentation
|
|
182
|
+
|
|
183
|
+
- Architecture: [`docs/architecture.md`](docs/architecture.md)
|
|
184
|
+
- Methodology: [`docs/methodology.md`](docs/methodology.md)
|
|
185
|
+
- Verification: [`docs/verification.md`](docs/verification.md)
|
|
186
|
+
- Benchmarks: [`docs/benchmarks.md`](docs/benchmarks.md)
|
|
187
|
+
- Agent safety: [`docs/agent_safety.md`](docs/agent_safety.md)
|
|
188
|
+
- AI security: [`docs/ai_security.md`](docs/ai_security.md)
|
|
189
|
+
- Authentication: [`docs/authentication.md`](docs/authentication.md)
|
|
190
|
+
- LLM integration: [`docs/llm_integration.md`](docs/llm_integration.md)
|
|
191
|
+
- CI integrations: [`docs/integrations.md`](docs/integrations.md)
|
|
192
|
+
- Writing a check: [`docs/writing_checks.md`](docs/writing_checks.md)
|
|
193
|
+
- Integrating a tool: [`docs/integrating_tools.md`](docs/integrating_tools.md)
|
|
194
|
+
|
|
195
|
+
A new scanner subclasses `BaseScanner` and uses `@register_scanner`. A new check uses `@register_check`. A report subclasses `BaseReporter` and implements `generate()`. An LLM backend subclasses `BaseLLMBackend` and implements `complete()`.
|
|
196
|
+
|
|
197
|
+
## Limitations
|
|
198
|
+
|
|
199
|
+
- Black-box only. No source code analysis.
|
|
200
|
+
- Target auth methods on `AuthConfig` are `none`, `cookie`, `header` and `form`.
|
|
201
|
+
- LLM features need an API key and have a cost. They are optional.
|
|
202
|
+
- Email verification needs SMTP. Without it, an admin activates accounts.
|
|
203
|
+
- A security professional should confirm a finding before anyone acts on it.
|
|
204
|
+
- External scanner results depend on those tools being installed.
|
|
205
|
+
|
|
206
|
+
## Legal
|
|
207
|
+
|
|
208
|
+
For authorised testing only. See [LEGAL_NOTICE.md](LEGAL_NOTICE.md).
|
|
209
|
+
|
|
210
|
+
## License
|
|
211
|
+
|
|
212
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "haris"
|
|
7
|
+
version = "0.7.0"
|
|
8
|
+
description = "Black-box web application security audit framework"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.13"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "HARIS contributors"},
|
|
14
|
+
]
|
|
15
|
+
keywords = ["security", "audit", "pentest", "owasp", "vulnerability-scanner"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Intended Audience :: Information Technology",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Programming Language :: Python :: 3.14",
|
|
24
|
+
"Topic :: Security",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
dependencies = [
|
|
28
|
+
"pydantic>=2.14.3",
|
|
29
|
+
"requests>=2.34.2",
|
|
30
|
+
"pyyaml>=6.0.3",
|
|
31
|
+
"jinja2>=3.1.6",
|
|
32
|
+
"openai>=3.46.0",
|
|
33
|
+
"anthropic>=2.6.0",
|
|
34
|
+
"bcrypt>=5.0.0",
|
|
35
|
+
"starlette>=1.10.0",
|
|
36
|
+
"yoyo-migrations>=9.0.0",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
[project.optional-dependencies]
|
|
40
|
+
# Web dashboard
|
|
41
|
+
web = [
|
|
42
|
+
"fastapi>=0.162.2",
|
|
43
|
+
"uvicorn[standard]>=0.54.0",
|
|
44
|
+
"python-multipart>=0.0.33",
|
|
45
|
+
"authlib>=1.9.5",
|
|
46
|
+
"httpx>=0.28.1",
|
|
47
|
+
"itsdangerous>=2.2.0",
|
|
48
|
+
"dnspython>=2.8.0",
|
|
49
|
+
]
|
|
50
|
+
# Report generation extras
|
|
51
|
+
reporting = [
|
|
52
|
+
"markdown>=3.11.3",
|
|
53
|
+
]
|
|
54
|
+
# Everything installable alongside the web dashboard
|
|
55
|
+
all = [
|
|
56
|
+
"haris[web,reporting]",
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
[dependency-groups]
|
|
60
|
+
dev = [
|
|
61
|
+
"pytest>=9.2.0",
|
|
62
|
+
"pytest-cov>=7.1.0",
|
|
63
|
+
"ruff>=0.17.4",
|
|
64
|
+
"mypy>=2.4.1",
|
|
65
|
+
"types-requests",
|
|
66
|
+
"types-PyYAML",
|
|
67
|
+
"types-authlib",
|
|
68
|
+
"bandit[toml]>=1.9.4",
|
|
69
|
+
"pip-audit>=2.10.1",
|
|
70
|
+
"pre-commit>=4.7.0",
|
|
71
|
+
"jsonschema>=4.26.0",
|
|
72
|
+
"types-jsonschema>=4.26.0.20261006",
|
|
73
|
+
]
|
|
74
|
+
docs = [
|
|
75
|
+
"mkdocs-material>=9.8.1",
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
[project.scripts]
|
|
79
|
+
haris = "haris.cli:main"
|
|
80
|
+
|
|
81
|
+
[tool.setuptools.packages.find]
|
|
82
|
+
where = ["src"]
|
|
83
|
+
include = ["haris*"]
|
|
84
|
+
|
|
85
|
+
[tool.setuptools.package-data]
|
|
86
|
+
haris = [
|
|
87
|
+
"web/templates/**/*",
|
|
88
|
+
"web/static/**/*",
|
|
89
|
+
"llm/templates/**/*",
|
|
90
|
+
"resources/config/**/*",
|
|
91
|
+
"resources/schema/**/*",
|
|
92
|
+
"db/migrations/*",
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
[tool.pytest.ini_options]
|
|
96
|
+
testpaths = ["tests"]
|
|
97
|
+
addopts = "-v --tb=short"
|
|
98
|
+
markers = [
|
|
99
|
+
"docker: requires a local Docker daemon and the haris-agent-sandbox image",
|
|
100
|
+
]
|
|
101
|
+
filterwarnings = ["ignore:The default datetime adapter:DeprecationWarning"]
|
|
102
|
+
|
|
103
|
+
[tool.ruff]
|
|
104
|
+
target-version = "py313"
|
|
105
|
+
line-length = 88
|
|
106
|
+
|
|
107
|
+
[tool.ruff.lint]
|
|
108
|
+
select = ["E", "F", "W", "I", "N", "UP", "B", "SIM", "TID251"]
|
|
109
|
+
# B008: FastAPI's Depends() in function defaults is the standard DI pattern
|
|
110
|
+
ignore = ["B008"]
|
|
111
|
+
|
|
112
|
+
[tool.ruff.lint.flake8-tidy-imports.banned-api]
|
|
113
|
+
"requests".msg = "Send HTTP through haris.net.ScopedClient."
|
|
114
|
+
"httpx".msg = "Send HTTP through haris.net.ScopedClient."
|
|
115
|
+
"urllib3".msg = "Send HTTP through haris.net.ScopedClient."
|
|
116
|
+
|
|
117
|
+
[tool.ruff.lint.per-file-ignores]
|
|
118
|
+
"src/haris/net/**" = ["TID251"]
|
|
119
|
+
# LLM provider SDK calls; not target traffic
|
|
120
|
+
"src/haris/llm/providers.py" = ["TID251"]
|
|
121
|
+
# Fake transports and test servers
|
|
122
|
+
"tests/**" = ["TID251"]
|
|
123
|
+
# Benchmark harness talks to its own local fixtures
|
|
124
|
+
"bench/**" = ["TID251"]
|
|
125
|
+
|
|
126
|
+
[tool.mypy]
|
|
127
|
+
python_version = "3.13"
|
|
128
|
+
warn_return_any = true
|
|
129
|
+
warn_unused_configs = true
|
|
130
|
+
|
|
131
|
+
[[tool.mypy.overrides]]
|
|
132
|
+
module = "yoyo.*"
|
|
133
|
+
ignore_missing_imports = true
|
|
134
|
+
|
|
135
|
+
[tool.bandit]
|
|
136
|
+
exclude_dirs = ["tests", ".venv", "venv"]
|
|
137
|
+
# B603/B607: scanners intentionally call external tools (nmap, nuclei, etc.) by name
|
|
138
|
+
skips = ["B603", "B607"]
|
haris-0.7.0/setup.cfg
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from .policy import (
|
|
2
|
+
AgentPolicy,
|
|
3
|
+
activation_result,
|
|
4
|
+
bind_cli,
|
|
5
|
+
bind_policy,
|
|
6
|
+
current_policy,
|
|
7
|
+
policy_for_web,
|
|
8
|
+
reset_policy,
|
|
9
|
+
)
|
|
10
|
+
from .stages import note_stage
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"AgentPolicy",
|
|
14
|
+
"activation_result",
|
|
15
|
+
"bind_cli",
|
|
16
|
+
"bind_policy",
|
|
17
|
+
"current_policy",
|
|
18
|
+
"note_stage",
|
|
19
|
+
"policy_for_web",
|
|
20
|
+
"reset_policy",
|
|
21
|
+
]
|