spotifyovercastrssapple-podcasts

Security in Elm

We discuss what makes Elm's security vulnerability surface area smaller, and what frontend security considerations are important in Elm apps.
January 2, 2023
#73

Transcript

[00:00:00]
Hello Jeroen.
[00:00:02]
Hello Dillon.
[00:00:04]
I will admit, today's topic feels very vulnerable to me.
[00:00:07]
I'm feeling a little insecure about talking about this.
[00:00:11]
Well, you know what? I'm used to fixing vulnerable things.
[00:00:17]
You would never exploit my insecurities, would you Jeroen?
[00:00:21]
I didn't prepare puns, okay?
[00:00:26]
What are we talking about today?
[00:00:28]
I feel so much at loss here.
[00:00:33]
We are talking about security and Elm.
[00:00:37]
Well, the Elm part I think most people know, so they could have guessed that.
[00:00:42]
But we're talking about security.
[00:00:44]
Security.
[00:00:45]
That's the only word that we have agreed upon.
[00:00:49]
So what comes next depends on what we want to talk about.
[00:00:53]
Just in general, Elm feels like a pretty secure language in the sense that
[00:01:00]
I don't ever wonder about, is my code secure?
[00:01:04]
Which is a surprisingly fresh feeling.
[00:01:08]
And maybe I should feel bad about it, but I kind of know I don't have to worry about it.
[00:01:15]
Right.
[00:01:16]
Well, we should explore that question a little bit.
[00:01:19]
Where do we feel a sense of security and where is it a false sense of security
[00:01:25]
that we have about our Elm code?
[00:01:27]
Where do we need to take precautions to make sure we're writing secure Elm code?
[00:01:32]
Also, security is a large topic.
[00:01:35]
So just to clarify, I think we're not talking about backend security here.
[00:01:39]
I think we're talking about frontend security.
[00:01:42]
Yeah, I think we're going to talk about security for whatever Elm is used for.
[00:01:47]
And Elm is used for frontend.
[00:01:49]
I guess with tools like Lambdara, it extends to the backend somewhat.
[00:01:55]
But yeah, I'm going to stick to talk about the frontend for now, at least.
[00:02:00]
Right. Yeah, to me, the entire concept of frontend security is really,
[00:02:06]
I think, pretty interesting and subtle.
[00:02:08]
Like in a way, it's pretty obvious when you think about backend security,
[00:02:13]
you think about Bobby Tables, you think about SQL injection attacks.
[00:02:17]
And DDoS attacks as well.
[00:02:19]
DDoS attacks, right.
[00:02:21]
Which are denial of service, distributed denial of service.
[00:02:27]
Right. And to me, those are pretty easy to wrap your head around, right?
[00:02:31]
Because you're like, well, the user makes a request.
[00:02:35]
I need some data to know what they're searching for that I'm going to use
[00:02:40]
in a database query to perform a search or to do a user lookup or something.
[00:02:44]
It's like, well, if I don't scrub my inputs, then they can just drop the database.
[00:02:49]
And that, like, yes, we don't want arbitrary code executed on our database.
[00:02:54]
Right? Yeah, exactly.
[00:02:56]
But when you think about frontend security, the web is this strange place
[00:03:01]
where the user can open up dev tools in their browser,
[00:03:05]
and they can run JavaScript, right?
[00:03:08]
So making it secure, like in the backend, it's this protected, sacred space
[00:03:14]
where you're like, I run code, and when you give me data,
[00:03:18]
I need to make sure it doesn't cause code to run that I didn't intend to.
[00:03:22]
That's pretty obvious.
[00:03:24]
But the user can just run JavaScript code anytime they want
[00:03:28]
and do anything in their frontend application.
[00:03:31]
So why does frontend security matter?
[00:03:33]
Right. Well, I think it's always the same thing for the frontend and the backend.
[00:03:38]
It's basically you don't want people to be able to run arbitrary code
[00:03:43]
where they shouldn't, or rather where it would have an impact on someone else.
[00:03:48]
So if you run a request and send it to the server,
[00:03:52]
and it drops a database table, well, that will impact a lot of people.
[00:03:56]
So we don't want you to be able to do that, right?
[00:03:59]
For the frontend, you can run any arbitrary JavaScript code in your browser.
[00:04:06]
Like you open your console, as you said, and then you can do whatever.
[00:04:09]
You can mess up the internal state of the application,
[00:04:12]
and the application might crash, and that's kind of bad,
[00:04:16]
but you did it upon yourself, right?
[00:04:18]
If it's only for yourself, who really cares?
[00:04:21]
You actively try to mess with a machine.
[00:04:24]
So it's not something that we care about.
[00:04:26]
But if you're trying to execute some code on someone else's machine,
[00:04:32]
or on the server, or somewhere else where it might affect someone
[00:04:36]
who didn't want to be affected, then that's a security issue.
[00:04:41]
Right. Yes. That's a great point.
[00:04:44]
It's about certain trusted parties.
[00:04:47]
And when you're on a client page, a web page,
[00:04:52]
then the user is a trusted client,
[00:04:55]
and they can do whatever they want, and that's fine.
[00:04:58]
But, yeah, if you're at mysupersecurebank.com,
[00:05:04]
and you're logged in, and you're browsing through your bank's chat forums
[00:05:10]
that lets people post statements about how cool their bank is
[00:05:15]
and what fun financial things they're doing,
[00:05:19]
then if they can embed HTML in there
[00:05:23]
to put little emojis and bold things,
[00:05:25]
and you let them put whatever code you want,
[00:05:27]
and whoops, I let them embed a script tag,
[00:05:30]
now when Yaroon logs in to mysupersecurebank.com
[00:05:35]
and Dillon put in a script tag that can access Yaroon's cookies,
[00:05:40]
that is an untrusted party accessing, running code on your machine.
[00:05:45]
So it's a little more subtle,
[00:05:50]
but it comes down to, as you're saying,
[00:05:55]
trusted parties and trusted environments.
[00:05:59]
So obviously a backend server is a trusted environment
[00:06:05]
that untrusted parties need strict restrictions
[00:06:10]
on how they can use that,
[00:06:12]
and arbitrary code is the opposite of strict restrictions.
[00:06:15]
Yeah, and when you say trusted parties,
[00:06:20]
trusted parties for specific actions as well.
[00:06:23]
Right, right.
[00:06:25]
You as a user are allowed to create other users maybe,
[00:06:29]
if you're an administrator, if you're not, then you're not allowed to,
[00:06:33]
and you're creating some kind of content on the website
[00:06:38]
that will be seen by other people,
[00:06:40]
while you impact their application,
[00:06:42]
because they now see your content or your actions,
[00:06:45]
but that is allowed, right?
[00:06:47]
But injecting a script, not so much.
[00:06:50]
Right, totally.
[00:06:51]
Yeah, so it is all about trust and privileges,
[00:06:53]
because yeah, that's a great example.
[00:06:55]
You could be an admin user,
[00:06:57]
and the thing is, it does require trust to have an admin user,
[00:07:01]
and that trust can be abused.
[00:07:03]
So if the bank wanted to,
[00:07:06]
they could put, they can steal your data if they want to,
[00:07:10]
like they have it, and they have control,
[00:07:12]
like they could certainly inject a script tag on your site, right?
[00:07:18]
Like that's not even injecting,
[00:07:20]
that's just serving you HTML that does a malicious thing.
[00:07:24]
So the bottom line is, like, it is a trusted party.
[00:07:28]
We are trusting the bank, right?
[00:07:30]
Which is why, like, if you go to a phishing site
[00:07:33]
that's going to steal your data,
[00:07:35]
or you're trusting to put your credit card information into a forum,
[00:07:39]
it's important that the page is who it says it is,
[00:07:43]
and is not contaminated by other untrusted parties being that.
[00:07:48]
But it does require you trusting them.
[00:07:50]
Like, we think that Amazon is probably not going to go
[00:07:54]
take our credit card information we submit there
[00:07:57]
and, like, make fraudulent payments, but, like, they could.
[00:08:01]
We're assuming they won't because we're trusting them,
[00:08:04]
and that seems like a pretty safe thing to put our trust in.
[00:08:07]
So that's the reason that front-end security matters
[00:08:10]
is because when you go to a website,
[00:08:13]
you are trusting that party.
[00:08:16]
And if code can be executed by other parties,
[00:08:20]
you might not trust that party.
[00:08:22]
So that contaminates the trust by allowing untrusted parties
[00:08:26]
to be executing code on your browser.
[00:08:30]
So, like, it's kind of an amazing thing to me,
[00:08:34]
that the browser is this, like, very open, transparent environment
[00:08:39]
where, like, you can set cookies and you can present data
[00:08:45]
and you can, like, submit forms with passwords and things.
[00:08:49]
And somehow, like, in this very transparent, open thing,
[00:08:54]
we're able to build an environment where we can sandbox things enough
[00:08:58]
and come up with these conventions where trusted parties,
[00:09:01]
like, you can submit a password and it's pretty secure.
[00:09:05]
That's kind of amazing.
[00:09:07]
So the web is like this fragile ecosystem built on these tools for trust
[00:09:14]
that are largely, like, tools that the browsers provide
[00:09:17]
through these standards.
[00:09:19]
But there's nothing that the browser can do
[00:09:21]
if they provide these standards and these conventions for us.
[00:09:25]
But if we're not scrubbing our input properly,
[00:09:28]
then there's nothing they can do because they can only trust our assumptions
[00:09:32]
from the HTML and code we give them.
[00:09:36]
But if we don't sanitize it, then we're giving them code
[00:09:40]
that is going to do bad things.
[00:09:42]
So front-end security, I think, largely comes down to sanitization
[00:09:46]
is a lot of what it comes down to.
[00:09:49]
Yeah, so when you say sanitization, what you mean is sanitizing the data
[00:09:54]
that is coming from the back-end, the responses that you get
[00:10:00]
from HTTP requests, like, I want to render this HTML.
[00:10:05]
Well, we need to sanitize it so that we don't inject scripts, mostly, right?
[00:10:10]
Yeah, well, let's talk about that.
[00:10:12]
There are different sanitization contexts.
[00:10:14]
And actually, this is one of the things that makes web security difficult
[00:10:19]
and front-end security difficult,
[00:10:21]
there are so many different languages and contexts.
[00:10:24]
So in a sense, frameworks can help with sanitization
[00:10:29]
because if you're doing React and you use a prop somewhere,
[00:10:37]
then it's going to sanitize it for you unless you say,
[00:10:40]
yeah, unless you say dangerously set innerHTML,
[00:10:44]
and then it says, oh, I'm going to trust the context this comes from
[00:10:49]
and arbitrarily put HTML tags rather than escaping HTML characters, for example.
[00:10:55]
When you render HTML but not when using props or...
[00:11:01]
Okay, I think I got the idea at least, yeah.
[00:11:03]
In certain contexts.
[00:11:05]
So you can only do so much because you're trying to allow
[00:11:09]
programmatic things to be done, right?
[00:11:11]
So if you're like...
[00:11:13]
But you can at least say, well, if I'm setting an attribute,
[00:11:17]
this is the Bobby Tables thing, right?
[00:11:19]
We'll link to the Bobby Tables in the show notes
[00:11:21]
for anyone who hasn't seen that XKCD comic.
[00:11:24]
But basically, if you can get like a semicolon or whatever
[00:11:29]
into your SQL query, then you might be able to start a fresh SQL query
[00:11:34]
and escape out of that box that you were put in where it's like,
[00:11:37]
this box is for find user by username.
[00:11:42]
The user gets to provide their username,
[00:11:44]
but you break out of that box by using these meaningful characters.
[00:11:50]
So if you escape those meaningful characters,
[00:11:52]
you can't break out of that box because there's no way
[00:11:54]
to terminate a SQL statement or terminate the HTML attribute.
[00:11:59]
So that's how frameworks can help by escaping those things.
[00:12:03]
Yeah, this is actually one of those things where I let the backend
[00:12:07]
do most of the security checks.
[00:12:09]
For instance, if you somehow have to send a SQL query to the backend
[00:12:16]
or something that will be transformed to create a SQL query,
[00:12:20]
you can put as many checks in the frontend code that you want,
[00:12:24]
like making sure that you can't delete a user
[00:12:27]
or that you don't craft any weird SQL queries.
[00:12:32]
But if the backend allows that, then at some point
[00:12:35]
that is going to happen, either because someone just did a curl request
[00:12:40]
to the backend, which means it doesn't go through the frontend.
[00:12:44]
So whatever security checks you have in the frontend don't matter at all,
[00:12:48]
or they ran some JavaScript to bypass all the security checks
[00:12:52]
that you did in the frontend, and you're at the same point again.
[00:12:56]
So the backend anyway has to make the necessary checks.
[00:13:02]
So if you don't want someone to delete a user or delete some content,
[00:13:06]
then you're going to have to do that at the backend.
[00:13:08]
You might do it in the frontend for a nicer user experience,
[00:13:12]
but it's not going to be necessary from a security point of view,
[00:13:17]
in my opinion.
[00:13:19]
Absolutely. I definitely agree that this is a very important point
[00:13:23]
that sometimes people write frontend validations because it's like,
[00:13:27]
well, you need to have frontend validations
[00:13:29]
because you need a good user experience.
[00:13:31]
So I'll check for these things.
[00:13:33]
But then I already validated this on the frontend,
[00:13:35]
so I don't need to validate it on the backend again.
[00:13:37]
That would be like duplicating things.
[00:13:39]
But of course, as you say, it is anything that's coming from the client
[00:13:44]
cannot be trusted by the backend.
[00:13:46]
So that's like another dimension of this is there's like the frontend
[00:13:50]
to backend security, which essentially you need to treat any client
[00:13:55]
as untrusted.
[00:13:56]
And again, to me, that's this sort of magical thing
[00:13:59]
that we've been able to create something where you can create trust
[00:14:03]
in this environment where you don't really know,
[00:14:07]
like the client could be anyone,
[00:14:09]
and somehow we can create trust within that context.
[00:14:12]
That's pretty interesting.
[00:14:14]
Yeah. Like the backend even, it can't really trust much of its code,
[00:14:19]
except when you have opaque types, right?
[00:14:21]
If the backend has opaque types, then you can absolutely trust that code.
[00:14:26]
But when it comes from the frontend, well, that's going through HTTP,
[00:14:31]
that's going through GraphQL or some other kind of protocol.
[00:14:35]
And therefore, it's raw data that has no inherent security
[00:14:40]
or validation on it, right?
[00:14:43]
Right. Exactly.
[00:14:44]
So you need to check it again, at which point you turn it
[00:14:47]
into an opaque type, blah, blah, blah, blah, blah.
[00:14:49]
You know the drill.
[00:14:50]
Absolutely. Yes. Yeah.
[00:14:53]
And so then there's just the stuff that happens purely on the frontend.
[00:14:59]
And again, I think if my supersecurebank.com allows my post
[00:15:06]
on their message board, which it's a bad idea,
[00:15:09]
they shouldn't have built that feature, but they did.
[00:15:12]
They let me post arbitrary HTML in there, and they don't scrub the inputs,
[00:15:17]
and they let me put script tags, and they let me modify the DOM
[00:15:20]
of the page, right?
[00:15:22]
Now they're allowing me to essentially open up the dev tools
[00:15:26]
in another user's browser that's looking at their bank
[00:15:29]
in a logged-in session, or maybe a logged-out session,
[00:15:33]
and I go and take advantage of that by essentially I can now execute
[00:15:38]
arbitrary code on another user's page through posting on that message board.
[00:15:44]
I add a script tag that says, okay, hide all of the stuff
[00:15:47]
on the original page, and then put in my HTML that is going to,
[00:15:52]
when they log in, it's going to do on submit, post it to my phishing site,
[00:15:58]
and now I've stolen their credentials when they try to log in.
[00:16:01]
So we're putting a lot of trust in, like, typing in a password
[00:16:06]
in an input field in a web page and then hitting enter
[00:16:10]
is kind of a move of extreme trust.
[00:16:14]
And so we've been sort of, we haven't said the term,
[00:16:17]
but we've kind of been talking about cross-site scripting attacks
[00:16:20]
or XSS attacks, and so that's why it's so important,
[00:16:24]
because we are trusting that, like, we're putting a lot of trust
[00:16:29]
in just, like, the HTML elements that are presented on that page.
[00:16:34]
And if we abuse that, like, if we allow a malicious user
[00:16:40]
to take control of another user's, like, web page,
[00:16:44]
like the HTML they see on their page and script tags they see on their page,
[00:16:48]
then all of that trust is now tainted and we can do malicious things
[00:16:52]
because they're trusting us as if we were that authoritative trusted source.
[00:16:56]
So that's why finance security is really important.
[00:17:00]
We don't necessarily think about it a lot,
[00:17:02]
but it's an important thing to be aware of.
[00:17:04]
Absolutely. Yeah, the results can be quite disastrous, right?
[00:17:08]
So in my opinion, or at least in my understanding,
[00:17:12]
what it all comes down to is that you shouldn't trust
[00:17:16]
any arbitrary data from the back end either.
[00:17:19]
The back end should try to avoid saving arbitrary HTML
[00:17:23]
or arbitrary JavaScript code, because it will then be likely
[00:17:27]
to send it to the front end, but the front end should also try
[00:17:31]
to avoid rendering and executing that code.
[00:17:34]
And that's where multiple frameworks and languages have different strategies for this, right?
[00:17:40]
React has one that you mentioned where we sanitize things.
[00:17:44]
Most JavaScript frameworks do this or will tell you,
[00:17:49]
oh, you should always sanitize, never forget to sanitize.
[00:17:52]
Have you sanitized yet? Have you sanitized it once, twice, three times?
[00:17:56]
The charm.
[00:17:58]
And Elm has a different strategy for this, right?
[00:18:03]
Where you are not allowed to do this.
[00:18:07]
You're not allowed to render arbitrary HTML or run arbitrary JavaScript code
[00:18:14]
unless you, through some escape hatches, allow it to.
[00:18:18]
Let's dive into a few strategies for attackers
[00:18:23]
and how they inject things, right? Or how do they do bad things?
[00:18:27]
Because that will also open up to how they can do things.
[00:18:32]
So in the beginning, there was JavaScript.
[00:18:35]
I might be going forward a little bit like when browsers were like five years old,
[00:18:42]
but let's say in the beginning.
[00:18:44]
ECMAScript, perhaps?
[00:18:46]
Not yet, I think.
[00:18:48]
Didn't it start as ECMAScript?
[00:18:51]
Hmm. We're going to need to look this up.
[00:18:53]
I think ECMAScript was later and that was something,
[00:18:57]
like they couldn't call it JavaScript because Oracle had a patent or something.
[00:19:01]
I'm not sure either.
[00:19:03]
So there was JavaScript.
[00:19:05]
And browsers, they added support for JavaScript, all of them.
[00:19:11]
And JavaScript is super useful.
[00:19:13]
We've talked about it before.
[00:19:14]
It has a few quirks.
[00:19:15]
We've talked about those before.
[00:19:17]
But basically in JavaScript, if you want to make a HTTP request,
[00:19:21]
it is pretty easy.
[00:19:23]
Well, somewhat easy.
[00:19:25]
You do new XML HTTP requests, pass in some arguments.
[00:19:29]
And basically in one line of code, you can run arbitrary JavaScript code
[00:19:35]
or run send arbitrary HTTP requests.
[00:19:38]
And that doesn't have any checks on it.
[00:19:41]
It does not have any sandboxing around it.
[00:19:44]
You just write that code, execute it, and boom, the HTTP request is going.
[00:19:49]
And that can happen in any piece of code.
[00:19:52]
Like if you write that in a line of JavaScript code, it runs.
[00:19:57]
If you run that in a getter method, it runs.
[00:20:01]
If you run that in a promise, it runs wherever.
[00:20:05]
And that is quite dangerous as well because that means that you can
[00:20:11]
potentially run this in prototypes or methods that have been overwritten
[00:20:18]
by prototypes.
[00:20:19]
But maybe I'm going too far ahead.
[00:20:21]
Are you telling me that you can just write code and it just executes
[00:20:25]
side effects?
[00:20:26]
Yes.
[00:20:27]
What?
[00:20:28]
Yes.
[00:20:29]
It's bad.
[00:20:30]
That's so strange.
[00:20:31]
Did I tell you it's bad?
[00:20:33]
It's bad.
[00:20:36]
So yeah, there's no control over those effects, right?
[00:20:40]
And that's why we call them side effects even though in a way they are
[00:20:44]
done on purpose.
[00:20:46]
They're not side effects.
[00:20:47]
They're purposeful effects.
[00:20:48]
But they're not managed effects like the way that we like to use them now.
[00:20:52]
Exactly.
[00:20:53]
Right, because we are performing effects but it's constrained where they
[00:20:57]
can occur and what can trigger them.
[00:21:00]
Yeah, exactly.
[00:21:01]
And so because you can do pretty much any kind of code, any kind of effects
[00:21:07]
when running JavaScript code, the strategy that Elm has taken to prevent
[00:21:12]
security issues is to prevent JavaScript because that is surprisingly much
[00:21:17]
easier to control everything.
[00:21:20]
Yeah.
[00:21:21]
And for that Elm has chosen a few strategies.
[00:21:24]
So how do you prevent JavaScript from running?
[00:21:28]
Well, first of all, you don't have a direct interop.
[00:21:32]
You don't have FFI.
[00:21:34]
You can't just run arbitrary JavaScript functions inside Elm code.
[00:21:38]
So that has been a pain for a lot of people especially when going from
[00:21:42]
18 to 19.
[00:21:44]
But that does mean that you don't have any security issues and that is
[00:21:48]
quite cool.
[00:21:49]
So just to clarify, to put on our malicious hacker hat again for a second,
[00:21:56]
what is the malicious hacker trying to do in this case?
[00:22:00]
Like how are they, what's their attack factor they're trying to exploit?
[00:22:03]
Are we talking an NPM package that I, NPM install is even and it makes
[00:22:08]
an HTTP request?
[00:22:10]
Yeah, so you've got multiple ways of doing things.
[00:22:14]
So as we said before with XSS, cross-site scripting, where if you have
[00:22:20]
the backend returning some arbitrary JavaScript code that someone else,
[00:22:26]
someone malicious has entered, then executed that would trigger
[00:22:31]
HTTP requests which can now send your cookies and other important
[00:22:37]
information to the malicious attacker.
[00:22:41]
Attacker.
[00:22:42]
Attacker.
[00:22:43]
Yes.
[00:22:44]
Attacker.
[00:22:45]
An attacker.
[00:22:47]
But yeah, you also have NPM as you said where if you have a JavaScript
[00:22:54]
application and you have installed a malicious package, well if you
[00:22:59]
execute that code, then it can run arbitrary JavaScript code, right?
[00:23:06]
So it can do that somewhat explicitly like, oh, you call that function
[00:23:10]
from that library and then it does some HTTP request or it can do it
[00:23:17]
in weird ways like it can change the prototype of core functions
[00:23:23]
from JavaScript.
[00:23:24]
So if you try to access window.array.from, whatever, then now
[00:23:32]
suddenly it starts making HTTP requests in a very unexpected way.
[00:23:37]
And that is why you get a lot of these security issues about prototype
[00:23:42]
pollution is because now people can do weird things about the prototype,
[00:23:48]
meaning anything that looks even normal can do anything weird.
[00:23:55]
Right.
[00:23:56]
Right.
[00:23:57]
And this is not theoretical.
[00:23:58]
Like there have definitely been like supply chain attacks where a
[00:24:02]
package that's used by millions of packages upstream, it's a dependency
[00:24:08]
in the node modules of this one dependency, either the author of that
[00:24:14]
package or maintainer of that package decides to put something malicious
[00:24:18]
in or somebody convinces the maintainer of an NPM package to give them
[00:24:24]
the keys because they're stepping down as maintainer, they're looking
[00:24:27]
for new maintainers or they maliciously take control of an NPM account
[00:24:34]
or whatever.
[00:24:35]
These things have happened many times, increasingly so.
[00:24:38]
Yeah.
[00:24:39]
And in some cases you've got a little bit of both, like where a package
[00:24:43]
doesn't do anything malicious, but it somehow has the capability of
[00:24:48]
changing the prototype something because it can set an arbitrary value
[00:24:54]
on an arbitrary position, like lodash for instance, I think had an issue
[00:24:58]
like that where I don't know the details, but I imagine like the underscore
[00:25:03]
dash set function, you can change the prototype of something.
[00:25:07]
So now if a package uses lodash and uses the set method and the path at
[00:25:15]
which you set something is supplied by the user, well now the user can
[00:25:20]
set an arbitrary value at a prototype and that could be some JavaScript
[00:25:26]
code running HTTP requests.
[00:25:29]
And that's where it gets like, well, it becomes really hard to audit
[00:25:34]
things and some people do hard work, but yeah, it looks like, does it
[00:25:39]
really matter?
[00:25:41]
Well, in some cases it doesn't, in some cases it does.
[00:25:44]
Right. So most of these types of problems don't exist in Elm, not all
[00:25:50]
of them, but most of them.
[00:25:52]
Yeah. They don't own their own, right?
[00:25:57]
Right. Because you can always do interop, you can do JavaScript interop
[00:26:02]
from Elm using user input.
[00:26:04]
You can install NPM to packages in an Elm app.
[00:26:08]
Yeah, exactly. And if they do something weird, well then that impacts
[00:26:12]
your Elm code as well, but it's mostly because you installed a lot of
[00:26:17]
package which has this vulnerability.
[00:26:19]
So it's not because Elm is vulnerable in this aspect.
[00:26:23]
So yeah, the ways that Elm prevents you from doing all this weird
[00:26:28]
things that lead to problematic results is it doesn't have FFI and you
[00:26:33]
also can't just render plain HTML like you can with React where you
[00:26:38]
have the dangerously set inner HTML.
[00:26:43]
Right. And as a workaround, sometimes Elm users will use something like
[00:26:49]
an HTML parser package.
[00:26:52]
They'll take user input, they'll parse it, and then they'll render that.
[00:26:56]
And then they get something of the HTML type in Elm that they can render
[00:27:00]
on their page.
[00:27:02]
At least, though, in that case, there are a few attack vectors that are
[00:27:05]
closed off.
[00:27:07]
You cannot include script tags there.
[00:27:09]
You cannot include on-click handlers or these types of things and put
[00:27:14]
arbitrary JavaScript as a string as those attributes.
[00:27:18]
So some of these attack vectors for...
[00:27:21]
Essentially, you actually just can't put JavaScript in there.
[00:27:25]
So you can put HTML, and you actually can do malicious things with only
[00:27:31]
HTML tags if you're accepting untrusted HTML, but you can't execute
[00:27:37]
JavaScript from that.
[00:27:38]
So Elm shuts off that attack vector.
[00:27:40]
Yeah.
[00:27:41]
So to continue on the ways around that that you mentioned, so yeah, you
[00:27:45]
can parse the HTML and you can re-render it using plain Elm functions,
[00:27:50]
or you can use ports or web components to route that to JavaScript and
[00:27:57]
let it render the whole thing.
[00:28:00]
Potentially, and hopefully, with some sanitization.
[00:28:03]
So you mentioned that you couldn't render script tags.
[00:28:08]
Why not?
[00:28:09]
Well, I mean, partially, I think it's just the Elm language's philosophy
[00:28:16]
of pure functions, and it introduces a break in that mental model, a
[00:28:23]
leak in that model, if you have script tags, because now you say, well,
[00:28:27]
this is a pure function, but it renders a script tag that makes an HTTP
[00:28:31]
request.
[00:28:32]
Yeah.
[00:28:33]
And we're back at square one.
[00:28:36]
Right.
[00:28:37]
So I think that, I mean, I think security is one motivation, but perhaps
[00:28:43]
it's almost a side effect, if you will, of that.
[00:28:48]
I would call it a controlled effect of not wanting side effects.
[00:28:54]
Yeah.
[00:28:55]
So the reason why, the technical reason why we can't have these script
[00:29:00]
tags is because Elm's virtual DOM, which is what the Elm slash HTML
[00:29:05]
package and Elm UI and Elm CSS all use, and the Elm virtual DOM is the
[00:29:11]
one responsible for creating the DOM nodes.
[00:29:14]
And basically, whenever you call one of the primitive functions, you
[00:29:19]
pass in the tag name, so that can be a div, that can be an a tag.
[00:29:25]
And if you try to pass in a script tag, then Elm will actually look at
[00:29:29]
that and see, that looks very much like a script tag.
[00:29:33]
Let me replace that by a p tag, so a paragraph.
[00:29:36]
And therefore, you now have a p tag with some JavaScript code inside of
[00:29:40]
it, but when it's rendered to the browser, the browser will not execute
[00:29:44]
it because it's not a script tag.
[00:29:46]
That's embarrassing.
[00:29:47]
You've got your script tag rendered in the DOM in a p tag?
[00:29:51]
Yeah, like you at Sacker are making a fool of yourself.
[00:29:56]
Look at the XML HTTP request that you're trying to show to your users,
[00:30:03]
to your fellow users, right?
[00:30:05]
Kind of embarrassing.
[00:30:06]
Yeah.
[00:30:07]
And yeah, so Elm does quite a lot of these similar tricks where it tries
[00:30:12]
to prevent you from declaring and executing JavaScript code through
[00:30:17]
different ways that the browser would understand it.
[00:30:19]
So script tags are one.
[00:30:21]
Unclick, yeah.
[00:30:22]
Unclick or event handlers in general, it prevents those.
[00:30:26]
And basically the way that it does that is not through sanitizing the
[00:30:30]
JavaScript or the inputs.
[00:30:32]
It's by doing something a little bit easier performance-wise by disabling
[00:30:40]
the tag, like replacing the script tag by p tag, for instance.
[00:30:44]
So the only check is looking at the tag name or checking the attribute
[00:30:50]
name or the property name.
[00:30:52]
So for instance, if you have an event handler, like whenever you click
[00:30:57]
on something, you could have something that says console log or make
[00:31:01]
some HTTP request.
[00:31:03]
Well, the Elm virtual DOM will look at the name of the attributes.
[00:31:08]
And if it looks like something like unclick, then it will change that
[00:31:12]
to data-unclick.
[00:31:14]
And that way that is just data and the browser doesn't try to execute
[00:31:18]
it, doesn't look like an event handler for it in its point of view.
[00:31:22]
So yes, these kind of small tricks, small checks that the Elm virtual
[00:31:27]
DOM does, and that makes it really hard to inject JavaScript.
[00:31:32]
I know there are a few ways we can still do it.
[00:31:35]
And I know that some issues have been opened recently, but I think that
[00:31:41]
those will be solved through some changes to Elm virtual DOM.
[00:31:46]
Yeah.
[00:31:47]
You had some that were merged in recently as well, right?
[00:31:50]
In the last year or so.
[00:31:52]
Yeah.
[00:31:53]
Sometime this year.
[00:31:55]
Oh, actually, when is this episode released?
[00:31:58]
Sometime in 2022, I had.
[00:32:00]
True.
[00:32:01]
So I made a blog post about that, that explained kind of what I'm talking
[00:32:05]
about now and the different vulnerabilities that were found and fixed.
[00:32:11]
Yeah.
[00:32:12]
So I think just to clarify this point, injecting JavaScript is most of
[00:32:20]
those vectors are closed off in Elm, which is kind of a unique thing in Elm,
[00:32:25]
which is really great.
[00:32:26]
It simplifies how you reason about these injection vulnerabilities.
[00:32:30]
One thing that I want to point out is that so the web does give you, again,
[00:32:38]
like these sort of trusted handshakes that somehow fit together, even though
[00:32:42]
there are all these points where we're giving a lot of trust to like, yeah,
[00:32:46]
you can enter your password and send it to this place and it'll probably
[00:32:49]
work out fine.
[00:32:50]
We're putting a lot of trust, right?
[00:32:52]
Another place that we put our trust is like, if you, for example, if you
[00:32:57]
inject an image tag, it will perform a get request.
[00:33:02]
So that's actually a way to inject a get request.
[00:33:05]
It's a bit subtle, but you put that in the page and the browser injects it.
[00:33:10]
The browser performs a get request.
[00:33:13]
Yeah, which is what some people call a pixel tracker, I think.
[00:33:17]
Well, I would say that's a special case of it.
[00:33:19]
A pixel tracker is one way of abusing that.
[00:33:22]
So one of the reasons why, so it performs a get request, not a post request.
[00:33:28]
So one of the reasons why the HTTP method matters, this is actually relevant
[00:33:33]
on the backend side, but there's an interplay between backend and frontend
[00:33:36]
here.
[00:33:37]
So let's say you have a logout endpoint that accepts a get request.
[00:33:42]
Now you post an image to google.com slash logout, like image source equals
[00:33:50]
google.com slash logout.
[00:33:52]
You somehow managed to inject that image source on a page, which there are
[00:33:56]
many ways to successfully do that.
[00:33:59]
And now you've logged out the user.
[00:34:01]
That's inconvenient.
[00:34:02]
Maybe you even have effectively locked them out of that account where they
[00:34:06]
can't enter their account.
[00:34:08]
That's not good.
[00:34:09]
Right?
[00:34:10]
So that's something that you have to understand, these handshakes and
[00:34:14]
protocols and how these different tools and conventions are giving trust and
[00:34:20]
authority by using them.
[00:34:22]
And so because you're essentially saying, like, I will allow, like, within my
[00:34:28]
web page, if you make a get request, I will perform that get request and send
[00:34:33]
along my cookies.
[00:34:34]
Now, usually the way it's set up, it's only going to send those cookies to the
[00:34:38]
same domain.
[00:34:40]
So usually that's not going to be an issue because you trust sending those
[00:34:44]
cookies to that same domain.
[00:34:46]
But you need to be aware that you're, by using these web standards, you are
[00:34:54]
putting trust by doing certain things.
[00:34:56]
So that's why, like, you need to be sure to not perform side effects when a get
[00:35:01]
request is done, more or less.
[00:35:03]
Right?
[00:35:04]
You can, okay, I can give this data.
[00:35:07]
I can do analytics and yeah.
[00:35:10]
Exactly.
[00:35:11]
There's a bit of a gray area, but you need to be careful about that.
[00:35:14]
You need to be aware of what you're essentially authorizing by choosing to
[00:35:19]
accept the get method by performing some action.
[00:35:23]
So we've talked about people injecting things to NPM packages, for instance.
[00:35:28]
We haven't talked about doing it through Elm packages.
[00:35:31]
But you can probably do similar things, right?
[00:35:34]
So if you want to make an HTTP request from an Elm package, there are
[00:35:38]
multiple ways to do it.
[00:35:39]
But the main one is to do it through the Elm slash HTTP package and to call
[00:35:46]
the HTTP functions and therefore return either a task or a command.
[00:35:52]
Right?
[00:35:53]
So already the nice thing about this in Elm is that you have a type that
[00:35:58]
tells you, hey, this is doing something.
[00:36:01]
This is an effect.
[00:36:02]
And these are pretty much the only things that you have to look at.
[00:36:05]
If you want to audit things carefully, make sure that no one is sending
[00:36:11]
weird requests over the wire.
[00:36:13]
Look at whatever is returning a task or a command or whatever that contains
[00:36:19]
one of these.
[00:36:20]
And you can only use them in the context of an update function.
[00:36:25]
Right?
[00:36:26]
If these are used in a view function, it doesn't matter.
[00:36:29]
They won't get executed.
[00:36:31]
That's something that differs from something like React, where even if you
[00:36:36]
call this function, it's not going to get executed.
[00:36:38]
But in the context of React, yeah, you might want to worry about this
[00:36:43]
because calling this function will trigger the HTTP request.
[00:36:46]
And the other way that you can create HTTP requests is, like you said,
[00:36:52]
with HTML.
[00:36:54]
And this is something that is actually possible in Elm, but doesn't happen
[00:36:59]
in practice.
[00:37:00]
And I'll talk about that, why.
[00:37:02]
So someone can create some div or HTML elements and publish that as part
[00:37:09]
of an Elm package.
[00:37:11]
And if that one contains an image with a source that leads to a malicious
[00:37:18]
attacker's URL endpoint, then automatically we'll be sending data,
[00:37:25]
cookies potentially, to the malicious attacker.
[00:37:29]
Although cookies are...
[00:37:30]
Yeah, not cookies.
[00:37:32]
I think over HTTPS, cookies will never be sent cross-origin.
[00:37:38]
Ah, maybe, yeah.
[00:37:40]
You know what?
[00:37:41]
No, I think when you set HTTP-only cookies, you can set your policy.
[00:37:47]
So the default HTTP-only cookie policy is lax, which sounds like it would
[00:37:53]
be relaxed, but it's actually fairly strict.
[00:37:57]
So you can do lax, strict, and I think the third option is none.
[00:38:01]
But only the none option, which is not the default, will allow cookies
[00:38:07]
to be sent in cross-origin HTTP requests.
[00:38:11]
So generally, you're not going to have cookies being sent to other domains.
[00:38:16]
Yeah.
[00:38:17]
I have heard of people using this technique to notice when the policy
[00:38:22]
was not set the right way.
[00:38:24]
So there is a pixel tracker or something that just sends requests to the
[00:38:29]
malicious attacker's servers.
[00:38:31]
And the only thing that it actually tells the attacker is that, hey,
[00:38:36]
this website here is vulnerable.
[00:38:38]
Yummy cookies.
[00:38:40]
It's not correctly protected.
[00:38:42]
If there's one thing hackers love, it's yummy cookies.
[00:38:45]
Yeah.
[00:38:46]
So yeah, this you can do in Elm.
[00:38:48]
So if you really want to do an audit, you need to check for tasks,
[00:38:52]
commands, and HTML.
[00:38:54]
Although for tasks and commands, you only have to care about whether
[00:38:57]
if the package depends on Elm slash HTTP.
[00:39:00]
Otherwise, it doesn't matter.
[00:39:02]
There's nothing that I think people can do without that.
[00:39:06]
Yeah, or anything that influences the strings in the URL in your HTTP
[00:39:13]
request.
[00:39:14]
So you have to look at, in general, the flow to these insecure
[00:39:19]
sort of endpoints.
[00:39:21]
What are the points in your application where you can do potentially
[00:39:25]
malicious things, HTTP requests, image tags, things like that?
[00:39:28]
How is data flowing to them?
[00:39:31]
So if you perform an HTTP request and it's a hard-coded URL and you can,
[00:39:37]
you know, add a query parameter from the user, that's very different than
[00:39:42]
if you're taking the entire URL from the user input.
[00:39:45]
That can potentially be more malicious.
[00:39:48]
So you have to consider, like, the flow of trusted and untrusted inputs
[00:39:54]
and trusted and untrusted code to these potential attack vectors.
[00:39:59]
Absolutely, yeah.
[00:40:00]
In practice, I found that to be quite rare, but yeah, absolutely.
[00:40:04]
And in Elm, there are fewer of these attack vectors and there's, like,
[00:40:08]
a cleaner, clearer flow to them.
[00:40:11]
So it's just there's less attack surface area and an easier way to analyze
[00:40:19]
how untrusted things may go to them.
[00:40:21]
Yeah.
[00:40:22]
You can't just say, well, replace the HTTP or XML HTTP requests
[00:40:27]
implementation by this, and now the URL will always be this.
[00:40:31]
Right, exactly.
[00:40:33]
Yeah.
[00:40:34]
And Richard Feldman gave a talk.
[00:40:37]
He was at Oslo Elm Days, and I'll link to the talk.
[00:40:41]
I've mentioned it before, but he made a really nice point there.
[00:40:44]
He also talked about NPM package vulnerabilities and all that stuff.
[00:40:49]
But he was talking about in Elm, you know, why would you even want to install,
[00:40:56]
like, Richard's like, I trust Luke Westby, but why would I use
[00:41:02]
the Elm HTTP builder package?
[00:41:05]
Why would I use any third-party code to construct an HTTP request when,
[00:41:11]
if you look at the API, just, like, copy-paste the parts of it that you want,
[00:41:15]
look at the code, make sure it looks good.
[00:41:17]
And then not only is it, like, secure stuff that you don't have to trust
[00:41:21]
and you don't have to think about if I'm updating the version,
[00:41:24]
did another maintainer take over and push commits in there or whatever,
[00:41:27]
but now you can say, well, this is the hard-coded URL for our API.
[00:41:35]
So the HTTP builder API, you can custom-tailor it for your needs
[00:41:40]
and make it safer where you're not even thinking about what URL does it go to
[00:41:44]
because it only goes to one URL, or it goes to here's a custom type
[00:41:49]
of the three different possible URLs it can go to, and you choose one.
[00:41:52]
So it's a tool for reasoning and constraining these things
[00:41:56]
so that you can analyze the flow even more easily
[00:41:58]
and not have to depend on third-party code.
[00:42:00]
Because so much of this third-party code,
[00:42:02]
just vendor it or bring it into your own codebase, build it yourself.
[00:42:06]
Yeah, and because of this, we tend to not have many packages.
[00:42:12]
We don't tend to have many dependencies in our applications.
[00:42:16]
And that makes it much easier to audit our code if we really want to,
[00:42:19]
because there's, I don't know, maybe a few dozen dependencies
[00:42:23]
for very large applications, and that's it.
[00:42:26]
And you only have to look at the ones that depend on HTML,
[00:42:30]
Elm Virtual DOM, and Elm HTTP.
[00:42:33]
And that reduces them by, maybe you only have two or three left at most.
[00:42:38]
And auditing, I think, is where this stuff you were talking about before
[00:42:42]
really comes into play, the prototype pollution and things like that,
[00:42:48]
where you can set global variables and have effects happen
[00:42:51]
in unexpected places that get triggered in strange places.
[00:42:55]
You just don't have to think about those things with Elm.
[00:42:57]
So auditing code is so much more straightforward.
[00:43:00]
Yeah, just like it's also very simple code, right?
[00:43:03]
It's Elm, there's no mutations, there are no global effects, blah, blah, blah.
[00:43:07]
But also because we have so few dependencies, right?
[00:43:10]
That's very different from the NPM ecosystem,
[00:43:14]
where people use thousands of NPM dependencies,
[00:43:18]
often without knowing it, because there are so many indirect dependencies.
[00:43:23]
And there's this one thing where we're lucky that the Elm community is quite small,
[00:43:31]
and that is security.
[00:43:33]
Because if there are 10 million JavaScript developers,
[00:43:37]
and like, I don't know how many we are.
[00:43:40]
I don't want to make it too small nor too high.
[00:43:43]
I don't know, how does that work?
[00:43:45]
Less than 10 million.
[00:43:47]
Yeah, less than 10 million developers.
[00:43:50]
Well, then it's not going to be very interesting for attackers
[00:43:54]
to create these malicious packages.
[00:43:56]
Like maybe one of them or two of them will do it.
[00:44:00]
But also the things that they're going to be able to do with it
[00:44:03]
is going to be very restricted compared to what you do in JavaScript.
[00:44:08]
And also to make it possible is much harder
[00:44:12]
because you are much more constrained.
[00:44:14]
Oh, you want to make an HTTP request, then you have to go through
[00:44:18]
an update function to return something with a task or a command.
[00:44:22]
And that's going to be a lot more obvious.
[00:44:24]
Or you need to do something like a pixel tracker,
[00:44:26]
and then you're kind of limited in the kind of information
[00:44:29]
that you can send to the malicious attackers' servers.
[00:44:34]
And also, you don't have access to cookies in Elm in practice, right?
[00:44:39]
So there's almost no information that you can send.
[00:44:42]
You can't do document.cookies and reach into the cookie jar to get, yeah.
[00:44:47]
And we should mention those are so that document.cookies
[00:44:51]
allows you to get cookies that are visible to JavaScript.
[00:44:55]
One practice that I really like is using HTTP-only cookies.
[00:44:59]
So they're not visible through document.cookies.
[00:45:03]
They're only visible, the server receives them as a request header
[00:45:08]
when you make an HTTP request to the same origin, to the URL you're on.
[00:45:13]
And it will not send any of the other cookies to any other places?
[00:45:18]
Right. Yes.
[00:45:20]
If you're using the default permission type security policy
[00:45:24]
for HTTP-only cookies, then it will not send them to other domains.
[00:45:32]
So that's a very secure way to do it.
[00:45:34]
It does, well, we'll talk about this in the future,
[00:45:37]
but you sort of need to be able to have a server-side story
[00:45:42]
where you're deciding what data to send, right?
[00:45:46]
So that could be a Rails application where you're maybe grabbing,
[00:45:50]
like deciding that the user is logged in in a Rails application
[00:45:54]
that can read the cookies in the incoming request
[00:45:58]
and then say, okay, the user is logged in.
[00:46:00]
Here's the user-specific data that I'll send
[00:46:03]
that can be passed in as flags to the Elm application that's rendered.
[00:46:07]
Elm pages v3, you can do similar things because you can, in pure Elm,
[00:46:12]
look at the incoming server request cookies and do a logged in user session.
[00:46:17]
So, but those types of approaches where you have a server involved in the process
[00:46:22]
rather than a client-only application
[00:46:25]
that doesn't have an opportunity to look at HTTP cookies,
[00:46:29]
you can do some of these practices that are just easier to reason about
[00:46:34]
that you're doing in a secure way.
[00:46:35]
There's less to think about protecting the cookies from an attacker.
[00:46:39]
So we've talked a lot about making HTTP calls,
[00:46:43]
but I would generally say that we don't want anything unexpected
[00:46:48]
or malicious to happen in the context of security, right?
[00:46:52]
And something that unexpected that can happen is that your code crashes.
[00:46:57]
Like you start depending on a package and now everything crashes because of it.
[00:47:03]
And now your whole application is made unusable.
[00:47:08]
So a malicious attacker could want to do that
[00:47:10]
if they want to sabotage your application.
[00:47:13]
But that is much harder to do because it's Elm, right?
[00:47:17]
Like there's not many things that you can do that will cause runtime errors.
[00:47:23]
You still can do things like infinite loops or infinite recursions,
[00:47:29]
but it's going to be very restrictive in what you can do.
[00:47:33]
Yes, it's very restrictive.
[00:47:34]
I think one interesting exercise is to think about
[00:47:37]
where does Elm delegate directly to JavaScript
[00:47:41]
and where does it protect that or not?
[00:47:46]
So for example, you can create a regex in Elm
[00:47:50]
that creates a JavaScript regex under the hood.
[00:47:52]
JavaScript regexes have DDoS vulnerabilities,
[00:47:55]
meaning you can create a regex that's basically going to crash the page.
[00:48:01]
Do you mean they will crash it or do you mean that it will take so much time
[00:48:05]
that it will make the site unusable?
[00:48:08]
Exactly, exactly.
[00:48:09]
It'll grind it to a halt to the point where it stops responding.
[00:48:13]
That's only a problem for the server, right?
[00:48:15]
See that? It's a gray area.
[00:48:18]
Again, I think you really have to consider,
[00:48:24]
to me this is the mindset.
[00:48:25]
It's like thinking about the flow of untrusted inputs
[00:48:29]
to potential attack vectors and untrusted code to potential attack vectors.
[00:48:34]
So if you have a package that allows you to build regexes,
[00:48:42]
you could potentially say,
[00:48:44]
does an attacker really stand to gain from that?
[00:48:47]
Maybe it's not that big of a risk,
[00:48:49]
but maybe it's something you'd be aware of
[00:48:51]
depending on how important that would be.
[00:48:53]
If they can crash your cat GIF site,
[00:48:59]
then maybe you're like, well, there's not that much in it for them.
[00:49:03]
But if they can crash your site for submitting taxes
[00:49:07]
and they do that on tax day,
[00:49:09]
then maybe that's more important for you to be careful about.
[00:49:12]
What is the flow of untrusted input and untrusted code to attack vectors?
[00:49:18]
And what would happen if that untrusted data or untrusted code
[00:49:22]
did something with that attack vector?
[00:49:24]
So you have to think about that with regexes.
[00:49:28]
Now, if you have user input and you use that directly to do a regex,
[00:49:34]
and now that means the user can DDoS themselves and crash the page,
[00:49:38]
you're like, okay, well, if the user is being malicious to themselves
[00:49:42]
and it causes them to crash their own page,
[00:49:45]
then maybe I'm fine with that.
[00:49:47]
Maybe they deserved it, you know?
[00:49:51]
But if the input is coming from another user,
[00:49:54]
so another user can cause somebody's page to crash,
[00:49:57]
maybe that's not good.
[00:49:59]
So you really have to think about the flow.
[00:50:01]
It's really like just being aware of these things and thinking them through.
[00:50:04]
There's no silver bullet for these things.
[00:50:06]
There is.
[00:50:08]
Yeah, you take that input and then you validate it by making the opaque type,
[00:50:14]
like regex that won't crash the user application.
[00:50:18]
Yeah, sure, sure.
[00:50:19]
And then you can execute that if you have successfully created that kind of regex.
[00:50:24]
And otherwise, you don't execute it, you return an error to the user.
[00:50:29]
Right, yeah.
[00:50:30]
So opaque types, man.
[00:50:32]
I agree.
[00:50:33]
You know what they always say, right?
[00:50:35]
Always bet on opaque types.
[00:50:38]
Yeah, as the saying goes, there are no silver bullets except opaque types, as we know.
[00:50:45]
Elm radio t-shirt coming soon.
[00:50:47]
It could be.
[00:50:48]
It could be.
[00:50:50]
Hey, listener, do you want it?
[00:50:53]
Let us know.
[00:50:55]
So are these the main attack factors that Elm users should be aware of?
[00:51:00]
In my opinion, yeah.
[00:51:01]
Or at least in my, from my viewpoint, yeah, there's nothing more than I can think of.
[00:51:07]
You can have someone run an exceedingly number of computations through infinite recursions
[00:51:16]
or through regexes, if you want.
[00:51:18]
And that's one category of issues that you can, that you might want to look at.
[00:51:24]
The other ones are rendering HTML that will trigger HTTP requests, and the other ones
[00:51:33]
are making HTTP calls through dependencies that will send something to the attacker.
[00:51:40]
And that's pretty much it, in my opinion.
[00:51:42]
So like, even the concept of sanitizing doesn't really apply much in practice.
[00:51:48]
Yeah, most of the time.
[00:51:50]
I mean, I think with sanitization, like, I think just to kind of put a simple process
[00:52:00]
to that, I think it's like, what are the special characters that can break out of the box that
[00:52:06]
you're expecting the user input to be constrained to, right?
[00:52:10]
So if it's HTML, it's like closing, you know, closing caret for a tag and closing quotes
[00:52:18]
and these sorts of characters can escape things.
[00:52:21]
So there are a handful of special characters that will break out of the intended context.
[00:52:26]
There are a finite number of them.
[00:52:29]
There is a way to escape them, to remove their special behavior or meaning, so that you know
[00:52:37]
that the user will be kept in that box.
[00:52:39]
That's what sanitization is.
[00:52:40]
The thing is, you do have to think about, what is the box I'm trying to keep them in?
[00:52:45]
So if like something belongs as a URL query parameter, and you're trying to keep them
[00:52:50]
in that box, now in that context, an ampersand will break them out of that box and allow
[00:52:56]
them to add more URL query parameters.
[00:52:59]
Is that a security issue?
[00:53:00]
It depends on your context.
[00:53:02]
Like if that query parameter can be an attack vector, the way that your API works and you're
[00:53:08]
trusting input that comes from a place that could allow a malicious user to exploit that,
[00:53:14]
then it is.
[00:53:15]
So you need to know, what box are you expecting?
[00:53:19]
Anytime you're taking untrusted input and you're like, well, this data can only do this
[00:53:27]
one thing, you have to make sure it doesn't go outside of that one thing you think it's
[00:53:31]
going to do.
[00:53:32]
Or if it does, it's not going to cause a huge exploit.
[00:53:36]
Or also just give a very bad user experience.
[00:53:40]
Because that can also, it's not an attack factor, but it's also something that we should
[00:53:47]
care about.
[00:53:48]
Right.
[00:53:49]
So I think the thing with the web is that there are a lot of different sort of encoding
[00:53:56]
contexts.
[00:53:57]
Like there's a nice article that I'll link to that talks about like a lot of these, what
[00:54:02]
they call output encoding contexts.
[00:54:04]
So they say like HTML entities is one output encoding context, HTML attributes, URLs, and
[00:54:12]
in particular, HTML attributes that accepts JavaScript, which isn't an attack vector in
[00:54:18]
Elm.
[00:54:19]
But again, even within like the context of a URL, maybe you're trying to constrain where
[00:54:25]
they put that thing to be a query parameter.
[00:54:28]
So you just have to, I think you just have to think that through.
[00:54:32]
That to me, that's the thought process.
[00:54:34]
Anytime you're taking untrusted input, you need to do that thought process.
[00:54:39]
Well, so are there any resources we should point our listeners to?
[00:54:43]
I wrote a blog post about fixing these security issues in Elm Virtual DOM.
[00:54:48]
We could point out that.
[00:54:50]
If you're interested, look at the implementation of Elm Virtual DOM.
[00:54:54]
It's quite short and it can be quite interesting.
[00:54:58]
Otherwise you should probably learn about cross-site scripting issues.
[00:55:02]
So XSS, what they are and how they matter.
[00:55:05]
But yeah, they tend not to matter too much in Elm, in my opinion, my experience, which
[00:55:11]
is so freeing.
[00:55:13]
Like I don't have to care about it so much.
[00:55:15]
Yeah.
[00:55:16]
If you want to explore anything about security, I'm sure there's a lot of things to cover,
[00:55:20]
but not that I'm too knowledgeable about.
[00:55:23]
Do you have any other ones?
[00:55:25]
So the one I want to mention is there.
[00:55:28]
So first of all, there's like a little cheat sheet, a little article from OWASP about XSS
[00:55:35]
attacks.
[00:55:36]
So I'll drop a link to that.
[00:55:37]
That's a nice little resource.
[00:55:38]
But Firas in the JS community did a Stanford course, CS53 on web security, and it is online,
[00:55:50]
available for free on YouTube.
[00:55:52]
It's very long, but you can go and look at the specific lectures you might be interested
[00:55:59]
in.
[00:56:00]
It's very well done.
[00:56:02]
It's a very good summary.
[00:56:04]
There are some modules on cross-site scripting and cross-site scripting defenses.
[00:56:09]
So I'll drop a link to all of that.
[00:56:12]
You can even just like peruse the slides and they're short and concise and explain these
[00:56:19]
potential attack vectors very nicely.
[00:56:21]
So yeah, I mean, I think the web is sort of a magical thing that has all of these conventions
[00:56:28]
that have a lot of meaning.
[00:56:30]
Like when do cookies get sent places?
[00:56:33]
And most of the time we sort of like maybe the defaults kind of work out pretty well
[00:56:39]
or certain backend frameworks or frontend frameworks make assumptions about these things
[00:56:44]
so we don't have to think about them as much because they're built in and taken care of
[00:56:49]
for us.
[00:56:50]
But I think it's good to be aware of some of these things just so you can bring your
[00:56:55]
attention to any places that you really need to be careful about.
[00:57:00]
Yeah.
[00:57:01]
Talking about Feroz again.
[00:57:02]
So he made a company called Socket.dev and he has a very nice blog post, which he has
[00:57:09]
also made talks about called What's Really Going On Inside Your Node Modules Folder.
[00:57:14]
And it's a very scary article about all the things that NPM can screw you over.
[00:57:22]
And it's really nice because reading through that, I'm like, all these things don't apply
[00:57:28]
to Elm.
[00:57:29]
Like mostly because Elm doesn't have any post install scripts when you run a package.
[00:57:37]
Like adding a package is not an effectful thing in practice or it's not anything that
[00:57:44]
can be an attack vector as far as I know.
[00:57:47]
So that one is really nice as well.
[00:57:50]
We have not talked about this as an attack vector, but it absolutely is.
[00:57:54]
Yeah.
[00:57:55]
And I think if someone wants to make an attack vector for NPM, currently this is the way
[00:58:03]
that they tend to do things mostly.
[00:58:06]
But it will mostly target developers rather than users, but maybe a little bit of both,
[00:58:13]
depending on what they do.
[00:58:14]
And basically like send your data to the attacker or start...
[00:58:19]
Mines bitcoins on your machine.
[00:58:21]
Yeah, mine bitcoin.
[00:58:23]
One of them was kind of stupid.
[00:58:25]
Like they started mining bitcoin.
[00:58:28]
They did just all the way, like they took all your CPUs to mine bitcoin.
[00:58:34]
And therefore people could notice that their fans were going.
[00:58:38]
They're like, wow, this is a totally normal NPM install step.
[00:58:43]
It's taking many hours with 100% CPU.
[00:58:47]
Oh no, the NPM install finished, but then like, yeah, the CPU was 100% all the time.
[00:58:54]
And they're like, well, something must be going on.
[00:58:57]
Oh, I have something that originated from a script that is doing something.
[00:59:02]
And people investigated it and like, okay, well, it's mining bitcoin.
[00:59:05]
I see.
[00:59:06]
So they could have gotten away with it.
[00:59:08]
Yeah, absolutely.
[00:59:09]
If they were a bit more sneaky, like just using 10% of their CPU,
[00:59:14]
like maybe they wouldn't notice it for a few months.
[00:59:17]
Yeah.
[00:59:18]
Maybe.
[00:59:19]
Interesting.
[00:59:20]
So yeah.
[00:59:22]
Hmm.
[00:59:23]
Yeah.
[00:59:24]
So I'm generally not worrying too much about security, as you might have noticed.
[00:59:28]
Right, right.
[00:59:29]
Because I fixed all the issues.
[00:59:31]
No, it is beautiful to have this like mental model that just, I mean, for me,
[00:59:37]
this is how I feel about so many things in Elm.
[00:59:39]
Like it reduces the surface area.
[00:59:41]
So it's so much easier for me to just focus on solving the problem at hand
[00:59:46]
instead of like all of the junk around it that I don't care about.
[00:59:49]
Yeah.
[00:59:50]
Just the fact of not never worry about sanitization.
[00:59:54]
But I would not underestimate attackers.
[00:59:58]
Like if anything, they're part of the most resourceful kind of people
[01:00:03]
that you can encounter.
[01:00:05]
Right.
[01:00:06]
Well, all it takes is one exploit to be a problem, right?
[01:00:10]
So they can throw the kitchen sink at it.
[01:00:13]
Yeah.
[01:00:14]
But yeah, security is one of those features that Elm has
[01:00:18]
and that I think we don't talk about enough.
[01:00:20]
Like Elm makes small bundles.
[01:00:24]
It is very fast.
[01:00:26]
It makes code very maintainable,
[01:00:29]
but it also has very good security features.
[01:00:33]
And that is very much not the case with other JavaScript frameworks.
[01:00:39]
And we tend not to mention that one too much.
[01:00:42]
And maybe it's because we don't care about it,
[01:00:45]
like in the sense that we don't think about security,
[01:00:48]
and therefore we don't use it as a, we don't mention it as a feature of Elm.
[01:00:53]
I don't know.
[01:00:54]
Yeah. Yeah. It's definitely one of the things that makes Elm delightful.
[01:00:58]
Absolutely.
[01:00:59]
All right. Well, follow us on Twitter.
[01:01:02]
Give us a review in Apple Podcasts.
[01:01:04]
Let us know if you want that opaque type T-shirt.
[01:01:07]
Yeah. And Jeroen, until next time.
[01:01:11]
♪♪♪