{"verdict":"FAIL","findings":[{"severity":"P2","file":"scripts/health/health_dashboard_server.py","line":547,"reason":"The Origin validator compares hostname and explicit port but never binds the Origin scheme to the scheme serving the request. Consequently, an Origin with the same authority but the opposite scheme is accepted for browser-session bootstrap and nutrition-mapping POSTs, contrary to the exact-origin CSRF boundary.","fix":"Derive the canonical externally served scheme from a trusted server configuration and require scheme, canonical host, and effective port to match exactly. Add a fresh-session test using the same host/port with only http/https changed and assert rejection before queue mutation."},{"severity":"P2","file":"scripts/health/health_dashboard_action_worker.py","line":927,"reason":"Catalog validation is conditional on mapping_method being sighi_reference or local_alias. A tampered exact-shape form can submit mapping_method=manual_review or ingredient_label with an arbitrary canonical_food and score, and the worker will write that medical classification without proving it exists in the trusted local catalog.","fix":"For every assign decision, resolve canonical_food in histamine_food_rules and require the submitted score to match the catalog row, independently of the browser-supplied mapping_method. Derive method, confidence, source label, and source version server-side where possible, and add adversarial manual_review/ingredient_label tests."},{"severity":"P2","file":"scripts/health/health_dashboard_action_worker.py","line":873,"reason":"The preview revalidation is not protected by a write transaction. Entering `with connection` does not begin a SQLite transaction; resolve_mapping_group and the full target-row scan run before the first write at line 916. Another writer can change the target after validation but before the transaction begins, allowing a stale decision to be applied.","fix":"Assert the existing schema before processing, execute BEGIN IMMEDIATE before resolving the group, and perform revision/count validation plus all mutations in that same transaction. Do not run schema-changing executescript calls in this action path."},{"severity":"P2","file":"scripts/health/dashboard_v5/nutrition_mapping_review.py","line":104,"reason":"target_revision covers nutrition target rows only and omits the current review state/latest action-log revision. Non-mapping actions such as defer, irrelevant, conflict, and reopen do not alter the hashed rows, so a stale page can later submit another state action with the same revision and counts and overwrite the newer review decision.","fix":"Bind the preview to an expected review-state revision that includes the latest applicable action-log identity/hash or monotonic sequence. Recompute and compare it under the same BEGIN IMMEDIATE transaction before applying any action."},{"severity":"P2","file":"scripts/health/dashboard_v5/nutrition_mapping_review.py","line":245,"reason":"The new review provider selects and materializes every nutrition item, then separately loads complete queue, action-log, rule, alias, and composite tables. The API's 120-group check occurs only after all rows have been read and grouped, so an authenticated request or bundle generation has no SQL-level raw-row ceiling and can consume unbounded memory and CPU as history grows.","fix":"Add explicit SQL/cursor-level ceilings with one extra row for overflow detection, fail closed with row_limit_exceeded before grouping, and bound every optional supporting-table query. Add a synthetic overflow test proving the limit is enforced before full materialization."},{"severity":"P3","file":"scripts/health/dashboard_v5/nutrition_mapping_review.py","line":141,"reason":"canonical_food and category are copied from local catalog rows into the browser contract without the existing privacy-safe metadata sanitizer. These values are rendered directly in the mapping selector and category preview, so a malformed catalog value containing a filesystem path, URL, identifier-like technical text, or raw source detail can reach the UI.","fix":"Validate catalog display fields through the shared path/URL/technical-source-safe metadata sanitizer before returning them, omit or fail closed on rejected rows, and add end-to-end catalog fixtures containing POSIX, Windows/UNC, URL, traversal, and Drive-token-like values."}]}