Found during the staff review of PR #266, out of that PR's scope.
Finding
spp_grm/security/ir.model.access.csv:6 grants base.group_portal 1,1,1,0 (read/write/create) on model_spp_grm_ticket, and no ir.rule targets base.group_portal — spp_grm/security/rules.xml scopes only group_grm_viewer / officer / supervisor / manager (lines 7/19/35/47/65). A portal user is in none of those groups, so no group rule filters them, and there are no global rules on the model either.
Net effect: a portal user can read and modify every grievance in the system over RPC. The controller's partner_id domain (spp_grm/controllers/grm_portal.py:16) is presentation-only and does not constrain direct search_read/write.
Grievance tickets routinely contain complainant identity, narrative detail, and case linkage, so this is a broad PII disclosure plus an integrity problem (a portal user can rewrite or reassign other people's grievances).
Why it wasn't caught
spp_mis_demo_v2/tests/test_access_control_grm.py has test_portal_cannot_see_other_portal_tickets and test_portal_cannot_write_other_portal_tickets which would catch exactly this — but they are gated on cls.grm_installed (test_access_control.py:86), and spp_mis_demo_v2 does not depend on spp_grm (only the five spp_grm_* modules do). The tests silently skip.
Suggested fix
Add a portal record rule on spp.grm.ticket scoping to the requesting partner (and their commercial partner, per the usual Odoo portal pattern), or drop portal write/create entirely and route all portal mutations through the already-sudo'd controller. Then un-gate or relocate the two skipped tests so the boundary is actually pinned.
Note PR #266 fixed the rule-model half of the portal over-grant (routing/escalation rules); this is the ticket-model half and is arguably larger.
Related: #266.
Found during the staff review of PR #266, out of that PR's scope.
Finding
spp_grm/security/ir.model.access.csv:6grantsbase.group_portal1,1,1,0(read/write/create) onmodel_spp_grm_ticket, and noir.ruletargetsbase.group_portal—spp_grm/security/rules.xmlscopes onlygroup_grm_viewer/officer/supervisor/manager(lines 7/19/35/47/65). A portal user is in none of those groups, so no group rule filters them, and there are no global rules on the model either.Net effect: a portal user can read and modify every grievance in the system over RPC. The controller's
partner_iddomain (spp_grm/controllers/grm_portal.py:16) is presentation-only and does not constrain directsearch_read/write.Grievance tickets routinely contain complainant identity, narrative detail, and case linkage, so this is a broad PII disclosure plus an integrity problem (a portal user can rewrite or reassign other people's grievances).
Why it wasn't caught
spp_mis_demo_v2/tests/test_access_control_grm.pyhastest_portal_cannot_see_other_portal_ticketsandtest_portal_cannot_write_other_portal_ticketswhich would catch exactly this — but they are gated oncls.grm_installed(test_access_control.py:86), andspp_mis_demo_v2does not depend onspp_grm(only the fivespp_grm_*modules do). The tests silently skip.Suggested fix
Add a portal record rule on
spp.grm.ticketscoping to the requesting partner (and their commercial partner, per the usual Odoo portal pattern), or drop portal write/create entirely and route all portal mutations through the already-sudo'd controller. Then un-gate or relocate the two skipped tests so the boundary is actually pinned.Note PR #266 fixed the rule-model half of the portal over-grant (routing/escalation rules); this is the ticket-model half and is arguably larger.
Related: #266.