Skip to content

security(spp_scoring): scoring viewers read all scoring results incl. registrant name + snapshot PII [Severity: Medium] #354

Description

@gonzalesedwin1123

Follow-up from PR #351 (which closes the spp.program.membership PII grant for scoring viewers). This is a separate, pre-existing sink on spp.scoring.result that PR #351 does not touch and should be triaged on its own.

Finding

A pure spp_scoring.group_scoring_viewer (no program/registry role) can read registrant PII directly from every scoring result:

  • ACL grants the viewer read on spp.scoring.resultspp_scoring/security/ir.model.access.csv (access_spp_scoring_result_viewer, 1,0,0,0).
  • The record rule is unfiltered — spp_scoring/security/rules.xml:46-53 rule_scoring_result_read_all domain_force = [(1, '=', 1)] for group_scoring_viewerall results, not scoped to the viewer's area/programs.
  • spp_scoring/models/scoring_result.py:130-134: registrant_name = fields.Char(related="registrant_id.name", store=True)stored, so the viewer reads the name of every scored registrant with no res.partner access needed.
  • scoring_result.py:91-97: inputs_snapshot / breakdown_json are JSON blobs of the field values used at scoring time. Indicators pull from res.partner (scoring_indicator.py), so these can contain arbitrary registrant field values (income, address, demographics — whatever indicators reference) for every scored registrant.
  • registrant_id (M2o res.partner) is also readable; whether it dereferences to full partner PII depends on the base res.partner ACL + OpenSPP global partner rules (area rule no-ops for a user with no assigned area) — flagged as likely-open, not confirmed.

Net: a scoring viewer obtains name + score + classification for all scored registrants, and potentially arbitrary snapshotted field values — without any program/registry role.

Severity: Medium

Authenticated-internal-user PII disclosure across all scored registrants; no privilege beyond the scoring-viewer role. Impact scales with how many registrants have been scored and which fields indicators reference.

Suggested fix (needs design decision)

  • Scope rule_scoring_result_read_all for group_scoring_viewer to the viewer's area/assigned scope (or to results they are entitled to), rather than [(1,'=',1)]; and/or
  • restrict PII-bearing fields (registrant_name, inputs_snapshot, breakdown_json, registrant_id dereference) from the pure-viewer surface via field-level groups or a redacted summary view.

Source: observed at spp_scoring/models/scoring_result.py:130 / spp_scoring/security/rules.xml:46 while staff-reviewing PR #351. Related: #351.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions