What
Oncofiles is shipping a P0 security sweep (oncofiles#484) to close cross-patient data leaks reported by Michal Gašparík.
Phase 2 of that sweep tightens the query_db MCP tool that Oncoteam uses for lab-trend audits and clinical analyses. Some of your existing queries will break — intentionally — after the change.
What's changing (Phase 2)
query_db moves from block-list (only a handful of credential tables denied) to allow-list (every other table denied by default).
patient_id filter check moves from regex to SQL AST parse (sqlglot) — requires literal equality patient_id = '<uuid>' on every patient-scoped table reference. These will no longer satisfy the filter:
GROUP BY patient_id
WHERE patient_id LIKE '%'
WHERE patient_id IS NOT NULL
WHERE patient_id IN (...)
- Missing pid filter + admin session (no more implicit "admin = see everything")
- The
patient_slug= argument becomes mandatory for patient-scoped queries — no more silent fallback to the caller's resolved pid when the query doesn't specify a patient.
sqlite_master, pragma_*, patients, newsletter_subscribers, email_entries, calendar_entries, clinical_records, clinical_analyses, sync_history are all denied at the allow-list layer.
Action required on Oncoteam side
- Inventory every
query_db call in this repo.
- For each:
- Confirm it targets a table in the new allow-list:
documents, activity_log, conversations, treatment_events, research_entries, lab_values, document_pages, agent_state, patient_context, conversation_entries, clinical_records (if added), prompt_log, schema_migrations, sync_history (if added), document_cross_references.
- Rewrite filter to
WHERE patient_id = '<uuid>' literal equality (or = :pid bind).
- Add explicit
patient_slug= argument.
- Retest via the Oncoteam agent after oncofiles v5.15.0 ships (ETA 2026-04-27).
- Any table you need that's not on the allow-list → comment here and we'll evaluate adding it.
Why
From oncofiles's empirical retest — our own probes:
SELECT * FROM patients → returned full roster with caregiver_email + diagnosis_summary (this is what Michal screenshotted)
WHERE patient_id LIKE '%' on documents → returned every doc, every patient (296 rows)
GROUP BY patient_id on activity_log → returned 36,155 rows across 2 patients
Medical data; EU AI Act HIGH RISK; this is not optional.
Timeline
- oncofiles Phase 2 lands 2026-04-25
- oncofiles v5.15.0 tag 2026-04-27
- Oncoteam self-retest by 2026-04-28
Related
- oncofiles#484 (meta)
- oncofiles#483 (Michal's original report)
- prior coordination: oncoteam#433 (patient_slug propagation), oncoteam#406 (agent_state)
cc @peter-fusek
What
Oncofiles is shipping a P0 security sweep (oncofiles#484) to close cross-patient data leaks reported by Michal Gašparík.
Phase 2 of that sweep tightens the
query_dbMCP tool that Oncoteam uses for lab-trend audits and clinical analyses. Some of your existing queries will break — intentionally — after the change.What's changing (Phase 2)
query_dbmoves from block-list (only a handful of credential tables denied) to allow-list (every other table denied by default).patient_idfilter check moves from regex to SQL AST parse (sqlglot) — requires literal equalitypatient_id = '<uuid>'on every patient-scoped table reference. These will no longer satisfy the filter:GROUP BY patient_idWHERE patient_id LIKE '%'WHERE patient_id IS NOT NULLWHERE patient_id IN (...)patient_slug=argument becomes mandatory for patient-scoped queries — no more silent fallback to the caller's resolved pid when the query doesn't specify a patient.sqlite_master,pragma_*,patients,newsletter_subscribers,email_entries,calendar_entries,clinical_records,clinical_analyses,sync_historyare all denied at the allow-list layer.Action required on Oncoteam side
query_dbcall in this repo.documents,activity_log,conversations,treatment_events,research_entries,lab_values,document_pages,agent_state,patient_context,conversation_entries,clinical_records(if added),prompt_log,schema_migrations,sync_history(if added),document_cross_references.WHERE patient_id = '<uuid>'literal equality (or= :pidbind).patient_slug=argument.Why
From oncofiles's empirical retest — our own probes:
SELECT * FROM patients→ returned full roster with caregiver_email + diagnosis_summary (this is what Michal screenshotted)WHERE patient_id LIKE '%'ondocuments→ returned every doc, every patient (296 rows)GROUP BY patient_idonactivity_log→ returned 36,155 rows across 2 patientsMedical data; EU AI Act HIGH RISK; this is not optional.
Timeline
Related
cc @peter-fusek