{"version": "2.1.0", "$schema": "https://json.schemastore.org/sarif-2.1.0.json", "runs": [{"tool": {"driver": {"name": "Repobility", "informationUri": "https://repobility.com", "rules": [{"id": "scanner-ff04aeda444593ca", "name": "Possibly dead Python function: loop", "shortDescription": {"text": "Possibly dead Python function: loop"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-cc8a2ae16244f910", "name": "Possibly dead Python function: is_up", "shortDescription": {"text": "Possibly dead Python function: is_up"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-52fb9c7c691c6d8f", "name": "Possibly dead Python function: loop", "shortDescription": {"text": "Possibly dead Python function: loop"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-86a64f90bd122ae9", "name": "Possibly dead Python function: run_ssdp", "shortDescription": {"text": "Possibly dead Python function: run_ssdp"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ccf6b4f92d5c6cee", "name": "Possibly dead Python function: run_mdns", "shortDescription": {"text": "Possibly dead Python function: run_mdns"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d63da3583b14afc0", "name": "Dockerfile runs as root: Dockerfile", "shortDescription": {"text": "Dockerfile runs as root: Dockerfile"}, "fullDescription": {"text": "No non-root USER set. Containers running as root expand the blast radius of any vulnerability inside the image."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-84019dfd8d98a34d", "name": "Docker base image is tag-pinned but not digest-pinned: debian:bookworm-slim", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: debian:bookworm-slim"}, "fullDescription": {"text": "Container tags can be retagged upstream. Pin production base images to a reviewed digest (`image@sha256:...`) when reproducibility and supply-chain integrity matter."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ce1fec675e91d850", "name": "Docker base image is tag-pinned but not digest-pinned: python:3.12-slim-bookworm", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: python:3.12-slim-bookworm"}, "fullDescription": {"text": "Container tags can be retagged upstream. Pin production base images to a reviewed digest (`image@sha256:...`) when reproducibility and supply-chain integrity matter."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d3a88b67e2ad7e17", "name": "Dockerfile runs as root: hub/Dockerfile", "shortDescription": {"text": "Dockerfile runs as root: hub/Dockerfile"}, "fullDescription": {"text": "No non-root USER set. Containers running as root expand the blast radius of any vulnerability inside the image."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-74ba98032554335e", "name": "Docker base image is tag-pinned but not digest-pinned: debian:bookworm-slim", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: debian:bookworm-slim"}, "fullDescription": {"text": "Container tags can be retagged upstream. Pin production base images to a reviewed digest (`image@sha256:...`) when reproducibility and supply-chain integrity matter."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-80f458688e94c28e", "name": "Docker base image is tag-pinned but not digest-pinned: python:3.12-slim-bookworm", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: python:3.12-slim-bookworm"}, "fullDescription": {"text": "Container tags can be retagged upstream. Pin production base images to a reviewed digest (`image@sha256:...`) when reproducibility and supply-chain integrity matter."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-aa5acaa49eb8315b", "name": "Containers defined but no K8s/orchestration manifest found", "shortDescription": {"text": "Containers defined but no K8s/orchestration manifest found"}, "fullDescription": {"text": "Repo has Dockerfiles/compose but no Kubernetes/Nomad manifests. If the target deployment is K8s, the manifests may live in a separate ops repo."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9710c8d059e53154", "name": "No frontend routes/components detected", "shortDescription": {"text": "No frontend routes/components detected"}, "fullDescription": {"text": "No React/Vue/Next routes were found. This is fine for backend-only repos."}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-82c03ef7f12b7cac", "name": "Insecure pattern 'direct_innerhtml_assignment' in hub/app/static/site.html:257", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in hub/app/static/site.html:257"}, "fullDescription": {"text": "Found a known-risky pattern (direct_innerhtml_assignment). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-087330ce88937f9c", "name": "Insecure pattern 'direct_innerhtml_assignment' in hub/app/static/index.html:232", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in hub/app/static/index.html:232"}, "fullDescription": {"text": "Found a known-risky pattern (direct_innerhtml_assignment). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b4cabcdb18b98bfe", "name": "Insecure pattern 'tls_verify_false' in app/hikvision.py:40", "shortDescription": {"text": "Insecure pattern 'tls_verify_false' in app/hikvision.py:40"}, "fullDescription": {"text": "Found a known-risky pattern (tls_verify_false). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-b2ec0ebe6a02f71a", "name": "Insecure pattern 'tls_verify_false' in app/identify.py:119", "shortDescription": {"text": "Insecure pattern 'tls_verify_false' in app/identify.py:119"}, "fullDescription": {"text": "Found a known-risky pattern (tls_verify_false). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-52a0e9989b662fff", "name": "Insecure pattern 'direct_innerhtml_assignment' in app/static/index.html:435", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in app/static/index.html:435"}, "fullDescription": {"text": "Found a known-risky pattern (direct_innerhtml_assignment). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-632c6e30e35f8e5c", "name": "Insecure pattern 'direct_innerhtml_assignment' in app/static/setup.html:104", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in app/static/setup.html:104"}, "fullDescription": {"text": "Found a known-risky pattern (direct_innerhtml_assignment). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-6372cebde0220094", "name": "No auth library detected", "shortDescription": {"text": "No auth library detected"}, "fullDescription": {"text": "The scanner did not find any standard auth library (JWT, OAuth, NextAuth, Auth0, etc.). The repo has auth/admin/session surface indicators, so auth may live in custom code, in a separate service, or be missing."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-6ba9bfab5f283202", "name": "GitHub Action is tag-pinned rather than SHA-pinned", "shortDescription": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "fullDescription": {"text": "docker/setup-qemu-action@v3 can move without a code change in this repo. Pin third-party actions to a reviewed 40-character commit SHA."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b769174c9fcf8ea8", "name": "GitHub Actions workflow grants broad write permissions", "shortDescription": {"text": "GitHub Actions workflow grants broad write permissions"}, "fullDescription": {"text": "CI tokens with write permissions increase blast radius when an action, dependency, or PR workflow is compromised. Prefer job-level least-privilege permissions."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-6893a6c8b0861585", "name": "Very low test-to-source ratio", "shortDescription": {"text": "Very low test-to-source ratio"}, "fullDescription": {"text": "0 test file(s) for 24 source file(s) (ratio 0.00). Consider adding integration or unit tests for critical paths."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-141b30a41e03817b", "name": "No license file detected", "shortDescription": {"text": "No license file detected"}, "fullDescription": {"text": "No LICENSE/COPYING/NOTICE file was found. Generated repositories often omit licensing, which blocks reuse and automated intake."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 17 console/debugger/print-style debug statements in non-test source. This is a common fast-generation residue before production cleanup."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2d0c7b7ab8f8aacf", "name": "Critical user flow still appears backed by mock or placeholder data", "shortDescription": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "fullDescription": {"text": "A payment/auth/admin/order/billing-style flow contains mock, fake, TODO, dummy, or placeholder markers in runtime source. In the Fable corpus this is a high-leverage completeness smell: the app can look finished while the money, identity, or tenant flow is still scaffolded."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-11825279136b53a3", "name": "CI is configured but no tests are detected", "shortDescription": {"text": "CI is configured but no tests are detected"}, "fullDescription": {"text": "A CI pipeline exists, but the scan found no test files to gate. Opus labeled this generated-code pattern as config theater: release machinery exists, but it has little behavioral signal."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b9088664ace7f748", "name": "Composite production-readiness gap", "shortDescription": {"text": "Composite production-readiness gap"}, "fullDescription": {"text": "Multiple low-cost hardening controls are missing together: license, tests. Opus verification showed these co-occurring gaps are a better readiness signal than reading each flag in isolation."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ea8f3013f588db25", "name": "Shallow git history limits provenance confidence", "shortDescription": {"text": "Shallow git history limits provenance confidence"}, "fullDescription": {"text": "The repository is a shallow clone. Origin/evolution analysis cannot distinguish fresh generation, imported legacy code, or long-lived human code with high confidence."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8424db9c75e04ba4", "name": "Very short observed git history", "shortDescription": {"text": "Very short observed git history"}, "fullDescription": {"text": "The repo has multiple source files but two or fewer visible commits. This is not a failure by itself, but it lowers confidence in evolution-based diagnosis."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-ca236c58db7c90f8", "name": "Commented-code block (8 lines) in hub/app/hubconfig.py:36", "shortDescription": {"text": "Commented-code block (8 lines) in hub/app/hubconfig.py:36"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-603dc4567c54d32d", "name": "Commented-code block (5 lines) in hub/app/server.py:251", "shortDescription": {"text": "Commented-code block (5 lines) in hub/app/server.py:251"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-8e047ab7af03962f", "name": "7 env vars used in code but missing from .env.example", "shortDescription": {"text": "7 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `HUB_DATA`, `HUB_PROXY_RANGE`, `HUB_TCP_RANGE`, `NETWATCH_DATA`, `NETWATCH_INSTALL_URL`, `NETWATCH_PORT`, `WGEASY_URL`. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-49c98f7cedd9c977", "name": "Near-duplicate function bodies in 4 places", "shortDescription": {"text": "Near-duplicate function bodies in 4 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nhub/app/tunnels.py:start, hub/app/tunnels.py:start, app/tunnels.py:start, app/tunnels.py:start\n\nThis is *the* AI-coder failure mode (4\u00d7 more duplication in vibe-coded repos \u2014 see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2c04133e54348533", "name": "Near-duplicate function bodies in 2 places", "shortDescription": {"text": "Near-duplicate function bodies in 2 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nhub/app/tunnels.py:conns, app/tunnels.py:conns\n\nThis is *the* AI-coder failure mode (4\u00d7 more duplication in vibe-coded repos \u2014 see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-20988bb37defafcb", "name": "Flask mutation route `api_login` without `@login_required` \u2014 hub/app/server.py:83", "shortDescription": {"text": "Flask mutation route `api_login` without `@login_required` \u2014 hub/app/server.py:83"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-b6f4dc2e7e31d49f", "name": "Flask mutation route `api_logout` without `@login_required` \u2014 hub/app/server.py:106", "shortDescription": {"text": "Flask mutation route `api_logout` without `@login_required` \u2014 hub/app/server.py:106"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-56ea97ecce3595c1", "name": "Flask mutation route `api_sites` without `@login_required` \u2014 hub/app/server.py:198", "shortDescription": {"text": "Flask mutation route `api_sites` without `@login_required` \u2014 hub/app/server.py:198"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-e1a0d12017d5c5ca", "name": "Flask mutation route `api_site` without `@login_required` \u2014 hub/app/server.py:214", "shortDescription": {"text": "Flask mutation route `api_site` without `@login_required` \u2014 hub/app/server.py:214"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-d6e94b7cdb8f6dc9", "name": "Flask mutation route `api_hub_wizard` without `@login_required` \u2014 hub/app/server.py:275", "shortDescription": {"text": "Flask mutation route `api_hub_wizard` without `@login_required` \u2014 hub/app/server.py:275"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-fc4d832ea5002ca5", "name": "Flask mutation route `api_site_command` without `@login_required` \u2014 hub/app/server.py:375", "shortDescription": {"text": "Flask mutation route `api_site_command` without `@login_required` \u2014 hub/app/server.py:375"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-6c499899b45ca347", "name": "Flask mutation route `api_site_trigger` without `@login_required` \u2014 hub/app/server.py:393", "shortDescription": {"text": "Flask mutation route `api_site_trigger` without `@login_required` \u2014 hub/app/server.py:393"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-2be017c1b0384cb5", "name": "Flask mutation route `api_site_poll` without `@login_required` \u2014 hub/app/server.py:431", "shortDescription": {"text": "Flask mutation route `api_site_poll` without `@login_required` \u2014 hub/app/server.py:431"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-1cf3126c5bc30402", "name": "Flask mutation route `api_site_tunnel` without `@login_required` \u2014 hub/app/server.py:441", "shortDescription": {"text": "Flask mutation route `api_site_tunnel` without `@login_required` \u2014 hub/app/server.py:441"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-8e8b4939ae93747a", "name": "Flask mutation route `api_site_tunnel_close` without `@login_required` \u2014 hub/app/server.py:464", "shortDescription": {"text": "Flask mutation route `api_site_tunnel_close` without `@login_required` \u2014 hub/app/server.py:464"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-80c052daf6067863", "name": "Flask mutation route `api_config` without `@login_required` \u2014 app/server.py:90", "shortDescription": {"text": "Flask mutation route `api_config` without `@login_required` \u2014 app/server.py:90"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-6d150049c2cfcb20", "name": "Flask mutation route `api_trigger` without `@login_required` \u2014 app/server.py:100", "shortDescription": {"text": "Flask mutation route `api_trigger` without `@login_required` \u2014 app/server.py:100"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-d59472a45e420c11", "name": "Flask mutation route `api_command` without `@login_required` \u2014 app/server.py:113", "shortDescription": {"text": "Flask mutation route `api_command` without `@login_required` \u2014 app/server.py:113"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-f7c54aed07c5ed60", "name": "Flask mutation route `api_test_ntfy` without `@login_required` \u2014 app/server.py:133", "shortDescription": {"text": "Flask mutation route `api_test_ntfy` without `@login_required` \u2014 app/server.py:133"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-c474677086f2d4bc", "name": "Flask mutation route `api_setup` without `@login_required` \u2014 app/server.py:154", "shortDescription": {"text": "Flask mutation route `api_setup` without `@login_required` \u2014 app/server.py:154"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-1af2ddf52864c968", "name": "Flask mutation route `api_credentials` without `@login_required` \u2014 app/server.py:219", "shortDescription": {"text": "Flask mutation route `api_credentials` without `@login_required` \u2014 app/server.py:219"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-abfc6576712434a2", "name": "Flask mutation route `api_devices_prune` without `@login_required` \u2014 app/server.py:230", "shortDescription": {"text": "Flask mutation route `api_devices_prune` without `@login_required` \u2014 app/server.py:230"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-c6a2f3148f28149e", "name": "Flask mutation route `api_device_meta` without `@login_required` \u2014 app/server.py:244", "shortDescription": {"text": "Flask mutation route `api_device_meta` without `@login_required` \u2014 app/server.py:244"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-b70f2f9c4270702c", "name": "Flask mutation route `api_hikvision` without `@login_required` \u2014 app/server.py:263", "shortDescription": {"text": "Flask mutation route `api_hikvision` without `@login_required` \u2014 app/server.py:263"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-3c8022af7ecd662f", "name": "Flask mutation route `api_kuma` without `@login_required` \u2014 app/server.py:306", "shortDescription": {"text": "Flask mutation route `api_kuma` without `@login_required` \u2014 app/server.py:306"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-c163a9f51361a9f1", "name": "Flask mutation route `api_kuma_sync_tags` without `@login_required` \u2014 app/server.py:356", "shortDescription": {"text": "Flask mutation route `api_kuma_sync_tags` without `@login_required` \u2014 app/server.py:356"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-95755d4766b52d51", "name": "Flask mutation route `api_kuma_repair` without `@login_required` \u2014 app/server.py:376", "shortDescription": {"text": "Flask mutation route `api_kuma_repair` without `@login_required` \u2014 app/server.py:376"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-9f7d3e84fe673724", "name": "Flask mutation route `api_kuma_test` without `@login_required` \u2014 app/server.py:402", "shortDescription": {"text": "Flask mutation route `api_kuma_test` without `@login_required` \u2014 app/server.py:402"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-890dd6b0801803e2", "name": "Flask mutation route `api_photo` without `@login_required` \u2014 app/server.py:414", "shortDescription": {"text": "Flask mutation route `api_photo` without `@login_required` \u2014 app/server.py:414"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-9ee1b7bc721243a9", "name": "Flask mutation route `api_wizard` without `@login_required` \u2014 app/server.py:473", "shortDescription": {"text": "Flask mutation route `api_wizard` without `@login_required` \u2014 app/server.py:473"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-3dd04847781e13d5", "name": "Flask mutation route `api_hub_connect` without `@login_required` \u2014 app/server.py:512", "shortDescription": {"text": "Flask mutation route `api_hub_connect` without `@login_required` \u2014 app/server.py:512"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-0f844d13bca8299e", "name": "Flask mutation route `api_hub_disconnect` without `@login_required` \u2014 app/server.py:528", "shortDescription": {"text": "Flask mutation route `api_hub_disconnect` without `@login_required` \u2014 app/server.py:528"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-8d7f565d4bc87b71", "name": "Flask mutation route `api_tunnel` without `@login_required` \u2014 app/server.py:541", "shortDescription": {"text": "Flask mutation route `api_tunnel` without `@login_required` \u2014 app/server.py:541"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-06a691e8887be8c9", "name": "Flask mutation route `api_tunnel_close` without `@login_required` \u2014 app/server.py:557", "shortDescription": {"text": "Flask mutation route `api_tunnel_close` without `@login_required` \u2014 app/server.py:557"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-1a6d91f2236825bf", "name": "Unused endpoint: ANY /", "shortDescription": {"text": "Unused endpoint: ANY /"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-bbbf5e5b0d020b09", "name": "Unused endpoint: ANY /site/<site_id>", "shortDescription": {"text": "Unused endpoint: ANY /site/<site_id>"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /site/<site_id>` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-4c7ad61ba1b23915", "name": "Unused endpoint: ANY /login", "shortDescription": {"text": "Unused endpoint: ANY /login"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /login` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-5b8a18e809010ae2", "name": "Unused endpoint: ANY /app.css", "shortDescription": {"text": "Unused endpoint: ANY /app.css"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /app.css` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-72ac4a22be37196a", "name": "Unused endpoint: ANY /api/auth-state", "shortDescription": {"text": "Unused endpoint: ANY /api/auth-state"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /api/auth-state` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-cee1b1903574e9ca", "name": "Unused endpoint: ANY /api/login", "shortDescription": {"text": "Unused endpoint: ANY /api/login"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /api/login` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8c60a66fb2a1dff2", "name": "Unused endpoint: ANY /api/logout", "shortDescription": {"text": "Unused endpoint: ANY /api/logout"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /api/logout` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8ece8c987ff9c424", "name": "Unused endpoint: ANY /api/health", "shortDescription": {"text": "Unused endpoint: ANY /api/health"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /api/health` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ae4c75fbb388dfa7", "name": "Unused endpoint: ANY /api/hub/overview", "shortDescription": {"text": "Unused endpoint: ANY /api/hub/overview"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /api/hub/overview` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-348b93880fd6d4d6", "name": "Unused endpoint: ANY /api/hub/sites", "shortDescription": {"text": "Unused endpoint: ANY /api/hub/sites"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /api/hub/sites` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-4881c15c06272617", "name": "Unused endpoint: ANY /api/hub/sites/<site_id>", "shortDescription": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /api/hub/sites/<site_id>` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-628c039d0ae41060", "name": "Unused endpoint: ANY /api/hub/wizard", "shortDescription": {"text": "Unused endpoint: ANY /api/hub/wizard"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /api/hub/wizard` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1439e4705488e10f", "name": "Unused endpoint: ANY /api/hub/sites/<site_id>/enroll", "shortDescription": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/enroll"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /api/hub/sites/<site_id>/enroll` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ad6e8e5fa32810e7", "name": "Unused endpoint: ANY /api/hub/sites/<site_id>/devices", "shortDescription": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/devices"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /api/hub/sites/<site_id>/devices` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b6ca1ff4a83ef80e", "name": "Unused endpoint: ANY /api/hub/sites/<site_id>/history/<path:key>", "shortDescription": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/history/<path:key>"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /api/hub/sites/<site_id>/history/<path:key>` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-0887fa8713d68713", "name": "Unused endpoint: ANY /api/hub/sites/<site_id>/command", "shortDescription": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/command"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /api/hub/sites/<site_id>/command` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a136bf0afa624dae", "name": "Unused endpoint: ANY /api/hub/sites/<site_id>/trigger", "shortDescription": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/trigger"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /api/hub/sites/<site_id>/trigger` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f621e35313443387", "name": "Unused endpoint: ANY /api/hub/sites/<site_id>/kuma", "shortDescription": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/kuma"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /api/hub/sites/<site_id>/kuma` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-386930a247dc7e9a", "name": "Unused endpoint: ANY /api/hub/sites/<site_id>/reachability", "shortDescription": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/reachability"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /api/hub/sites/<site_id>/reachability` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e261cb54066ef9a8", "name": "Unused endpoint: ANY /api/hub/sites/<site_id>/poll", "shortDescription": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/poll"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /api/hub/sites/<site_id>/poll` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-0f699a30168d040b", "name": "Unused endpoint: ANY /api/hub/sites/<site_id>/tunnel", "shortDescription": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/tunnel"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /api/hub/sites/<site_id>/tunnel` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-203ed2ace87505a2", "name": "Unused endpoint: ANY /api/hub/sites/<site_id>/tunnels", "shortDescription": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/tunnels"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /api/hub/sites/<site_id>/tunnels` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ed5c8df76ede693d", "name": "Unused endpoint: ANY /api/hub/sites/<site_id>/tunnel/<tid>", "shortDescription": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/tunnel/<tid>"}, "fullDescription": {"text": "`hub/app/server.py` declares `ANY /api/hub/sites/<site_id>/tunnel/<tid>` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-44c7d3a14d8d8103", "name": "Unused endpoint: ANY /setup", "shortDescription": {"text": "Unused endpoint: ANY /setup"}, "fullDescription": {"text": "`app/server.py` declares `ANY /setup` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e1a61ead29e17012", "name": "Unused endpoint: ANY /api/status", "shortDescription": {"text": "Unused endpoint: ANY /api/status"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/status` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-36d677a7715b9807", "name": "Unused endpoint: ANY /api/config", "shortDescription": {"text": "Unused endpoint: ANY /api/config"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/config` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ab2f607bc6844d8f", "name": "Unused endpoint: ANY /api/trigger", "shortDescription": {"text": "Unused endpoint: ANY /api/trigger"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/trigger` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-53ae7003c582ecc1", "name": "Unused endpoint: ANY /api/command", "shortDescription": {"text": "Unused endpoint: ANY /api/command"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/command` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d1b663d768e5b52b", "name": "Unused endpoint: ANY /api/test-ntfy", "shortDescription": {"text": "Unused endpoint: ANY /api/test-ntfy"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/test-ntfy` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-33b8aecc86c57eaa", "name": "Unused endpoint: ANY /api/setup", "shortDescription": {"text": "Unused endpoint: ANY /api/setup"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/setup` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-88ecf3d2670cb720", "name": "Unused endpoint: ANY /api/devices", "shortDescription": {"text": "Unused endpoint: ANY /api/devices"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/devices` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3d089d2588bc4af0", "name": "Unused endpoint: ANY /api/devices/<path:key>/credentials", "shortDescription": {"text": "Unused endpoint: ANY /api/devices/<path:key>/credentials"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/devices/<path:key>/credentials` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f8488fe9b89a1ff4", "name": "Unused endpoint: ANY /api/devices/prune", "shortDescription": {"text": "Unused endpoint: ANY /api/devices/prune"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/devices/prune` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8816c8eaa2073f7d", "name": "Unused endpoint: ANY /api/devices/<path:key>", "shortDescription": {"text": "Unused endpoint: ANY /api/devices/<path:key>"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/devices/<path:key>` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-0b26655a4d246bb1", "name": "Unused endpoint: ANY /api/devices/<path:key>/hikvision", "shortDescription": {"text": "Unused endpoint: ANY /api/devices/<path:key>/hikvision"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/devices/<path:key>/hikvision` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f65ab9840e72849c", "name": "Unused endpoint: ANY /api/devices/<path:key>/health", "shortDescription": {"text": "Unused endpoint: ANY /api/devices/<path:key>/health"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/devices/<path:key>/health` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-667e8093ec0349a1", "name": "Unused endpoint: ANY /api/devices/<path:key>/kuma", "shortDescription": {"text": "Unused endpoint: ANY /api/devices/<path:key>/kuma"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/devices/<path:key>/kuma` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9506b6aab2c5f7fb", "name": "Unused endpoint: ANY /api/kuma/sync-tags", "shortDescription": {"text": "Unused endpoint: ANY /api/kuma/sync-tags"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/kuma/sync-tags` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d77bd8ac3cd28f5c", "name": "Unused endpoint: ANY /api/kuma/repair", "shortDescription": {"text": "Unused endpoint: ANY /api/kuma/repair"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/kuma/repair` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-993914243ad9704f", "name": "Unused endpoint: ANY /api/kuma/test", "shortDescription": {"text": "Unused endpoint: ANY /api/kuma/test"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/kuma/test` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b8d2c78ef58079b7", "name": "Unused endpoint: ANY /api/devices/<path:key>/photo", "shortDescription": {"text": "Unused endpoint: ANY /api/devices/<path:key>/photo"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/devices/<path:key>/photo` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-667b7ba516ce7e33", "name": "Unused endpoint: ANY /api/history/<path:key>", "shortDescription": {"text": "Unused endpoint: ANY /api/history/<path:key>"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/history/<path:key>` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ecfd4e7dd5375629", "name": "Unused endpoint: ANY /api/events", "shortDescription": {"text": "Unused endpoint: ANY /api/events"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/events` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-fde135fa5036e79c", "name": "Unused endpoint: ANY /api/ip-history", "shortDescription": {"text": "Unused endpoint: ANY /api/ip-history"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/ip-history` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1f6824ccf578b278", "name": "Unused endpoint: ANY /api/wizard", "shortDescription": {"text": "Unused endpoint: ANY /api/wizard"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/wizard` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-bb96b4b3db7c092e", "name": "Unused endpoint: ANY /api/hub/status", "shortDescription": {"text": "Unused endpoint: ANY /api/hub/status"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/hub/status` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2656db164e68341d", "name": "Unused endpoint: ANY /api/hub/connect", "shortDescription": {"text": "Unused endpoint: ANY /api/hub/connect"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/hub/connect` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-47ec0e0e1901253d", "name": "Unused endpoint: ANY /api/hub/disconnect", "shortDescription": {"text": "Unused endpoint: ANY /api/hub/disconnect"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/hub/disconnect` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9d826a847eb2e3d3", "name": "Unused endpoint: ANY /api/tunnel", "shortDescription": {"text": "Unused endpoint: ANY /api/tunnel"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/tunnel` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8490becd355fcc70", "name": "Unused endpoint: ANY /api/tunnel/<tid>", "shortDescription": {"text": "Unused endpoint: ANY /api/tunnel/<tid>"}, "fullDescription": {"text": "`app/server.py` declares `ANY /api/tunnel/<tid>` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}]}}, "automationDetails": {"id": "repobility/18102"}, "properties": {"repository": "Riaan007/farm-netwatch", "repoUrl": "https://github.com/Riaan007/farm-netwatch", "branch": "main"}, "results": [{"ruleId": "scanner-ff04aeda444593ca", "level": "note", "message": {"text": "Possibly dead Python function: loop"}, "properties": {"repobilityId": "ef7a4029179da27e", "scanner": "scanner-primary", "fingerprint": "ff04aeda444593ca", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/scanner.py:702"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-cc8a2ae16244f910", "level": "note", "message": {"text": "Possibly dead Python function: is_up"}, "properties": {"repobilityId": "43ba6d3d81f0ac09", "scanner": "scanner-primary", "fingerprint": "cc8a2ae16244f910", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/hubvpn.py:108"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-52fb9c7c691c6d8f", "level": "note", "message": {"text": "Possibly dead Python function: loop"}, "properties": {"repobilityId": "ef7a4029179da27e", "scanner": "scanner-primary", "fingerprint": "52fb9c7c691c6d8f", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/listener.py:52"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-86a64f90bd122ae9", "level": "note", "message": {"text": "Possibly dead Python function: run_ssdp"}, "properties": {"repobilityId": "88d684bee6787c41", "scanner": "scanner-primary", "fingerprint": "86a64f90bd122ae9", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/discovery.py:249"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-ccf6b4f92d5c6cee", "level": "note", "message": {"text": "Possibly dead Python function: run_mdns"}, "properties": {"repobilityId": "38b45d31535eec50", "scanner": "scanner-primary", "fingerprint": "ccf6b4f92d5c6cee", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/discovery.py:252"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-d63da3583b14afc0", "level": "warning", "message": {"text": "Dockerfile runs as root: Dockerfile"}, "properties": {"repobilityId": "a2ed1bd120e507db", "scanner": "scanner-primary", "fingerprint": "d63da3583b14afc0", "layer": "hardware", "severity": "medium", "confidence": 1.0, "tags": ["security", "container"]}}, {"ruleId": "scanner-84019dfd8d98a34d", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: debian:bookworm-slim"}, "properties": {"repobilityId": "94fd44233dc02d63", "scanner": "scanner-primary", "fingerprint": "84019dfd8d98a34d", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "Dockerfile"}, "region": {"startLine": 5}}}]}, {"ruleId": "scanner-ce1fec675e91d850", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: python:3.12-slim-bookworm"}, "properties": {"repobilityId": "d955c9bcae3fda2b", "scanner": "scanner-primary", "fingerprint": "ce1fec675e91d850", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "Dockerfile"}, "region": {"startLine": 25}}}]}, {"ruleId": "scanner-d3a88b67e2ad7e17", "level": "warning", "message": {"text": "Dockerfile runs as root: hub/Dockerfile"}, "properties": {"repobilityId": "320c7646efbb2d9c", "scanner": "scanner-primary", "fingerprint": "d3a88b67e2ad7e17", "layer": "hardware", "severity": "medium", "confidence": 1.0, "tags": ["security", "container"]}}, {"ruleId": "scanner-74ba98032554335e", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: debian:bookworm-slim"}, "properties": {"repobilityId": "36c7db4b4239ff8e", "scanner": "scanner-primary", "fingerprint": "74ba98032554335e", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "hub/Dockerfile"}, "region": {"startLine": 6}}}]}, {"ruleId": "scanner-80f458688e94c28e", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: python:3.12-slim-bookworm"}, "properties": {"repobilityId": "869d21ebef63d5d9", "scanner": "scanner-primary", "fingerprint": "80f458688e94c28e", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "hub/Dockerfile"}, "region": {"startLine": 26}}}]}, {"ruleId": "scanner-aa5acaa49eb8315b", "level": "note", "message": {"text": "Containers defined but no K8s/orchestration manifest found"}, "properties": {"repobilityId": "b230ea9b68736081", "scanner": "scanner-primary", "fingerprint": "aa5acaa49eb8315b", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["coverage", "deployment"]}}, {"ruleId": "scanner-9710c8d059e53154", "level": "none", "message": {"text": "No frontend routes/components detected"}, "properties": {"repobilityId": "44ca61485762e494", "scanner": "scanner-primary", "fingerprint": "9710c8d059e53154", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["coverage"]}}, {"ruleId": "scanner-82c03ef7f12b7cac", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in hub/app/static/site.html:257"}, "properties": {"repobilityId": "52f67887d8845d78", "scanner": "scanner-primary", "fingerprint": "82c03ef7f12b7cac", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "hub/app/static/site.html"}, "region": {"startLine": 257}}}]}, {"ruleId": "scanner-087330ce88937f9c", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in hub/app/static/index.html:232"}, "properties": {"repobilityId": "ea521dd52fbbbb05", "scanner": "scanner-primary", "fingerprint": "087330ce88937f9c", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "hub/app/static/index.html"}, "region": {"startLine": 232}}}]}, {"ruleId": "scanner-b4cabcdb18b98bfe", "level": "error", "message": {"text": "Insecure pattern 'tls_verify_false' in app/hikvision.py:40"}, "properties": {"repobilityId": "de3511b0757f7817", "scanner": "scanner-primary", "fingerprint": "b4cabcdb18b98bfe", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["owasp", "tls_verify_false"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/hikvision.py"}, "region": {"startLine": 40}}}]}, {"ruleId": "scanner-b2ec0ebe6a02f71a", "level": "error", "message": {"text": "Insecure pattern 'tls_verify_false' in app/identify.py:119"}, "properties": {"repobilityId": "75952d2501f83559", "scanner": "scanner-primary", "fingerprint": "b2ec0ebe6a02f71a", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["owasp", "tls_verify_false"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/identify.py"}, "region": {"startLine": 119}}}]}, {"ruleId": "scanner-52a0e9989b662fff", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in app/static/index.html:435"}, "properties": {"repobilityId": "a97dfede071e5ef1", "scanner": "scanner-primary", "fingerprint": "52a0e9989b662fff", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/static/index.html"}, "region": {"startLine": 435}}}]}, {"ruleId": "scanner-632c6e30e35f8e5c", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in app/static/setup.html:104"}, "properties": {"repobilityId": "30284bf6fa37f286", "scanner": "scanner-primary", "fingerprint": "632c6e30e35f8e5c", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/static/setup.html"}, "region": {"startLine": 104}}}]}, {"ruleId": "scanner-6372cebde0220094", "level": "warning", "message": {"text": "No auth library detected"}, "properties": {"repobilityId": "a5b6035a5bbf8054", "scanner": "scanner-primary", "fingerprint": "6372cebde0220094", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["coverage", "auth"]}}, {"ruleId": "scanner-6ba9bfab5f283202", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "74426512dcdd6034", "scanner": "scanner-primary", "fingerprint": "6ba9bfab5f283202", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/build.yml"}, "region": {"startLine": 22}}}]}, {"ruleId": "scanner-6ba9bfab5f283202", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "4ec74db6e1e49776", "scanner": "scanner-primary", "fingerprint": "6ba9bfab5f283202", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/build.yml"}, "region": {"startLine": 25}}}]}, {"ruleId": "scanner-6ba9bfab5f283202", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "e0130f45ae8f6a41", "scanner": "scanner-primary", "fingerprint": "6ba9bfab5f283202", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/build.yml"}, "region": {"startLine": 28}}}]}, {"ruleId": "scanner-6ba9bfab5f283202", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "8c93e56a7aa6c92c", "scanner": "scanner-primary", "fingerprint": "6ba9bfab5f283202", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/build.yml"}, "region": {"startLine": 36}}}]}, {"ruleId": "scanner-6ba9bfab5f283202", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "3a255e942786f887", "scanner": "scanner-primary", "fingerprint": "6ba9bfab5f283202", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/build.yml"}, "region": {"startLine": 45}}}]}, {"ruleId": "scanner-b769174c9fcf8ea8", "level": "warning", "message": {"text": "GitHub Actions workflow grants broad write permissions"}, "properties": {"repobilityId": "e34b6cb9b56931d2", "scanner": "scanner-primary", "fingerprint": "b769174c9fcf8ea8", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "least-privilege"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/build.yml"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-6893a6c8b0861585", "level": "warning", "message": {"text": "Very low test-to-source ratio"}, "properties": {"repobilityId": "54a7de3f06314bf0", "scanner": "scanner-primary", "fingerprint": "6893a6c8b0861585", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["tests", "coverage"]}}, {"ruleId": "scanner-141b30a41e03817b", "level": "note", "message": {"text": "No license file detected"}, "properties": {"repobilityId": "4ff65397288d1241", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "a0de3514163e276a", "scanner": "scanner-primary", "fingerprint": "3ab5d313dda8e5f9", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["debug", "cleanup", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-2d0c7b7ab8f8aacf", "level": "warning", "message": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "properties": {"repobilityId": "4eec6bb12618361b", "scanner": "scanner-primary", "fingerprint": "2d0c7b7ab8f8aacf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "critical-flow", "generated-repo-pattern"]}}, {"ruleId": "scanner-11825279136b53a3", "level": "warning", "message": {"text": "CI is configured but no tests are detected"}, "properties": {"repobilityId": "eae1f30291fc538d", "scanner": "scanner-primary", "fingerprint": "11825279136b53a3", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["tests", "ci", "config-theater", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-b9088664ace7f748", "level": "note", "message": {"text": "Composite production-readiness gap"}, "properties": {"repobilityId": "5402263eb5fefe7e", "scanner": "scanner-primary", "fingerprint": "b9088664ace7f748", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["production-readiness", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-ea8f3013f588db25", "level": "note", "message": {"text": "Shallow git history limits provenance confidence"}, "properties": {"repobilityId": "ba80b3d811f94c4c", "scanner": "scanner-primary", "fingerprint": "ea8f3013f588db25", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-8424db9c75e04ba4", "level": "none", "message": {"text": "Very short observed git history"}, "properties": {"repobilityId": "9fdd18e7729a235c", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-ca236c58db7c90f8", "level": "none", "message": {"text": "Commented-code block (8 lines) in hub/app/hubconfig.py:36"}, "properties": {"repobilityId": "16552942944376f2", "scanner": "scanner-primary", "fingerprint": "ca236c58db7c90f8", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-603dc4567c54d32d", "level": "none", "message": {"text": "Commented-code block (5 lines) in hub/app/server.py:251"}, "properties": {"repobilityId": "c379b85ab3c16a49", "scanner": "scanner-primary", "fingerprint": "603dc4567c54d32d", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-8e047ab7af03962f", "level": "note", "message": {"text": "7 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "5a0455f6498c27ad", "scanner": "scanner-primary", "fingerprint": "8e047ab7af03962f", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}, {"ruleId": "scanner-49c98f7cedd9c977", "level": "note", "message": {"text": "Near-duplicate function bodies in 4 places"}, "properties": {"repobilityId": "180bf7be19853271", "scanner": "scanner-primary", "fingerprint": "49c98f7cedd9c977", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "a1cc07759582df3f", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-49c98f7cedd9c977", "level": "note", "message": {"text": "Near-duplicate function bodies in 4 places"}, "properties": {"repobilityId": "f1cc879b58ebfce9", "scanner": "scanner-primary", "fingerprint": "49c98f7cedd9c977", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "898fafaed84c9a93", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "360c8ce8fab3cfad", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "9bfb23eb07966e67", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "37442ffcaf0d4fbc", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-20988bb37defafcb", "level": "error", "message": {"text": "Flask mutation route `api_login` without `@login_required` \u2014 hub/app/server.py:83"}, "properties": {"repobilityId": "9864387a8067a616", "scanner": "scanner-primary", "fingerprint": "20988bb37defafcb", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "hub/app/server.py"}, "region": {"startLine": 83}}}]}, {"ruleId": "scanner-b6f4dc2e7e31d49f", "level": "error", "message": {"text": "Flask mutation route `api_logout` without `@login_required` \u2014 hub/app/server.py:106"}, "properties": {"repobilityId": "2b42d26967131ad8", "scanner": "scanner-primary", "fingerprint": "b6f4dc2e7e31d49f", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "hub/app/server.py"}, "region": {"startLine": 106}}}]}, {"ruleId": "scanner-56ea97ecce3595c1", "level": "error", "message": {"text": "Flask mutation route `api_sites` without `@login_required` \u2014 hub/app/server.py:198"}, "properties": {"repobilityId": "4f783a1330b43d30", "scanner": "scanner-primary", "fingerprint": "56ea97ecce3595c1", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "hub/app/server.py"}, "region": {"startLine": 198}}}]}, {"ruleId": "scanner-e1a0d12017d5c5ca", "level": "error", "message": {"text": "Flask mutation route `api_site` without `@login_required` \u2014 hub/app/server.py:214"}, "properties": {"repobilityId": "ea97b5431cda8e93", "scanner": "scanner-primary", "fingerprint": "e1a0d12017d5c5ca", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "hub/app/server.py"}, "region": {"startLine": 214}}}]}, {"ruleId": "scanner-d6e94b7cdb8f6dc9", "level": "error", "message": {"text": "Flask mutation route `api_hub_wizard` without `@login_required` \u2014 hub/app/server.py:275"}, "properties": {"repobilityId": "6d1e71853a7f2ae6", "scanner": "scanner-primary", "fingerprint": "d6e94b7cdb8f6dc9", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "hub/app/server.py"}, "region": {"startLine": 275}}}]}, {"ruleId": "scanner-fc4d832ea5002ca5", "level": "error", "message": {"text": "Flask mutation route `api_site_command` without `@login_required` \u2014 hub/app/server.py:375"}, "properties": {"repobilityId": "6e0b8f91e0c7a260", "scanner": "scanner-primary", "fingerprint": "fc4d832ea5002ca5", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "hub/app/server.py"}, "region": {"startLine": 375}}}]}, {"ruleId": "scanner-6c499899b45ca347", "level": "error", "message": {"text": "Flask mutation route `api_site_trigger` without `@login_required` \u2014 hub/app/server.py:393"}, "properties": {"repobilityId": "c95885cc1dd68548", "scanner": "scanner-primary", "fingerprint": "6c499899b45ca347", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "hub/app/server.py"}, "region": {"startLine": 393}}}]}, {"ruleId": "scanner-2be017c1b0384cb5", "level": "error", "message": {"text": "Flask mutation route `api_site_poll` without `@login_required` \u2014 hub/app/server.py:431"}, "properties": {"repobilityId": "6e926f94fefc1e29", "scanner": "scanner-primary", "fingerprint": "2be017c1b0384cb5", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "hub/app/server.py"}, "region": {"startLine": 431}}}]}, {"ruleId": "scanner-1cf3126c5bc30402", "level": "error", "message": {"text": "Flask mutation route `api_site_tunnel` without `@login_required` \u2014 hub/app/server.py:441"}, "properties": {"repobilityId": "ac1f71ae53c7152a", "scanner": "scanner-primary", "fingerprint": "1cf3126c5bc30402", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "hub/app/server.py"}, "region": {"startLine": 441}}}]}, {"ruleId": "scanner-8e8b4939ae93747a", "level": "error", "message": {"text": "Flask mutation route `api_site_tunnel_close` without `@login_required` \u2014 hub/app/server.py:464"}, "properties": {"repobilityId": "7e28e0ab9e1e5aad", "scanner": "scanner-primary", "fingerprint": "8e8b4939ae93747a", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "hub/app/server.py"}, "region": {"startLine": 464}}}]}, {"ruleId": "scanner-80c052daf6067863", "level": "error", "message": {"text": "Flask mutation route `api_config` without `@login_required` \u2014 app/server.py:90"}, "properties": {"repobilityId": "ffa377faa7e28f84", "scanner": "scanner-primary", "fingerprint": "80c052daf6067863", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/server.py"}, "region": {"startLine": 90}}}]}, {"ruleId": "scanner-6d150049c2cfcb20", "level": "error", "message": {"text": "Flask mutation route `api_trigger` without `@login_required` \u2014 app/server.py:100"}, "properties": {"repobilityId": "456cd78010fa06f9", "scanner": "scanner-primary", "fingerprint": "6d150049c2cfcb20", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/server.py"}, "region": {"startLine": 100}}}]}, {"ruleId": "scanner-d59472a45e420c11", "level": "error", "message": {"text": "Flask mutation route `api_command` without `@login_required` \u2014 app/server.py:113"}, "properties": {"repobilityId": "a5bd8eb1e12fc828", "scanner": "scanner-primary", "fingerprint": "d59472a45e420c11", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/server.py"}, "region": {"startLine": 113}}}]}, {"ruleId": "scanner-f7c54aed07c5ed60", "level": "error", "message": {"text": "Flask mutation route `api_test_ntfy` without `@login_required` \u2014 app/server.py:133"}, "properties": {"repobilityId": "e8a487ba8d8d801e", "scanner": "scanner-primary", "fingerprint": "f7c54aed07c5ed60", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/server.py"}, "region": {"startLine": 133}}}]}, {"ruleId": "scanner-c474677086f2d4bc", "level": "error", "message": {"text": "Flask mutation route `api_setup` without `@login_required` \u2014 app/server.py:154"}, "properties": {"repobilityId": "ca0eacd518c84376", "scanner": "scanner-primary", "fingerprint": "c474677086f2d4bc", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/server.py"}, "region": {"startLine": 154}}}]}, {"ruleId": "scanner-1af2ddf52864c968", "level": "error", "message": {"text": "Flask mutation route `api_credentials` without `@login_required` \u2014 app/server.py:219"}, "properties": {"repobilityId": "81b836a02038c8ac", "scanner": "scanner-primary", "fingerprint": "1af2ddf52864c968", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/server.py"}, "region": {"startLine": 219}}}]}, {"ruleId": "scanner-abfc6576712434a2", "level": "error", "message": {"text": "Flask mutation route `api_devices_prune` without `@login_required` \u2014 app/server.py:230"}, "properties": {"repobilityId": "198db7669ae9f655", "scanner": "scanner-primary", "fingerprint": "abfc6576712434a2", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/server.py"}, "region": {"startLine": 230}}}]}, {"ruleId": "scanner-c6a2f3148f28149e", "level": "error", "message": {"text": "Flask mutation route `api_device_meta` without `@login_required` \u2014 app/server.py:244"}, "properties": {"repobilityId": "f70636b960c329e8", "scanner": "scanner-primary", "fingerprint": "c6a2f3148f28149e", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/server.py"}, "region": {"startLine": 244}}}]}, {"ruleId": "scanner-b70f2f9c4270702c", "level": "error", "message": {"text": "Flask mutation route `api_hikvision` without `@login_required` \u2014 app/server.py:263"}, "properties": {"repobilityId": "49b8a87048802284", "scanner": "scanner-primary", "fingerprint": "b70f2f9c4270702c", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/server.py"}, "region": {"startLine": 263}}}]}, {"ruleId": "scanner-3c8022af7ecd662f", "level": "error", "message": {"text": "Flask mutation route `api_kuma` without `@login_required` \u2014 app/server.py:306"}, "properties": {"repobilityId": "5d0f04b736648c29", "scanner": "scanner-primary", "fingerprint": "3c8022af7ecd662f", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/server.py"}, "region": {"startLine": 306}}}]}, {"ruleId": "scanner-c163a9f51361a9f1", "level": "error", "message": {"text": "Flask mutation route `api_kuma_sync_tags` without `@login_required` \u2014 app/server.py:356"}, "properties": {"repobilityId": "405a2cfe43b150c8", "scanner": "scanner-primary", "fingerprint": "c163a9f51361a9f1", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/server.py"}, "region": {"startLine": 356}}}]}, {"ruleId": "scanner-95755d4766b52d51", "level": "error", "message": {"text": "Flask mutation route `api_kuma_repair` without `@login_required` \u2014 app/server.py:376"}, "properties": {"repobilityId": "ceb116b162614309", "scanner": "scanner-primary", "fingerprint": "95755d4766b52d51", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/server.py"}, "region": {"startLine": 376}}}]}, {"ruleId": "scanner-9f7d3e84fe673724", "level": "error", "message": {"text": "Flask mutation route `api_kuma_test` without `@login_required` \u2014 app/server.py:402"}, "properties": {"repobilityId": "e69fb61eff967e48", "scanner": "scanner-primary", "fingerprint": "9f7d3e84fe673724", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/server.py"}, "region": {"startLine": 402}}}]}, {"ruleId": "scanner-890dd6b0801803e2", "level": "error", "message": {"text": "Flask mutation route `api_photo` without `@login_required` \u2014 app/server.py:414"}, "properties": {"repobilityId": "9ae2963a9580cb4d", "scanner": "scanner-primary", "fingerprint": "890dd6b0801803e2", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/server.py"}, "region": {"startLine": 414}}}]}, {"ruleId": "scanner-9ee1b7bc721243a9", "level": "error", "message": {"text": "Flask mutation route `api_wizard` without `@login_required` \u2014 app/server.py:473"}, "properties": {"repobilityId": "44a15186c5a20a1f", "scanner": "scanner-primary", "fingerprint": "9ee1b7bc721243a9", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/server.py"}, "region": {"startLine": 473}}}]}, {"ruleId": "scanner-3dd04847781e13d5", "level": "error", "message": {"text": "Flask mutation route `api_hub_connect` without `@login_required` \u2014 app/server.py:512"}, "properties": {"repobilityId": "eeeb48dfc092a9c7", "scanner": "scanner-primary", "fingerprint": "3dd04847781e13d5", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/server.py"}, "region": {"startLine": 512}}}]}, {"ruleId": "scanner-0f844d13bca8299e", "level": "error", "message": {"text": "Flask mutation route `api_hub_disconnect` without `@login_required` \u2014 app/server.py:528"}, "properties": {"repobilityId": "cb5478d2249f8412", "scanner": "scanner-primary", "fingerprint": "0f844d13bca8299e", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/server.py"}, "region": {"startLine": 528}}}]}, {"ruleId": "scanner-8d7f565d4bc87b71", "level": "error", "message": {"text": "Flask mutation route `api_tunnel` without `@login_required` \u2014 app/server.py:541"}, "properties": {"repobilityId": "96482a5d332f13c1", "scanner": "scanner-primary", "fingerprint": "8d7f565d4bc87b71", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/server.py"}, "region": {"startLine": 541}}}]}, {"ruleId": "scanner-06a691e8887be8c9", "level": "error", "message": {"text": "Flask mutation route `api_tunnel_close` without `@login_required` \u2014 app/server.py:557"}, "properties": {"repobilityId": "9ecccf068819918d", "scanner": "scanner-primary", "fingerprint": "06a691e8887be8c9", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "app/server.py"}, "region": {"startLine": 557}}}]}, {"ruleId": "scanner-1a6d91f2236825bf", "level": "note", "message": {"text": "Unused endpoint: ANY /"}, "properties": {"repobilityId": "a228c0711652da5d", "scanner": "scanner-primary", "fingerprint": "1a6d91f2236825bf", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-bbbf5e5b0d020b09", "level": "note", "message": {"text": "Unused endpoint: ANY /site/<site_id>"}, "properties": {"repobilityId": "e3ed627245ae6feb", "scanner": "scanner-primary", "fingerprint": "bbbf5e5b0d020b09", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-4c7ad61ba1b23915", "level": "note", "message": {"text": "Unused endpoint: ANY /login"}, "properties": {"repobilityId": "bbfef234751dd50c", "scanner": "scanner-primary", "fingerprint": "4c7ad61ba1b23915", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-5b8a18e809010ae2", "level": "note", "message": {"text": "Unused endpoint: ANY /app.css"}, "properties": {"repobilityId": "1e3486ecd0614b97", "scanner": "scanner-primary", "fingerprint": "5b8a18e809010ae2", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-72ac4a22be37196a", "level": "note", "message": {"text": "Unused endpoint: ANY /api/auth-state"}, "properties": {"repobilityId": "64e6ae68f69c7c9d", "scanner": "scanner-primary", "fingerprint": "72ac4a22be37196a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-cee1b1903574e9ca", "level": "note", "message": {"text": "Unused endpoint: ANY /api/login"}, "properties": {"repobilityId": "e6da98365ddffa04", "scanner": "scanner-primary", "fingerprint": "cee1b1903574e9ca", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-8c60a66fb2a1dff2", "level": "note", "message": {"text": "Unused endpoint: ANY /api/logout"}, "properties": {"repobilityId": "21c23bf32b4c17f5", "scanner": "scanner-primary", "fingerprint": "8c60a66fb2a1dff2", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-8ece8c987ff9c424", "level": "note", "message": {"text": "Unused endpoint: ANY /api/health"}, "properties": {"repobilityId": "657afdccb818f394", "scanner": "scanner-primary", "fingerprint": "8ece8c987ff9c424", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ae4c75fbb388dfa7", "level": "note", "message": {"text": "Unused endpoint: ANY /api/hub/overview"}, "properties": {"repobilityId": "afbbadfb49332625", "scanner": "scanner-primary", "fingerprint": "ae4c75fbb388dfa7", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-348b93880fd6d4d6", "level": "note", "message": {"text": "Unused endpoint: ANY /api/hub/sites"}, "properties": {"repobilityId": "c0ee8bf699ff5d04", "scanner": "scanner-primary", "fingerprint": "348b93880fd6d4d6", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-4881c15c06272617", "level": "note", "message": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>"}, "properties": {"repobilityId": "0d01c57f804043d8", "scanner": "scanner-primary", "fingerprint": "4881c15c06272617", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-628c039d0ae41060", "level": "note", "message": {"text": "Unused endpoint: ANY /api/hub/wizard"}, "properties": {"repobilityId": "d018b855c4d37e8e", "scanner": "scanner-primary", "fingerprint": "628c039d0ae41060", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1439e4705488e10f", "level": "note", "message": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/enroll"}, "properties": {"repobilityId": "600fc6de29e9db1c", "scanner": "scanner-primary", "fingerprint": "1439e4705488e10f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ad6e8e5fa32810e7", "level": "note", "message": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/devices"}, "properties": {"repobilityId": "bd26661a4854609c", "scanner": "scanner-primary", "fingerprint": "ad6e8e5fa32810e7", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b6ca1ff4a83ef80e", "level": "note", "message": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/history/<path:key>"}, "properties": {"repobilityId": "9a82df5f724f0b0c", "scanner": "scanner-primary", "fingerprint": "b6ca1ff4a83ef80e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0887fa8713d68713", "level": "note", "message": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/command"}, "properties": {"repobilityId": "8335c1f642d24d6b", "scanner": "scanner-primary", "fingerprint": "0887fa8713d68713", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-a136bf0afa624dae", "level": "note", "message": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/trigger"}, "properties": {"repobilityId": "4ae17977849f920c", "scanner": "scanner-primary", "fingerprint": "a136bf0afa624dae", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-f621e35313443387", "level": "note", "message": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/kuma"}, "properties": {"repobilityId": "84f551e66e024479", "scanner": "scanner-primary", "fingerprint": "f621e35313443387", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-386930a247dc7e9a", "level": "note", "message": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/reachability"}, "properties": {"repobilityId": "972a2b3f8fa50d54", "scanner": "scanner-primary", "fingerprint": "386930a247dc7e9a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e261cb54066ef9a8", "level": "note", "message": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/poll"}, "properties": {"repobilityId": "eff61bd313f8cb58", "scanner": "scanner-primary", "fingerprint": "e261cb54066ef9a8", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0f699a30168d040b", "level": "note", "message": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/tunnel"}, "properties": {"repobilityId": "1056f53831300eb4", "scanner": "scanner-primary", "fingerprint": "0f699a30168d040b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-203ed2ace87505a2", "level": "note", "message": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/tunnels"}, "properties": {"repobilityId": "632a8d26b67fe921", "scanner": "scanner-primary", "fingerprint": "203ed2ace87505a2", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ed5c8df76ede693d", "level": "note", "message": {"text": "Unused endpoint: ANY /api/hub/sites/<site_id>/tunnel/<tid>"}, "properties": {"repobilityId": "5833032fb481e2ed", "scanner": "scanner-primary", "fingerprint": "ed5c8df76ede693d", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-44c7d3a14d8d8103", "level": "note", "message": {"text": "Unused endpoint: ANY /setup"}, "properties": {"repobilityId": "1a1ef09722ddef20", "scanner": "scanner-primary", "fingerprint": "44c7d3a14d8d8103", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e1a61ead29e17012", "level": "note", "message": {"text": "Unused endpoint: ANY /api/status"}, "properties": {"repobilityId": "0983f5ee09bc3b82", "scanner": "scanner-primary", "fingerprint": "e1a61ead29e17012", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-36d677a7715b9807", "level": "note", "message": {"text": "Unused endpoint: ANY /api/config"}, "properties": {"repobilityId": "4e76a593f6404c3b", "scanner": "scanner-primary", "fingerprint": "36d677a7715b9807", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ab2f607bc6844d8f", "level": "note", "message": {"text": "Unused endpoint: ANY /api/trigger"}, "properties": {"repobilityId": "24f2f663488f3173", "scanner": "scanner-primary", "fingerprint": "ab2f607bc6844d8f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-53ae7003c582ecc1", "level": "note", "message": {"text": "Unused endpoint: ANY /api/command"}, "properties": {"repobilityId": "2b5605c968643cb8", "scanner": "scanner-primary", "fingerprint": "53ae7003c582ecc1", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d1b663d768e5b52b", "level": "note", "message": {"text": "Unused endpoint: ANY /api/test-ntfy"}, "properties": {"repobilityId": "6340939adb94bfa3", "scanner": "scanner-primary", "fingerprint": "d1b663d768e5b52b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-33b8aecc86c57eaa", "level": "note", "message": {"text": "Unused endpoint: ANY /api/setup"}, "properties": {"repobilityId": "e9dccdc9b2f67705", "scanner": "scanner-primary", "fingerprint": "33b8aecc86c57eaa", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-88ecf3d2670cb720", "level": "note", "message": {"text": "Unused endpoint: ANY /api/devices"}, "properties": {"repobilityId": "aeb894eaaec2b0a4", "scanner": "scanner-primary", "fingerprint": "88ecf3d2670cb720", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-3d089d2588bc4af0", "level": "note", "message": {"text": "Unused endpoint: ANY /api/devices/<path:key>/credentials"}, "properties": {"repobilityId": "7c3db60ba58d832b", "scanner": "scanner-primary", "fingerprint": "3d089d2588bc4af0", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-f8488fe9b89a1ff4", "level": "note", "message": {"text": "Unused endpoint: ANY /api/devices/prune"}, "properties": {"repobilityId": "ee9ba57169283866", "scanner": "scanner-primary", "fingerprint": "f8488fe9b89a1ff4", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-8816c8eaa2073f7d", "level": "note", "message": {"text": "Unused endpoint: ANY /api/devices/<path:key>"}, "properties": {"repobilityId": "104c7080b0dc97ee", "scanner": "scanner-primary", "fingerprint": "8816c8eaa2073f7d", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0b26655a4d246bb1", "level": "note", "message": {"text": "Unused endpoint: ANY /api/devices/<path:key>/hikvision"}, "properties": {"repobilityId": "21c32bac7d14e5ef", "scanner": "scanner-primary", "fingerprint": "0b26655a4d246bb1", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-f65ab9840e72849c", "level": "note", "message": {"text": "Unused endpoint: ANY /api/devices/<path:key>/health"}, "properties": {"repobilityId": "6b985f347a40bfb3", "scanner": "scanner-primary", "fingerprint": "f65ab9840e72849c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-667e8093ec0349a1", "level": "note", "message": {"text": "Unused endpoint: ANY /api/devices/<path:key>/kuma"}, "properties": {"repobilityId": "8ed520f2f69d77dc", "scanner": "scanner-primary", "fingerprint": "667e8093ec0349a1", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-9506b6aab2c5f7fb", "level": "note", "message": {"text": "Unused endpoint: ANY /api/kuma/sync-tags"}, "properties": {"repobilityId": "1da6402caf4ce45e", "scanner": "scanner-primary", "fingerprint": "9506b6aab2c5f7fb", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d77bd8ac3cd28f5c", "level": "note", "message": {"text": "Unused endpoint: ANY /api/kuma/repair"}, "properties": {"repobilityId": "c4d12f068806f317", "scanner": "scanner-primary", "fingerprint": "d77bd8ac3cd28f5c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-993914243ad9704f", "level": "note", "message": {"text": "Unused endpoint: ANY /api/kuma/test"}, "properties": {"repobilityId": "fa61548f7c6c30b3", "scanner": "scanner-primary", "fingerprint": "993914243ad9704f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b8d2c78ef58079b7", "level": "note", "message": {"text": "Unused endpoint: ANY /api/devices/<path:key>/photo"}, "properties": {"repobilityId": "73f1cf38554a17f2", "scanner": "scanner-primary", "fingerprint": "b8d2c78ef58079b7", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-667b7ba516ce7e33", "level": "note", "message": {"text": "Unused endpoint: ANY /api/history/<path:key>"}, "properties": {"repobilityId": "169689c70fdd79dc", "scanner": "scanner-primary", "fingerprint": "667b7ba516ce7e33", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ecfd4e7dd5375629", "level": "note", "message": {"text": "Unused endpoint: ANY /api/events"}, "properties": {"repobilityId": "81cfc27894055d09", "scanner": "scanner-primary", "fingerprint": "ecfd4e7dd5375629", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-fde135fa5036e79c", "level": "note", "message": {"text": "Unused endpoint: ANY /api/ip-history"}, "properties": {"repobilityId": "859f81803dd0de3a", "scanner": "scanner-primary", "fingerprint": "fde135fa5036e79c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1f6824ccf578b278", "level": "note", "message": {"text": "Unused endpoint: ANY /api/wizard"}, "properties": {"repobilityId": "d7f6e06fe697bc39", "scanner": "scanner-primary", "fingerprint": "1f6824ccf578b278", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-bb96b4b3db7c092e", "level": "note", "message": {"text": "Unused endpoint: ANY /api/hub/status"}, "properties": {"repobilityId": "1f66534d94565dcb", "scanner": "scanner-primary", "fingerprint": "bb96b4b3db7c092e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-2656db164e68341d", "level": "note", "message": {"text": "Unused endpoint: ANY /api/hub/connect"}, "properties": {"repobilityId": "f24ee436bc885470", "scanner": "scanner-primary", "fingerprint": "2656db164e68341d", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-47ec0e0e1901253d", "level": "note", "message": {"text": "Unused endpoint: ANY /api/hub/disconnect"}, "properties": {"repobilityId": "b1feba509547d4a5", "scanner": "scanner-primary", "fingerprint": "47ec0e0e1901253d", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-9d826a847eb2e3d3", "level": "note", "message": {"text": "Unused endpoint: ANY /api/tunnel"}, "properties": {"repobilityId": "88a96b5c08716096", "scanner": "scanner-primary", "fingerprint": "9d826a847eb2e3d3", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-8490becd355fcc70", "level": "note", "message": {"text": "Unused endpoint: ANY /api/tunnel/<tid>"}, "properties": {"repobilityId": "a94240f64628028e", "scanner": "scanner-primary", "fingerprint": "8490becd355fcc70", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}]}]}