Alba Rivas is a Lead Developer Evangelist at Salesforce and former Salesforce MVP. While in the past, Alba has presented frequently on migrating to Lightning Web Components  (LWC) – today, she talks about data security on the platform. We chat about some best practices to prevent leaking data or creating dangerous app security vulnerabilities when coding with Apex and with LWC. She also shares some tips and tricks for handling secrets in encryption.

Alba believes any developer should think about data security right from the very beginning and that applying best practices is crucial for having a high quality application to prevent vulnerabilities and attacks, which could be a big issue for any company.

Show Highlights:

  • Moving from Visualforce to Lightning Web Components (LWC)
  • Creating a Trailhead Module 
  • CRUD field level security vs. record level security
  • The importance of Apex and how it works within SQL queries
  • How to use schema to check if somebody has access to a record
  • What the Apex recipes project does and what functions support security
  • What Apex’s pilot user mode does and what the SOQL injection is for
  • An example of a successful injection attack and what it does to a web application 
  • What is a cross-site scripting attack?
  • Lightning Locker vs. content security policy (CSP)
  • How to enforce security in LWC
  • Some edge cases LWC developers need to worry about
  • Tips for securing data back in the database itself and protecting custom metadata

Links:

Episode Transcript

Alba Rivas:
And I start taking, really, my first step in the development and programming world then, in my career, my degree. And everything that I did after that was programming, mainly.

Josh Birk:
That is Alba Rivas, a lead developer advocate here at Salesforce. I’m Josh Birk, your host of the Salesforce developer podcast. And here on the podcast, you’ll hear stories and insights from developers for developers. Today, we sit down and talk with Alba about data security on the platform. But to kick things off, I actually wanted to talk about one topic that she has spoken about at length at places like Dreamforce.

Alba Rivas:
Sure. So, Visualforce to LWC was the first big topic that I touched when I joined Salesforce. And what I did was to create some resources to help people make the move from Visualforce to Lightning Web Components. So, one of the resources is a sample app. We have a sample app in our sample app gallery called Visualforce to Lightning Web Components that you can download and see how certain patterns migrate to Lightning Web Components. There is a side-by-side comparison and, on the left, you see the Visualforce implementation. On the right, you see the Lightning Web Components implementation. And the idea is that you learn from that, right?

Josh Birk:
Got you. Got you.

Alba Rivas:
The second big resource that I created for this topic is a Trailhead module called… Yeah, I think it’s make the move from Visualforce to LWC. I don’t remember the name exactly. But if you look for Visualforce and LWC in Trailhead, you are going to find it. And in that module, we try to represent the differences between Visualforce and LWC from the very beginning, from the most basic concepts, and then increasing in complexity, until there is a point in which you have a good idea in your mind of which are the differences and what do you need to spend more time learning about, right?

Josh Birk:
Got you. Got you. Awesome. And we’ll definitely try to include links to both of those in the show notes. Now, moving on to our main topic, we’re going to talk about security and break down some stuff that you’ve written about in a blog post. But to level set for everybody and just basic record security, can you quickly define for me CRUD field-level security and then record-level security?

Alba Rivas:
Well, these are acronyms that we use in the topic of data security, the security that you can configure in Salesforce to protect the access to your records, right? Let’s start with CRUD. CRUD stands for create, read, update, delete, and CRUD controls the security of objects. So, with CRUD, for instance, you can define if a user can read accounts or if another user can update contacts, right? We control the visibility of the whole table in the database.

Alba Rivas:
Then, we go one level down, we have field-level security. In this case, what we control is the visibility of fields in a table of the database. It’s a more granular security layer, right? And taking the example that we had before, we can have access maybe to create accounts, but then we may have access to indicate a name for the account but we may not have access to indicate the account revenue, for instance, right? It’s a much more granular degree of control.

Alba Rivas:
And then, we have record-level security, record-level security is also known as sharing, right? Record sharing. With record-level security, we go to a different dimension because, there, what we control is the visibility of individual records. You may have CRUD access to see an entire table. You may have FLS to see a specific field of that table. But if you don’t have access to the record, then you are not going to be able to access that record, right?

Josh Birk:
Right. Right. So, I might be a system administrator. I can create, read, update, I can do anything I want across any record, no matter what. Or I might be a sales rep and all I can do is maybe read some contacts, and I can’t even see all the fields and I only have access to a certain number of records, basically.

Alba Rivas:
Exactly. Exactly. And the ways in which you can configure data security in Salesforce are almost infinite. There is a whole certification that you can study to learn all of that, right?

Josh Birk:
Thinking about it from a developer point of view, though, why is this really important for us to keep in mind? In particular with Apex, because Salesforce likes to operate in different kinds of modes and Apex is specific about that, right?

Alba Rivas:
Yeah, exactly. So, what happens is that, in most of the cases, if you are, for instance, creating a record through the standard API or through the rest API, in all those cases, these three security layers, the security that you define in those layers is going to be enforced by default, right? But with Apex, it’s exactly the opposite. With Apex, the default is that we don’t enforce CRUD FLS or sharing. And it’s our responsibility for the developer to do that.

Josh Birk:
Now, one of the things that we can do in Apex is something that’s come up on the pod before. Our old friend with security enforced, how does that work within SOQL?

Alba Rivas:
So, this is a new clause that we can use in SOQL queries that is going to make that enforcement for you. So, before this annotation existed, the only way to check for object field… Well, not record-level security, sorry, only object and field-level security, was to use a schema method. You could check like a schema.account. I want to know if it’s accessible or if it’s creative or whatever, whatever, right? And the same for the fields. But today, we have a much simpler way, which is use this with security enforce parameter. You use it in a SOQL query, and then the records that you retrieve with that SOQL query are going to enforce both object, field, and record-level security. So, it’s very handy to use and it’s not going to occupy lines of your code.

Josh Birk:
Nice. So, going back to the old ways, though, how can you use Schema in order to check if somebody has access to a record?

Alba Rivas:
So, this is the traditional way, indeed, with security enforce, I think it was released like two or three releases ago, at most. And with Schema, you are really using the Schema describeSObjectResult class and the Schema describeFieldResult class. Those classes have methods. Purely, you can include a link in the transcription of their podcast, Josh, so that people have access to that. And in those methods, you can check for object-level security and for field-level security. You can check if an account is creatable or if an account field, for instance, annual revenues and [inaudible 00:08:15] is accessible or updatable or whatever permission level you want to check.

Josh Birk:
And we’ll definitely link to your blog posts, which have some great example code to show you how to do this. You also give a shout out to our Apex Recipes and the Candy user functions? I think I’m remembering the name of those right. What did those functions look like and what could somebody learn from those?

Alba Rivas:
Yeah. So, Apex Recipes is one of our sample apps in the gallery. And I think, in one of Kevin Poorman’s code lives, he created this class. So, this is an attempt to make it easier to use these Schema methods to check for security, because the way in which you read a method in the CanTheUser class is much more straightforward. For instance, if you want to check if a user has real access to an object, then the syntax that you are going to use is CanTheUser.read and then the name of the object. So, it’s much easier to use, right? There is something else that Kevin implemented which is an example that uses Platform Cash, if you have access to Platform Cash in your organization, to try to make the process faster.

Josh Birk:
And see, what I like about that is something else that’s come up in a couple previous episodes, in that it can probably… There’s enforcing your data layer and then there’s also putting that into your unit tasks, right? So that when you are trying to make sure that your code coverage is complete and your assertions are complete, you’re doing it not just for that SIS mode person but also for that field-rep-level person.

Alba Rivas:
Yeah. In test mode, you can use a method which is System.RunAs. And that method lets you execute the code as if you were a certain user.

Josh Birk:
Got it. Got it.

Alba Rivas:
So, normally, the flow to follow in your unit tests is to create a user, assign the permissions that you want to assign to that user, and then use the System.RunAs. But it’s important to remember that this method doesn’t enforce objects or field-level security. It’s only record-level security, okay?

Josh Birk:
Got it. Okay. No, that is good to know. But moving back to functional Apex, you mentioned a pilot for something called User Mode. What is that going to look like?

Alba Rivas:
Yeah. So, same does our amazing Apex team has created this super easy way to filter security in SOQL queries which is with security enforce, we talked about that before. They are working on a pilot to make it easier. Also, when you do DML operations, with this pilot, you are going to be able to execute and insert DML operation and update DLM operation, specifying a parameter that tells if the code should enforce security or not, right?

Josh Birk:
Got it. Okay. Nice. Nice. Okay. So, let’s move out of the realm of just Apex and back into, I guess, more client-side security focus. Let’s talk about some of the common security attacks that we see. First of all, describe SOQL injection for me.

Alba Rivas:
Yeah. So, this is one of the top 10… I think it’s the first, indeed, issues that the OWASP organization has identified for 2020, I believe. And well, I don’t know if you what the OWASP organization is.

Josh Birk:
No. Give me a tour of that real quick.

Alba Rivas:
It’s the Open Worldwide Application Security Project, right? And it is a nonprofit organization that, every year, elaborates a list of most common important vulnerabilities that are happening in the web application development world. And they explain what the issue is about and they explain how to solve it or how to prevent it, right? So, SOQL injection… Injection, in general, is the first item in their list. But SOQL injection is type of injection that only affects Salesforce, right? Because SOQL is what we have in Salesforce.

Josh Birk:
Right. Right. Right.

Alba Rivas:
The same concept applies to SQL, right? We have also SQL injection outside Salesforce, but in Salesforce, it’s SOQL injection. So, what happens with this attack is that untrusted data that is taken from the user or from a URL, something that we haven’t control, right? Something that it’s been indicated from an external source and that it may be corrupted, we take that data and we use it into a SOQL query in a way in which it becomes part of the query and it’s interpreted as part of the query, right?

Alba Rivas:
SOQL injection in Apex is not super common because there is only a way in which you can create queries that are vulnerable to SOQL injection. But it may happen, so as a developer, it’s important to know this because, if you don’t know it, you may be opening the door to these attacks that can be a very serious attack, right? Yeah. So, the way in which you open the door to SOQL injection is when you use dynamic queries and, instead of binding the parameters with column, which is a recommended way to do that, you simply concatenate parts of the queries with the untrusted data.

Josh Birk:
Got you.

Alba Rivas:
That way, what happens is that, that untrusted data becomes part of the query and it’s parsed, it can be evaluated same as the rest of the tokens of the query.

Josh Birk:
Got it. I think I’ve had experiences in the past where I’ve thought that I had covered edge cases when it came to SOQL queries. And I think this can even be broader than just Salesforce. What’s a good example of a successful injection attack and what kind of things can it do to a web application when those attacks are successful?

Alba Rivas:
Well, I remember some famous attacks indeed. For instance, do you remember two or three years ago that it happened that some chapters from Game of Thrones where exfiltrated?

Josh Birk:
Oh, really?

Alba Rivas:
Yeah. Exactly. They were able to do that thanks to a SQL injection attack, because they were able to modify the query and gain access to data that, by default, was not public or available, and they got access to all those records and we were able to watch the chapters much earlier.

Josh Birk:
Got you. Okay. So, static queries, that’s one way around that, because obviously, if you’re not binding to anything, then you’re in complete control over what the query is. Are there specific functions in Apex that we should be mindful of when we are looking at those bound dynamic queries?

Alba Rivas:
Yeah. So, one option is to use a static queries. If you can’t use static queries, then what you can do is to bind the parameter, the untrusted data, bind it with column. That way, the query’s going to be safe. It doesn’t matter if it’s static or dynamic. And if you can’t do that for any reason, then there is a function in Apex that may help you, a method, really, which is string, in the string class, .scape”. If you do that, then it’s going to be… Well, there are a few edge cases in which an attacker could perform an injection attack, but the edge cases are minimal. So, that’s not the best solution, but if you compulsorily need to do a dynamic query with string concatenation, then make sure to use a String.scape” because that’s going to cover most of the cases.

Josh Birk:
Got it. Got it. Okay. Okay. Let’s move to another common one. What is a cross-site scripting attack and, generally speaking, how do they work?

Alba Rivas:
So, with cross-site scripting, what happens is that, normally, an attacker gets to inject some malicious scripts in your browser. That may happen because the script is reflected, is something the attacker is passing in through your parameters, something like that. And then, your application is reflecting that script and executing. And that may happen as well because that script is stored in a database. Many people don’t take into account this kind of cross-site scripting. It’s called cross-site scripting. But this is very common and equally detrimental for your application, right?

Josh Birk:
Right. Right. It sounds like it’s the JavaScript neighbor to a dynamic SQL injection.

Alba Rivas:
Yeah, exactly. Exactly. So, normally, if you have, for instance, a table in the database in which you have a malicious script stored and your code is not evaluating that code, is not evaluating it as if it was JavaScript, there’s no harm right? There’s no problem with that. The problem is when your code is evaluating some tests, for instance, and executing that test, and that test is untrusted.

Josh Birk:
Got it. Got it. And Salesforce has some pretty decent built-in protections for this, which are, if I recall correctly, put on by default and hard to disable. But there are edge cases that Lightning Web Component developers need to worry about. What kind of edge cases are those?

Alba Rivas:
Yeah. Well, the full protections in place for these are Locker Service and they conduct security policy implementation. Normally, if you don’t disable Locker, I think you cannot do it anymore. In the past, you were able to do that. And if you followed the best practices, Locker and CSP are going to take care for cross-site scripting for you. But there are a few cases in which you can escape those protections somehow, right? One of the cases is when you use a lwc:dom=”manual” directive.

Josh Birk:
You mean manipulating the DOM directly within LWC? What specifically is the developer doing there?

Alba Rivas:
Yeah. So, what happens is that, normally, Lightning Web Components, the framework takes care of the DOM life cycle, right? And one of the things that the framework what is doing with Locker Service is to sanitize the inputs that you are rendering in the DOM. For instance, if you are using a template for:each to perform an iteration in the DOM and so show a few rows, for instance, the framework is sanitizing those inputs for you. What happens is that, sometimes, when you are using third-party libraries, you have to manipulate the DOM manually because those third-party libraries also manipulated them and they collide with LWC.

Alba Rivas:
So, to be able to do that, you have to use our directive, which is lwc:dom=”manual”. And there are cases in which you have to use it. I’m not saying that you don’t use it at all. I’m just saying that, if you can perform the DOM manipulation in a different way, for instance, using template directives, you should do that. If you are able to manipulate the DOM using template for:each or template if, right? If:true or false, whatever, that way is going to be much more secure than if you try to manipulate it manually.

Josh Birk:
Okay. So, you had mentioned Locker Service, and I think developers kind of have this concept of Locker Service just working mysteriously in the background. But we have a couple of things to handle security on the platform. So, what is Locker Service? And I think the other one is CSP. What’s the distinction between those two and what do they do?

Alba Rivas:
Yeah. So, Lightning Locker is something that we created to enforce security in Lightning components. And Locker does a couple of things, right? Starting by using the strict mode in JavaScript, by any means. In all the components that you write, we are using the strict mode. We don’t allow to use a non-strict mode in Lightning components. It also prevents internal namespace, DOM access. This is if there is a component in your page that doesn’t belong to your namespace, you won’t be able to interact with that component. That’s for security, right?

Alba Rivas:
And it also provides a secure implementation of some global objects in the browser. So, instead of window, we have secure window. Instead of documents, we have secure document, et cetera, right? We also disable access to some methods from the DOM APIs. And that’s something that people can check in the documentation because in the Lightning Web Components documentation, there is a tab called Local API Viewer, and there you can find the differences between the regular updates and the secure versions of them. And that’s basically it, more or less, right?

Alba Rivas:
And then, we have CSP. CSP is web standard, really, that we are implementing in Lightning components as well, right? And some of the policies that come in CSP… CSP stands for Content Security Policy, right? Some of those policies are, for instance, one of them is that JavaScript libraries can only reference from your org. That’s the way in which we implement that. We don’t allow reference in JavaScript libraries that are uploaded somewhere else, and that’s for security. You have to use static resources for that. Then, for instance, we force that resources are loaded with HTTPS so that the connection is encrypted and we don’t allow JavaScript.

Josh Birk:
Got it. Yeah.

Alba Rivas:
All those security features are there because of CSP.

Josh Birk:
Now, just out of my own curiosity, because I know a lot of the… Especially from the CSP point of… Actually, let’s start with Locker Service because Locker Service is something we created in part because we have this unique landscape, right? Where my JavaScript is running but, because I might pull something from an app exchange, some other developer’s JavaScript could be running on the same page, right next to each other, and the whole goal is to make sure that your bucket of JavaScript can’t look at my bucket of Lightning Web Components and pull data off of my component, right?

Alba Rivas:
Yeah. Yeah, yeah, yeah. That was the main reason. I know that we are working on a way to allow internal namespace trust. So, imagine that you are an ISV developer and that you have components in different namespaces and you want to access the components that live in a different namespace because it’s also yours, right? I know we are working on a way to support that.

Josh Birk:
Got it. Got it. Handshake across the names.

Alba Rivas:
Exactly. But for the general case, it’s for [inaudible 00:25:44].

Josh Birk:
Okay. So, we’ve talked Apex, we’ve talked data layers, and this very multifaceted way of keeping control some Apex-level attacks, some client-level attacks. What are some tips and tricks that you have for securing the data back in the database itself? If I’ve got something that I want to keep just completely secret, what are some of the options that we have on Salesforce for that?

Alba Rivas:
Indeed, we have a couple of options. It depends on the business case, right? But for instance, if that data that you want to store is authentication data that you need to access a third-party service, you can use name credentials. Name credentials is a type of metadata that you can use to store information about callout and points so that you don’t have to hard code that in your Apex code and you just call your name credential and configure everything in your name credential.

Josh Birk:
Right. Right. Which is also not only secure but also handy and convenient, right?

Alba Rivas:
Yeah. Also for moving configuration between orgs. And even you can do something with named credentials which is, for instance, you have your production org and your development org, and you are using different name credential configuration but you call the two name credentials in the same way. And you make your Apex code depend on the name of the name credential. That way, the development org is going to take the configuration of the development name credential, and in the production org, it’s going to take the configuration of the production name credential. It gives you that flexibility.

Josh Birk:
Got it. Got it. Are there other options for securing or protecting custom metadata in general?

Alba Rivas:
Yeah. So, we have protected custom settings and custom metadata. And that’s a great option when you need to store passwords, encryption keys, payment information, this kind of data that is sensitive data. If you use protected custom settings or metadata, what happens is that, if you package something that uses a protected custom setting of metadata, then the subscriber org is not going to be able to see that custom setting of metadata. But your code is going to be able to see it. Only the person that builds the package is going to have visibility for those settings.

Josh Birk:
And is there anything else on an Apex level that we have for handling secrets and encryption?

Alba Rivas:
At Apex level, we have the Apex crypto class. In the Apex crypto class, there are several methods that allow you to implement different algorithms that will ensure secrecy, integrity, authenticity, right, of your data. This is recommended when you are going to take that data outside of Salesforce, for instance, to communicate with an external system. You want to send that data and you want to ensure that nothing weird happen in the middle, right? That the data has been sent by the person that is meant to have been sent, that the data hasn’t been corrupted, that the data is authentic, right?

Josh Birk:
Mm-hmm (affirmative). And do you have any just general advice for when a developer is starting a new application? What’s your take on when and how to start thinking about security in general?

Alba Rivas:
I think we all should start thinking about security from the very beginning, from the very beginning. Having this knowledge around security is not going to take you that much. I promise this. I promise this. And there are a couple of Trailhead modules that you can do. You can watch the security series that I have done. It’s three hours in total. And after watching the series, you are going to have a good understanding of what you have to pay attention at, right? And applying best practices from the beginning is crucial for having a high-quality application, right? And don’t open the door to vulnerabilities and attacks. That may be a big issue for your company.

Josh Birk:
Learning about your security flaws when somebody else has already attacked them is usually a pretty bad time. Yeah.

Alba Rivas:
Yeah, exactly.

Josh Birk:
And what I love about a lot of your samples are that they… Going back to with security enforce, it’s one SOQL clause, right? A lot of the things that you can do feel like it’s really actually lightweight and not a lot of heavy lifting just to make things a little bit more secure.

Alba Rivas:
Yes. One thing that also the audience can can do is to try to use a security scanner. There are some automatic security scanners that scan your code, looking for vulnerabilities or security problems. There are some that will help you with Apex, and people can take a look at that. If you don’t remember everything, then the security scanner, you can even integrate that as part of your CI. Then, the scanner is going to remind it to you.

Josh Birk:
And that’s our show. Now, check out the show notes for more information, including a link to all those very informative blog posts. Now, before we go, I did ask after Alba’s favorite non-technical hobby.

Alba Rivas:
Oh. It’s gardening. I love gardening. I have lots of flower pots in my terrace. Indeed, I like growing vegetables. Now it’s the time, for instance, for tomatoes in Spain.

Josh Birk:
Nice.

Alba Rivas:
And I love doing that.

Josh Birk:
A non-technical hobby, by the way, that she shares with my florist wife. Now, I want to thank Alba for the great conversation information. And as always, hello and thank you for listening. Now, if you want to learn more about this show, head on over to developer.salesforce.com/podcast, where you can hear old episodes, see the show notes, and have links to your favorite podcast services. Thanks again, everybody. I’ll talk to you next week.

Get notified of new episodes with the new Salesforce Developers Slack app.