You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-ups from the code review that produced #64. The HIGH persist_path traversal is fixed in #64; these remain.
Medium
Tenant isolation only exists when Basic Auth is enabled — app/auth.py:36, app/tenancy.py:46: uses_default_storage is true whenever auth is off, so every request (regardless of X-RegEngine-Tenant) collapses onto the shared local-demo store. SECURITY_BOUNDARIES.md claims tenant data stays isolated — the guarantee silently does not hold in the default config. Fix: document explicitly, or route by tenant header even when auth is disabled.
CSV formula injection in FDA export — app/fda_export.py:99 writes user-controlled fields (product_description, location_name, KDE reference_document_*) via csv.DictWriter with no neutralization. A value like =cmd|'/c calc'!A1 becomes a live formula in Excel/Sheets. Fix: prefix cells starting with = + - @ \t \r with a leading apostrophe.
Low
EventStore._all_records re-reads the whole JSONL on every read — app/store.py:324 reparses the full file (Pydantic per line) for stats/lineage/all_between/status, defeating the in-memory cache. Fix: serve reads from the in-memory deque; treat disk as WAL.
In-memory deque vs unbounded disk file divergence — app/store.py:53 caps the deque at 5000 but add_many appends unboundedly; multi-worker uvicorn would corrupt the append/replace (lock is per-process). Fix: cap/rotate the file; document single-worker as a hard requirement.
Operator delete trusts normalized tenant id for shutil.rmtree — app/routers/operator.py:42. Safe as written (strict regex, URL segment can't contain /), but add a defensive resolve().is_relative_to(TENANT_DATA_ROOT) assert before rmtree.
Follow-ups from the code review that produced #64. The HIGH
persist_pathtraversal is fixed in #64; these remain.Medium
app/auth.py:36,app/tenancy.py:46:uses_default_storageis true whenever auth is off, so every request (regardless ofX-RegEngine-Tenant) collapses onto the sharedlocal-demostore.SECURITY_BOUNDARIES.mdclaims tenant data stays isolated — the guarantee silently does not hold in the default config. Fix: document explicitly, or route by tenant header even when auth is disabled.app/fda_export.py:99writes user-controlled fields (product_description,location_name, KDEreference_document_*) viacsv.DictWriterwith no neutralization. A value like=cmd|'/c calc'!A1becomes a live formula in Excel/Sheets. Fix: prefix cells starting with= + - @ \t \rwith a leading apostrophe.Low
EventStore._all_recordsre-reads the whole JSONL on every read —app/store.py:324reparses the full file (Pydantic per line) forstats/lineage/all_between/status, defeating the in-memory cache. Fix: serve reads from the in-memory deque; treat disk as WAL.app/store.py:53caps the deque at 5000 butadd_manyappends unboundedly; multi-worker uvicorn would corrupt the append/replace (lock is per-process). Fix: cap/rotate the file; document single-worker as a hard requirement.shutil.rmtree—app/routers/operator.py:42. Safe as written (strict regex, URL segment can't contain/), but add a defensiveresolve().is_relative_to(TENANT_DATA_ROOT)assert beforermtree.🤖 Generated with Claude Code