OD402 public-write-access¶
An access row gives public or portal users write, create or unlink, through their group or no group.
| Category | Severity | Series | Needs the index |
|---|---|---|---|
| Security | Warning | all | no |
What it reports¶
A row of an ir.model.access CSV file Odoo loads, whether ir.model.access.csv or a name such as
ir.model.access-hook.csv, that gives perm_write, perm_create or perm_unlink to
base.group_public, to base.group_portal or, with an empty group_id or no such column, to every
user. A permission reads as set when it is 1, true or yes, in any case.
An ir.access CSV file starts at saas~19.4, where ir.access replaces ir.model.access: a row of
it for one of those two groups whose operation contains c, u or d reports, and a row of an
ir.model.access file does not, since Odoo no longer has the model to load it into.
Why it matters¶
A portal user is a customer or supplier with a login. Like any user, they can call the ORM
methods of every model over JSON-RPC, not only through the pages the module wrote for them, so
the access rows and record rules are all that stand between them and the table. With write
access, they can change any field of the records the rules let through, including fields the
portal form never shows. The public user stands for every anonymous visitor, and its rights
apply in every auth="public" route.
The usual pattern is read-only access, narrowed by a record rule to the user's own records, and a
controller that checks what the user may change and then writes with sudo(). A record rule
that confines the row may make it safe; the finding then needs that rule reviewed with it.
An ir.model.access row with no group grants every user, so the public and portal users too. An
ir.access row with no group restricts every user instead, and is not reported. Neither is a row
with no group that only reads, nor one whose id the scan sees written twice, since the last write
may set a group, nor one in a file the manifest does not load, unless the module's own Python
loads that file. Before saas~13.2 Odoo does not check the rows of a TransientModel, so none of
them is reported, whatever its group.
A row whose active cell reads as false (0, false, no in any case, or empty) grants nothing,
so it is not reported, with or without a group. A file with no active column leaves its rows
active.
Only CSV rows are checked; an access record written in XML is not, and neither is a row that names
its group by database id in a group_id/.id column.
Example¶
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_library_loan_user,library.loan user,model_library_loan,base.group_user,1,1,1,1
access_library_loan_portal,library.loan portal,model_library_loan,base.group_portal,1,1,1,0
Any portal user can create loans and rewrite the due date or borrower of every loan they can see.
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_library_loan_user,library.loan user,model_library_loan,base.group_user,1,1,1,1
access_library_loan_portal,library.loan portal,model_library_loan,base.group_portal,1,0,0,0
Let the portal controller extend a loan after checking that it belongs to the user.
A row with no group goes further:
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_library_loan_all,library.loan all,model_library_loan,,1,1,0,0
Every user, logged in or not, can rewrite the loans the record rules let through. Name a group.
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_library_loan_all,library.loan all,model_library_loan,base.group_user,1,1,0,0
Suppressing¶
A comment would break the CSV file, so pass --ignore OD402 or add it to ignore in the
configuration file. To keep one reviewed row without turning the rule off, record it in a
baseline.