Home / security / visualforce-security-and-modernization
visualforce-security-and-modernization
Use when hardening or modernizing legacy Visualforce pages — covers the platform CSRF token model and when disabling it is a security regression, view state encryption guarantees and the 170 KB ceiling, FLS/CRUD enforcement gaps on `<apex:outputField>` and on getters that return sObjects, `<apex:includeScript>` interaction with the org Content Security Policy, hosting LWC inside a VF page via `lightning:container` / `lightning-out`, and the retire-vs-harden-vs-leave-alone decision for an inventory of legacy pages.
Open the skill folder on GitHub
Visualforce Security And Modernization
Activate this skill when an org has a population of Visualforce pages — usually a mix of legacy admin tools, customer-facing pages on Experience Cloud, and PDF generators — and a security review or LWC migration program is forcing decisions on each one. The skill is about the retire-vs-harden-vs-leave-alone choice plus the security baseline for whatever stays on Visualforce. Greenfield Visualforce architecture (controller patterns, PDF, view state strategy) belongs in apex/visualforce-fundamentals.
Before Starting
Gather this context before proposing changes to any Visualforce page:
- Visualforce is not deprecated. Salesforce has not announced a sunset date. Pages continue to be supported and CSRF / view state / iframe-in-LEX behaviors continue to receive platform-level fixes. Do not migrate to LWC just because LWC is newer — migrate when there is a real reason (security finding, broken UX in LEX, unmaintainable controller, performance regression). The default for a working page is leave alone.
- Who hits the page matters more than what it does. A page accessible only to System Administrators with a sharing-aware controller is low risk. The same page accessible to Customer Community users is a different security profile entirely — guest and external users get no implicit record access, and FLS gaps that would never trip an admin trip them on first load.
- The CSRF token is on by default and you almost never want to turn it off. Salesforce automatically embeds an anti-CSRF token in
<apex:form>POST submissions. ThecsrfProtectionpage attribute exists, but disabling it is a security regression that needs a documented justification. If the team is "just trying to make a callback work," 95% of the time the right answer is to fix the callback to use POST, not to disable CSRF. with sharingdoes not enforce FLS or CRUD. It only enforces record-level sharing. Awith sharingcontroller class still happily reads and returns fields the user has no FLS access to. FLS must be enforced separately — either by binding to standard-controller<apex:inputField>/<apex:outputField>, or by callingSchema.sObjectType.X.fields.Y.isAccessible()/ usingWITH USER_MODE. Read theapiVersionin the controller's.cls-meta.xmlbefore scoring any of this. Both Apex defaults inverted at 67.0 (Summer '26): a class with no sharing keyword runswith sharingthere rather thanwithout sharing, and database operations run in user mode with no clause at all. The gate is the class's pinned version, not the org's release — a Summer '26 org runs a controller pinned to 58.0 with the old behaviour. Canonical table: