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
Discovered during the verification of PR #399's review findings (spp_grm_cel rule-ACL analysis). Filed as its own issue because it is a live gap on released 19.0 and is strictly broader than the rule-model concerns raised there.
Severity: High (portal-authenticated read/write of all grievances)
Problem
spp_grm/security/ir.model.access.csv grants base.group_portalread, write and create on spp.grm.ticket:
access_spp_grm_ticket_portal_user,GRM Ticket Portal User Access,model_spp_grm_ticket,base.group_portal,1,1,1,0
and no ir.rule applies to portal users at all: spp_grm/security/rules.xml defines record rules only for the staff groups (group_grm_viewer/officer/supervisor/manager), and there is no global rule on the model. Group-scoped rules do not restrict non-members, so the portal ACL row is unscoped.
Any authenticated portal user can therefore, over plain RPC:
search_readevery grievance in the system — other people's complaints, contact details, descriptions, assignments, escalation state (grievances routinely contain sensitive personal information, and GRM sensitivity levels exist precisely because of that);
write on any ticket — rewrite descriptions, flip stage_id (which triggers escalation evaluation), reassign, or close other registrants' grievances;
create tickets directly, bypassing the portal controller (spp_grm/controllers/grm_portal.py runs sudo and is not the enforcement point).
The portal UI's apparent scoping comes only from the controller/views; the ORM surface is unscoped.
Why this is the root of the PR #399 finding-11 cluster
The retained portal read row on spp.grm.routing.rule / spp.grm.escalation.rule (kept in #266, questioned in the PR #399 review) is load-bearing only because portal users can create/stage-write tickets over direct RPC, which evaluates rules as the acting user. Scoping portal ticket access changes that premise, so the pieces belong to one coherent fix:
Portal record rule on spp.grm.ticket — own tickets only (e.g. [('partner_id', '=', user.partner_id.id)]; decide whether portal keeps write at all, or read-only + controller-mediated updates).
Drop the portal AND base.group_user read rows on both rule models — closes the enumeration surface (any portal user can currently map every routing/escalation condition, threshold, and target assignee/team; Odoo 19's Many2one.convert_to_read returns display names via sudo, so officer names leak despite the core res.users portal rule).
Items 2-4 are the finding-11 follow-up from the PR #399 review; item 1 is the new gap that makes them safe to do.
Notes
The missing-record-rule pattern is the exact "Related models need record rules too" pitfall; other spp_grm models with portal rows (stage, tag, channel, category, subcategory, team, sla_rule — all read-only) are global config and arguably fine, but worth a pass in the same PR.
Any fix ships with a version bump + migration considerations for deployments that relied on portal RPC access (none known — the portal UI goes through the controller).
Tests must cover: portal user cannot read/write another partner's ticket; portal user still sees their own; controller-submitted tickets still route; staff access unchanged.
Discovered during the verification of PR #399's review findings (spp_grm_cel rule-ACL analysis). Filed as its own issue because it is a live gap on released
19.0and is strictly broader than the rule-model concerns raised there.Severity: High (portal-authenticated read/write of all grievances)
Problem
spp_grm/security/ir.model.access.csvgrantsbase.group_portalread, write and create onspp.grm.ticket:and no
ir.ruleapplies to portal users at all:spp_grm/security/rules.xmldefines record rules only for the staff groups (group_grm_viewer/officer/supervisor/manager), and there is no global rule on the model. Group-scoped rules do not restrict non-members, so the portal ACL row is unscoped.Any authenticated portal user can therefore, over plain RPC:
search_readevery grievance in the system — other people's complaints, contact details, descriptions, assignments, escalation state (grievances routinely contain sensitive personal information, and GRM sensitivity levels exist precisely because of that);writeon any ticket — rewrite descriptions, flipstage_id(which triggers escalation evaluation), reassign, or close other registrants' grievances;createtickets directly, bypassing the portal controller (spp_grm/controllers/grm_portal.pyruns sudo and is not the enforcement point).The portal UI's apparent scoping comes only from the controller/views; the ORM surface is unscoped.
Why this is the root of the PR #399 finding-11 cluster
The retained portal read row on
spp.grm.routing.rule/spp.grm.escalation.rule(kept in #266, questioned in the PR #399 review) is load-bearing only because portal users can create/stage-write tickets over direct RPC, which evaluates rules as the acting user. Scoping portal ticket access changes that premise, so the pieces belong to one coherent fix:spp.grm.ticket— own tickets only (e.g.[('partner_id', '=', user.partner_id.id)]; decide whether portal keepswriteat all, or read-only + controller-mediated updates).sudo()inspp_grm_cel(apply_routing/apply_escalations) — rules are staff-authored trusted config after security(grm): restrict GRM automation rules to GRM staff (drop portal write/create) #266; the ticket recordset keeps the caller's env so write-rights semantics are unchanged.base.group_userread rows on both rule models — closes the enumeration surface (any portal user can currently map every routing/escalation condition, threshold, and target assignee/team; Odoo 19'sMany2one.convert_to_readreturns display names via sudo, so officer names leak despite the coreres.usersportal rule).test_portal_user_can_read_ruleswith a read-denial test and update the module docstring (already reworded in security: batch 1 — DCI/Key admin privilege escalations, OAuth signing keys, GRM rule ACL (#327, #329, #265, #266) #399 to call the grant a "current implementation dependency").Items 2-4 are the finding-11 follow-up from the PR #399 review; item 1 is the new gap that makes them safe to do.
Notes
spp_grmmodels with portal rows (stage,tag,channel,category,subcategory,team,sla_rule— all read-only) are global config and arguably fine, but worth a pass in the same PR.