A built-in feature was exposing personal data across an entire account.
A third-party penetration test landed an uncomfortable finding: any authenticated user of the client's Salesforce-powered portal could retrieve records belonging to other users on the same account, using a built-in Aura REST endpoint. The cause was implicit sharing (a documented behavior of master-detail relationships) cascading Account-level access down to every child object: Moves, Move Members, Contracted Services, and eight others.
A bad actor with valid portal credentials could extract personal data for every user on a corporate account. The standard playbook said patch the endpoint. We went deeper.
Why the Obvious Fixes FailedThree direct remediations got tested before we committed to schema work.
Disabling API access broke the portal without solving the underlying problem. Rerouting the endpoint masked the symptom and left the access path intact. Removing Object Level Security blocked the leak but broke every integration that depended on it. None of them addressed the root cause: the sharing model itself.
The WorkThe fix was structural, not surface-level.
- Redesigned the schemaConverted master-detail to lookup relationships across twelve affected objects, including Move, Move Member, Metric, Contracted Services, Supplier Information, and Authorized Order Account.
- Locked down sharing defaultsSet Default External Access to Private on every converted object. Each portal user now sees only the records they own, severing the implicit sharing chain at the source.
- Automated record ownershipDeployed Before Insert and Before Update Apex triggers across all affected objects. Ownership is assigned automatically on creation, with no manual intervention required.
- Migrated data cleanlyFull export, ownership reassignment, re-import, and regression testing across all three portal user profiles. Internal users saw zero disruption throughout the migration window.
- Preserved integration continuityPublic Read/Write OWD maintained for internal users. A queue-user bridge handles asynchronous provisioning gaps, and Informatica workflows continued without interruption.
What a penetration test surfaces as a single vulnerability is rarely a single fix.
Patching the endpoint leaves the door open. Removing Object Level Security breaks everything downstream. The only durable answer was a schema change: convert the relationships, lock the defaults, automate the ownership. Scaled across a portal serving thousands of users, that's the difference between a closed ticket and a closed vulnerability.