Cross-Package Privilege Escalation via @namespaceAccessible
This lab teaches how unsafe exposure of Apex classes and methods through @namespaceAccessible can let other packages invoke privileged business logic, creating cross-package escalation paths that are difficult to detect during normal tenant testing.
Executive Summary
@namespaceAccessible is designed for controlled interoperability between packages in the same namespace family. Misuse happens when high-impact operations are exposed without strict caller validation, authorization gates, and parameter constraints.
In managed package ecosystems, this can create trust-boundary failures: a secondary package, extension package, or compromised namespace component invokes privileged methods that subscriber users should never trigger directly.
Salesforce Attack Surface
Namespace-accessible Apex APIs: service facades, helper classes, and utility gateways callable across package boundaries
Blast radius expansion: one weak package integration weakens the entire package suite trust model
Forensics complexity: abuse appears as valid internal package-to-package invocation
PoC Use Cases
Use isolated package test fixtures to validate exploitability of namespace-accessible methods.
// Vulnerable anti-pattern
public with sharing class PrivilegedAccountOps {
@namespaceAccessible
public static void reassignOwner(Id recordId, Id newOwnerId) {
// Missing caller trust validation and authorization checks
Account acc = [SELECT Id, OwnerId FROM Account WHERE Id = :recordId LIMIT 1];
acc.OwnerId = newOwnerId;
update acc;
}
}
A sibling package invokes reassignOwner with attacker-selected record IDs.
Method executes privileged mutation without verifying business authorization.
User gains indirect control over records outside expected entitlement scope.
Testing Methodology
Enumerate exposed API surface: list all @namespaceAccessible methods and classify by sensitivity
Trace sink operations: identify DML, auth, secret, and system-mode actions reachable from exposed methods
Caller simulation: test invocation from separate package contexts and constrained user profiles
Abuse case design: vary target IDs and operation flags to test horizontal/vertical privilege abuse
Evidence collection: capture call chain, caller context, and unauthorized impact for report quality
Secure Engineering Patterns
Minimize exposure: mark only necessary APIs as namespace-accessible
Caller-aware authorization: enforce explicit permissions and business ownership checks before sensitive action
Action segmentation: separate read-only integration APIs from privileged mutation APIs
Parameter hardening: reject caller-controlled arbitrary object names, record IDs, and privilege flags
Review gates: treat every new @namespaceAccessible method as a security design decision
// Safer pattern
public with sharing class PrivilegedAccountOps {
@namespaceAccessible
public static void reassignOwner(Id recordId, Id newOwnerId) {
if (!FeatureManagement.checkPermission('PKG_Reassign_Owner')) {
throw new SecurityException('Not authorized');
}
Account acc = [SELECT Id, OwnerId FROM Account WHERE Id = :recordId LIMIT 1];
if (!isCallerAuthorizedForRecord(acc.Id)) {
throw new SecurityException('Record out of scope');
}
acc.OwnerId = newOwnerId;
update acc;
}
}
Verification Checklist
Inventory of all @namespaceAccessible methods is maintained and risk-classified
High-impact methods enforce explicit authZ and business-scope validation
Namespace-accessible methods do not directly expose system-mode privileged sinks
Cross-package abuse test cases are included in CI security regression suite
Security review evidence documents rationale for every exposed integration API
Lab Exercises
Run this sequence to understand and remediate cross-package abuse:
Exercise 1: Enumerate and classify all namespace-accessible methods in a package
Exercise 2: Build a simulated extension package caller to invoke exposed APIs
Exercise 3: Reproduce unauthorized record mutation via weak authorization checks
Exercise 4: Implement caller-aware authorization and scope controls
Exercise 5: Re-test and produce AppExchange-ready remediation evidence