Note: As of February 2017, we have updated the information available regarding Lightning Locker. You can find the updated information in this blog post.
As you know, Trust is Salesforce’s #1 value and product security is a key aspect of Trust. We are constantly searching for ways to improve the security of our products. In that regard, we’ve been working on a set of new security features for Lightning Components called Lightning Locker.
At a high level, Lightning Locker uses various technologies and techniques that are intended to do the following:
- Components from causing XSS and similar security issues
- Components from reading other component’s rendered data without any restrictions
- Components from calling undocumented/private APIs
- Cool new features like client-side API versioning similar to REST API versioning*
- Faster security review
- Better and more secure JS development practices
- Running 3rd party JS frameworks like React, Angular and so on*
- Easily adding or removing new security features and policies
*Some of the features will have limitations and will come during or after Winter 2017 #safeHarbor
In Winter ’17, Lightning Locker can be activated or deactivated in your org. Note: To ensure compatibility with Lightning Locker before the Summer ’17 release, test your Lightning components in a sandbox or a Developer Edition org.
In Spring ’17, the existing Lightning Locker critical update will tighten Content Security Policy (CSP) to eliminate the possibility of cross-site scripting attacks. These CSP changes will only be enforced in sandbox and Developer Edition orgs. If you have a sandbox or Developer Edition org with the Lightning Locker critical update activated, the stricter CSP will apply when Spring ’17 rolls out. If you deactivate the Lightning Locker critical update before the Spring ’17 release, the stricter CSP won’t be applied.
In Summer ’17, Lightning Locker will be auto-activated for all orgs with no option to disable.
Components installed from managed packages
To control whether Lightning Locker is enforced for components installed from a managed package:
- From Setup, enter Lightning Components in the Quick Find box, and then select Lightning Components.
- Select the Enable Lightning Locker for Managed Packages checkbox to enforce Lightning Locker for components
installed from a managed package.
Note: The checkbox is only visible when the critical update is activated.
If you deselect the Enable Lightning Locker for Managed Packages checkbox, Lightning Locker is not enforced for
components installed from a managed package. Components that you create in your org still run with enforcement of Lightning Locker restrictions.
Under the hood
To understand the technology under the hood, let’s take an example app. The below example Lightning app has four components: a button, a Weather component (that internally has a Map sub-component) and a Finance component.
Before Lightning Locker
Before Lightning Locker, the DOM tree and JS access for the example lightning app would look like the following image.
In this scenario:
- Any JS of any component can call any JS functions of any other component as they are all loaded in the DOM
- Any JS can also call any undocumented/private Lightning APIs
- Any JS can access real DOM and get rendered data from other components.
- Components that are not security reviewed can potentially have security issues.
After Lightning Locker
The same lightning app with all the techniques and technologies used in Lightning Locker will look something like the following image.
With the Lightning Locker turned ON
- Salesforce-authored components and JS run in “System mode” (similar to the Operating System’s system mode) and have full access to everything.
- Custom components run in “User mode” and don’t have access to the real Document or real “window” object.
- Custom components instead gets a custom DOM (“secureDOM”), custom Window and so on.
- Custom components can access other components’ DOM as long as they are in the same namespace but won’t be able to access other components’ DOM that are in different namespace. For example, JS in the “Weather” component can access DOM of “Map” component, but won’t be able to access DOM elements of the “Finance” or “button” component.
- In addition, custom components will only be able to access public and documented Lightning JS APIs and won’t be able to access Lightning framework’s “private” APIs.
- “Use strict” and CSP are enabled and enforced for security of all components.
- IE11 doesn’t support CSP, so we recommend using other supported browsers for enhanced security.
- Lighting Components Developer Guide – More details about Lightning Locker and how it works in Lighting components.
- Lightning Locker Video – Get detailed guidance from Salesforce staff.
- Salesforce Lightning CLI – Use the code review tool to check your code for Lightning Locker compatibility.
- Lightning Locker API Viewer – Check the DOM APIs exposed by Lightning Locker
In the below picture, we have a simple ui:button that uses a div (that’s in “c” namespace) for it’s label. Notice how the console.log differs for window, document and div when Lightning Locker is turned ON. Also notice that when the custom component’s JS tries to “walk the DOM” by doing div.parentNode.innerHTML to get the button’s innerHTML, it gets “undefined” because button is in a different “ui” namespace.
- What will happen to the existing custom components or those in the Component exchange?
- Lightning Locker runs behind the scenes. There is no change to the public and documented APIs. However, Lightning Locker enforces modern JS standards and new security rules. So depending how the component is built, they will need to be upgraded to meet these standards. We’ll be providing tools and articles to make this transition easy.
- Can I use 3rd party libraries (React, Angular, etc) if running in Lightning Locker?
- Yes, provided they are served from Static Resources and approved by security.
- Can different components use different versions of a 3rd party library?
- Yes, LS provides full JS module level isolation of window, document, etc so your locker (tied to your namespace) is its own world.
- Does Lightning Locker allow me to access libraries hosted on a CDN (i.e. Google Maps)?
- It makes it possible for us to open up our Content Security Policy to allow this in Winter 2017 (safe harbor).
- Does Lightning Locker use an iFrame for sandboxing?
- No – your code runs directly in the same browser window as the rest of the components in an application.
- Are application events sandboxed in a locker?
- No, but all events (Aura and DOM) are wrapped in a filtering proxy that only allows your code to see what it has access to. You can continue to use Lightning eventing framework to communicate between components irrespective of their namespace.
- Is there a way to access raw DOM elements?
- No – you always work with the Secure Virtual DOM – but your code and 3rd party code cannot tell the difference – no change in programming model (e.g. Component.getElement() works the way it does today). You cannot do things we’ve said not to do from day one now – e.g. node.parentNode.parentNode to escape into code you do not own is blocked.
- What’s the granularity of a locker? One component per locker? Multiple Components per locker?
- Today the granularity is all the components in the same namespace. Future versions of Salesforce are likely to allow both finer grain (e.g. set of components) and courser grain (e.g. set of namespaces owned by an org).
Please note that this is just an introductory post. We’ll be releasing tools, blogs, in-depth articles and Trailhead modules in the coming weeks and months before Lightning Locker is made available. Please watch this space for more information.
— Raja Rao D.V. @rajaraodv