fix(reports): code-review findings — XSS, SMTP, blocking, unit link, email guard
- #1 XSS: escape user-controlled values (location name, baseline values, recent- report fields, SMTP status message) in the modals via the existing _mergeEsc helper — they were concatenated raw into innerHTML (stored XSS via location name). - #2 SMTP: an unrecognized REPORT_SMTP_SECURITY no longer silently downgrades to a plaintext connection while still calling login() — it falls back to starttls and warns; warn on intentional security=none + auth. - #3 scheduler: run the (blocking smtplib + Excel) nightly report in a worker thread (asyncio.to_thread + its own DB session) so it can't stall the loop that drives time-sensitive device cycles. New _run_one_report helper. - #4 cycle ingest: set unit_id on the ingested data session (ingest_nrl_zip leaves it None) before dropping the empty placeholder, preserving the unit<->session link; repoint old_session_id at the real row. - #7 robustness: wrap send_report_email in the orchestrator and run_nightly_report in /view + /run so a render/SMTP error returns a clean error instead of a raw 500 after artifacts are written. Verified: SMTP paths (typo->starttls, none, starttls, ssl), off-thread tick stamps last_run_date + writes the file, /view 200, escaping wired, app imports. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -136,8 +136,14 @@ def send_report_email(
|
||||
)
|
||||
return result
|
||||
|
||||
# Validate the security mode: an unrecognized value (typo) must NOT silently
|
||||
# fall through to a plaintext connection while still sending credentials.
|
||||
sec = cfg.security if cfg.security in ("ssl", "starttls", "none") else "starttls"
|
||||
if sec != cfg.security:
|
||||
logger.warning("Unknown REPORT_SMTP_SECURITY=%r — falling back to 'starttls'", cfg.security)
|
||||
|
||||
try:
|
||||
if cfg.security == "ssl":
|
||||
if sec == "ssl":
|
||||
ctx = ssl.create_default_context()
|
||||
with smtplib.SMTP_SSL(cfg.host, cfg.port, timeout=cfg.timeout, context=ctx) as s:
|
||||
if cfg.user:
|
||||
@@ -146,10 +152,15 @@ def send_report_email(
|
||||
else:
|
||||
with smtplib.SMTP(cfg.host, cfg.port, timeout=cfg.timeout) as s:
|
||||
s.ehlo()
|
||||
if cfg.security == "starttls":
|
||||
if sec == "starttls":
|
||||
s.starttls(context=ssl.create_default_context())
|
||||
s.ehlo()
|
||||
if cfg.user:
|
||||
if sec == "none":
|
||||
logger.warning(
|
||||
"Sending SMTP credentials over an UNENCRYPTED connection "
|
||||
"(REPORT_SMTP_SECURITY=none) — set starttls/ssl if the relay supports it."
|
||||
)
|
||||
s.login(cfg.user, cfg.password)
|
||||
s.send_message(msg)
|
||||
result["sent"] = True
|
||||
|
||||
Reference in New Issue
Block a user