Introducing The LockerService For Lightning Components

This is an introductory post about a new security feature for Lightning Components called "LockerService (LS)". LockerService uses various technologies and techniques to make Lightning Components secure. It will be available as a critical update as part of Summer '16 and will be enforced in Winter '17.

Note: As of February 2017, we have updated the information available regarding LockerService. 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 LockerService (LS).

At a high level, LockerService uses various technologies and techniques that are intended to do the following:

Prevent:

  • 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

Enable:

  • 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

Availability

In Winter ’17, LockerService can be activated or deactivated in your org. Note: To ensure compatibility with LockerService before the Summer ’17 release, test your Lightning components in a sandbox or a Developer Edition org.

In Spring ’17, the existing LockerService 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 LockerService critical update activated, the stricter CSP will apply when Spring ’17 rolls out. If you deactivate the LockerService critical update before the Spring ’17 release, the stricter CSP won’t be applied.

In Summer ’17, LockerService will be auto-activated for all orgs with no option to disable.

Components Installed from Managed Packages

To control whether LockerService is enforced for components installed from a managed package:

  1. From Setup, enter Lightning Components in the Quick Find box, and then select Lightning Components.
  2. Select the Enable LockerService for Managed Packages checkbox to enforce LockerService for components
    installed from a managed package.
    Note: The checkbox is only visible when the critical update is activated.

If you deselect the Enable LockerService for Managed Packages checkbox, LockerService is not enforced for
components installed from a managed package. Components that you create in your org still run with enforcement of LockerService 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 LockerService

Before LockerService, the DOM tree and JS access for the example lightning app would look like the following image.

In this scenario:

  1. Any JS of any component can call any JS functions of any other component as they are all loaded in the DOM
  2. Any JS can also call any undocumented/private Lightning APIs
  3. Any JS can access real DOM and get rendered data from other components.
  4. Components that are not security reviewed can potentially have security issues.

After LockerService

The same lightning app with all the techniques and technologies used in LockerService will look something like the following image.

With the LockerService turned ON

  1. Salesforce-authored components and JS run in “System mode” (similar to the Operating System’s system mode) and have full access to everything.
  2. Custom components run in “User mode” and don’t have access to the real Document or real “window” object.
  3. Custom components instead gets a custom DOM (“secureDOM”), custom Window and so on.
  4. 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.
  5. 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.
  6. “Use strict” and CSP are enabled and enforced for security of all components.

In Spring ’17, LockerService tightens CSP to eliminate the possibility of cross-site scripting attacks by disallowing the unsafe-inline and unsafe-eval keywords for inline scripts (script-src). Eliminate use of these keywords in your code, and update third-party libraries to modern versions that don’t depend on unsafe-inline or unsafe-eval. These CSP changes are only enforced in sandbox and Developer Edition orgs.

Note:

  • When LockerService is activated in sandbox or Developer Edition orgs, you can’t edit rich-text fields and the fields are grayed out. We’re working on removing that limitation in a future release.
  • IE11 doesn’t support CSP, so we recommend using other supported browsers for enhanced security.

Additional Resources

  1. Lighting Components Developer Guide – More details about LockerService and how it works in Lighting components.
  2. Lightning LockerService Video – Get detailed guidance from Salesforce staff.
  3. Salesforce Lightning CLI – Use the code review tool to check your code for LockerService compatibility.
  4. LockerService API Viewer – Check the DOM APIs exposed by LockerService

Code Example

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 LockerService 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.

FAQs

What will happen to the existing custom components or those in the Component exchange?
LockerService runs behind the scenes. There is no change to the public and documented APIs. However, LockerService 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 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 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 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 LockerService is made available. Please watch this space for more information.

— Raja Rao D.V. @rajaraodv

Developer Evangelist

 

Leave your comments...

Introducing The LockerService For Lightning Components