---
name: plugin-security-review
description: Plugin system review (scored 4/10) + its 4-phase program; audit doc location and Phase 1 open items
metadata: 
  node_type: memory
  type: project
  originSessionId: 34e55f34-7301-4172-9626-5a54dac397f9
---

A large review of Evolution's plugin system scored it **4/10** and defined a **4-phase program**:
1=implement security/correctness fixes (DONE, on branch `plugin-review`, uncommitted), 2=re-audit,
3=re-evaluate architecture, 4=consolidate improvements into a plan. The original written analysis
was lost to a `/clear`; it was reconstructed on 2026-06-19 to
**`evolution/audits/PLUGIN_SECURITY_REVIEW.md`** (read that doc first — it has the full findings
table, before→after detail, testing checklist, and roadmap).

Phase 1 (implemented) closed: stored-XSS on the plugin settings page (new
`plugins/block_sanitiser.php` — save-time HTML/CSS/URL allow-list, wired into every block
save/import path; HTML fields are rendered RAW by design so the control is save-time sanitisation,
not render escaping), two SQLi spots (table-source + `gettablefields` → `information_schema`
whitelist), missing admin AuthZ gate on `plugin_ajax.php`, and the `LIKE '%id%'`→`FIND_IN_SET`
tenant-isolation bug (5 sites). See [[evolution_ajax_save_auth_gate]], [[evolution_sort_injection_validator]].

**Still OPEN after Phase 1:** O1 = free-form `WHERE` clause SQLi in `settings.php` (~262, the real
"Phase 4" local marker — highest remaining security item); O3 = sanitiser is save-time only, so
existing stored `blocks` rows need a one-off backfill; R1 = no CSRF token on `plugin_ajax.php`
mutations; minor: `$bmeta->name` raw attr (O2).

**Phase-numbering trap:** the code's "Phase 1/3 of plugin-system modernization" (manifest columns
migration) and "deferred to Phase 4" (the WHERE clause) are LOCAL labels, NOT the review's 4 phases.
Migration `customextrameta_drop_company.sql` must run AFTER the de-scoping code deploys.
