security(gate3): Security-Review-Haertung ueber 4 Pakete (luna-pro)

Phase 6 / Gate 3 — Security-Review auf den fertigen Code, 4 thematische Pakete:
- P1 Secrets+Injection (client/phraser/diagnostics): validate haertet URL/Entity/
  Unicode-Umgehungen (// , &entity; , Cc/Cf/Zl/Zp); kein Key-Leak.
- P2 XSS+externe (card/ha_entity/frontend): kein XSS; DoS-Caps (Forecast 400, Karte 60).
- P3 Mutator+Startup (coordinator/__init__/const): nicht-blockierender Startup via
  Background-Task, LLM-/Store-Ops defensiv, weather_entity_id-Guard, build_items
  NaN/inf+Caps, Warn-Log ohne Secret.
- P4 Flows (config_flow): test_entity exception-frei, _clean_item defensiv, finite
  Bandgrenzen + sanitized_options-Normalisierung, echte bool-Coercion, Typ-Log.
- 24 Findings, 14 uebernommen (mit Regressionstests), 10 verworfen mit Evidenz.
  Suite gruen 188/188. Gate 3 BESTANDEN.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nora 2026-07-13 16:01:31 +00:00
parent 9a74d40194
commit aae8c38a20
11 changed files with 223 additions and 44 deletions

View file

@ -98,6 +98,20 @@ def test_validate_requires_all_items_and_gaps() -> None:
assert phraser.validate("Zieh das Thermoshirt und die Jeans an, guten Morgen dir.", rec) is None
def test_validate_rejects_advanced_bypasses() -> None:
rec = _rec(item_names=("Thermoshirt", "Jeans"))
body = "Thermoshirt und Jeans, Handschuhe fehlen. "
# protocol-relative + HTML-entity encoded schemes
assert phraser.validate(body + "//attacker.example", rec) is None
assert phraser.validate(body + "http&colon;//x", rec) is None
assert phraser.validate(body + "&#x74;ext", rec) is None
# unicode format / bidi / zero-width / line separators
assert phraser.validate(body + "ab", rec) is None # bidi override
assert phraser.validate(body + "ab", rec) is None # zero-width space
assert phraser.validate(body + "ab", rec) is None # line separator
assert phraser.validate(body + "a…b", rec) is None # next line
def test_injection_catalog_outputs_rejected() -> None:
# Malicious item names try to make the model emit markup/links/instructions.
catalog = [