I Run Code From the Internet!

Rate this content
Bookmark

Is it wise to run code from strangers? Well, we do it all the time and there's no backing out of it. 

Let's take a look at how a JavaScript project could get hacked and then defend itself from supply chain attacks. 


Limit access to globals for each package? Sure. Control if a package can access network or file system? Yup, that too. And no more install scripts or prototype pollution.

20 min
23 Oct, 2023

Video Summary and Transcription

npm packages are unsanitized inputs from the internet that we run without much scrutiny, so we need to address the issue of malicious packages. Lavamote offers proactive runtime protections to automatically detect and mitigate threats. Lava Mode uses Hardened JavaScript to provide isolation and enforce a policy for your application's build process. The talk introduces a webpack plugin for those who don't want to use the browserify ecosystem. Lavamote's behavior is explored, showcasing how it restricts package access to certain properties. Beta testing is open to gather feedback and improve Lava Mode.

Available in Español

1. Introduction to npm packages

Short description:

Imagine I gave you a bit of JavaScript code and asked you to run it in your application. Would you do it without checking? Probably not. But if I offered to put it in a tar.gz file, some people would be more willing. That's because npm packages are just tar.gz files that you pull from the internet and install in your application. However, we have to acknowledge that these are unsanitized inputs from the internet that we run without much scrutiny. This is the topic we'll discuss today.

🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟�데🐟🐟🐟🐟🐟🐟🐜🐟🐟🐜🐟🐜🐟🐜🐟🐜🐟🐟🐜🐟🐜🐟🐜🐜🐟🐜🐟🐜🐟🐜🐟🐜🐟🐜🐟🐜🐟🐜🐟🐜🐟🐜🐟🐜🐟

Okay, imagine I gave you a bit of text and told you it's JavaScript, it does something, just put it in your application and run it. Would you put it in your application and run it in production for your users? Well, I've done this before, I've asked this question and no one wants to run my code without checking what it is, but if I offered to put it in the tar.gz file, would that help? And now, some people are suddenly more willing to run my code. Why is that? Well, that's because npm packages are just tar.gz files that you pull from the internet, don't read their contents and put them in your application. And don't get me wrong, this is great, I use npm packages all the time, but we have to admit that these are unsanitized inputs from the internet that you put in your application and run without much scrutiny, right? So this is what we're going to talk about today.

2. Dealing with Malicious npm Packages

Short description:

We need to address the issue of malicious npm packages. Reactive tools like npm audit and SocketDev can help identify potentially malicious packages, but they require manual checking. Alternatively, Lavamote offers proactive runtime protections for your application. Imagine a scenario where a developer installs a build tool, and a malicious hacker inserts code into a dependency. This code can compromise sensitive information. To mitigate this risk, we need an app that can automatically detect such threats.

You know, we're installing npm packages, we're installing a lot of them. But what if some of them are not great? And by not great, I don't mean lousy packages, I published a bunch of lousy packages in my time. Nothing bad happened, but I mean actually malicious packages. This talk is going to be strictly about malicious packages.

How do we handle that situation? Well, there's tools that I call reactive tools. You can use npm audit or anything that goes through CVE reports, etc., and tells you that, hey, this package in your dependencies that has been in production for two months, someone reviewed it and found a problem with it. That package is actually malicious. Is that good enough? Probably not. Then there's SocketDev. SocketDev is this new thing where they use various ways of analyzing the packages automatically and come up with suggestions that, hey, this package, it looks like something's wrong with it. You should look it up, you should check what this package is doing. It looks risky. So SocketDev can tell you that even hours after the package has been published, because it's already analyzed. That's a big improvement. Although you have to do the checking yourself. Do you have time for that? Well, now you have to. What are the other options? Well, you can be proactive instead of reactive. And this is where Lavamote comes in. I'm going to tell you about Lavamote. Lavamote is a bunch of tools that together provide for protections for your application. But those protection happen at runtime instead of when you're looking up packages that you wish to install. Okay?

So how does it work? Well, let's go through the basics here. So imagine this developer guy. He wants to install a build tool for the application. What happens is one of the dev dependencies of his application, somewhere in the tree of dependencies of this build tool is controlled by a malicious hacker represented by a black hat and a hoodie, obviously. And what the hacker does, they put a bit of code in an existing package that was already relied upon. That code takes your GitHub token and sends it somewhere. Is that nice? That's not nice. So would you spot it? Well, it's unlikely that you read everything that you put in your dependencies. So instead, let's use an app for that.

3. Lava Mode and Policy Enforcement

Short description:

Lava Mode generates a policy for your application's build process and enforces it. The policy is enforced per package, allowing you to control which built-ins, imports, and globals are available. If a package violates the policy, Lavamode prevents it from importing or using restricted items at runtime. Lavamode uses the language itself to defend against obfuscated or dynamically imported code, intercepting access to global variables. This is based on Hardened JavaScript, enabling isolation.

And this is where Lava Mode comes in. Lava Mode does two things at this stage. It first generates a policy. So you run Lava Mode on your application. In this case, your application is the build process. So you run your build process through Lava Mode with a flag that says, oh, generate the policy automatically. And do you get a policy file that you can edit? Let's get to it in a moment. And then your actual script is not running purely in Node, but it's running in Node instrumented by Lava Mode. And Lava Mode is going to make sure that the policy that is set is going to be enforced.

What's that policy all about? This is the policy. This is a short bit of the content of one policy. So you have that eslint plugin, and it has a dependency that the hacker modified, and the use of HTTPS and process env will likely be detected. So it shows up in the policy. You can switch that to false. Or you can remove those items altogether from the policy, which means these are not going to be available. And what's great is the policy is enforced per package. So inside of the same process, inside of the same contexts, we have sandboxed each package separately in a way that you can decide which built-ins or which imports in general are going to be available to it and which globals are going to be available to it.

So now, with the policy change, you will get an error saying that this package, EvilDependency, requested HDDPS, and it was not supposed to do so. So if a package that was only supposed to process strings had a policy generated, this thing is going to prevent it from importing or using some globals at runtime. And I need to double check that you understand only the initial step of generating the policy is processing the code at all. If it finds something that is being used in a regular fashion, it's going to put it in the policy and then you can modify it. But if the package, even if the package is obfuscated or it uses some... It imports things dynamically or it uses some globals dynamically, if the policy didn't detect it, these things didn't end up in the policy, which means at runtime, Lavamode is no longer reading the code. Lavamode is using the language itself to defend. So if any program is capable of reaching the global variable named process, Lavamode is going to intercept that. And we have the power to decide if process is going to be the process that the program is expecting or if this particular package is going to get undefined instead. This is where the power comes from. You can decide, the hacker cannot. Okay? So this is all based on a thing called Hardened JavaScript. Hardened JavaScript will let us do the isolation.

4. Hardened JavaScript and Lava Mode

Short description:

Hardened JavaScript provides isolation through compartments, lockdown, and harden. Compartments allow for the isolation of processes or tabs, while lockdown repairs and freezes language globals to eliminate prototype pollution. Harden function protects specific objects from untrusted code. The compartment implementation is an early stage proposal pushed by those responsible for object freeze, use strict, and promise. Lava Mode was created to protect Metamask, a browser extension, and uses a browserify based bundler.

And on top of that, we can build the part of Lavamode that decides what can be accessed by whom.

Okay, so Hardened JavaScript is three things. One is compartment. It's a thing that provides this isolation. So you can have compartments in one process in your application or in one tab in your browser. You can have multiple compartments that are isolated from each other. And for that to be safe and to avoid leaving anything in the language that can be messed with, we have lockdown. Lockdown is a thing that you run at the start of your application. And it's going to use the flexibility of JavaScript to remove the flexibility of JavaScript. So lockdown will repair and then freeze all of the globals that are part of the language itself. So object prototype is no longer going to be something that malicious code can fiddle with to do prototype pollution. Lockdown pretty much eliminates the global prototype pollution type of attack. And then last but not least, harden. Harden is a function that you can use to protect a specific object that you want to pass to some code that needs to use it, but you don't want to fully trust that thing. So you can use harden in your application when you're passing some objects to a dependency function and getting them back and then processing them still. So that, you know, they can replace an array with something that just happens to have the reduce method and is going to implement something completely different as the reduce method.

Okay, and compartments, or to be more precise, everything behind the compartment implementation is going to become part of the language. Well, eventually, it's an early stage proposal. There's been a bunch of progress on virtualizing the module loading. This is happening in 2C39, and eventually we will get all of the bits that are necessary to build a compartment in the language itself. And these are being pushed by people who are responsible for bringing us the things like object freeze, use strict or promise. So I'm hopeful.

And we're at a conference that's not exactly about Node. So my previous example was probably less interesting, but we have a bundler. So Lava Mode was created to protect Metamask, the crypto wallet, and Metamask happens to be a browser extension. So it needs to be built, and also it needs to run under content security policy that prevents the use of eval. And the current implementation of hardened JavaScript has to use eval to build an evaluator. In the future, evaluator is also going to be part of the language, but for now, we need an evaluator, but you don't have to use an evaluator that's built on top of eval. If you happen to be a bundler. So we have a browserify based bundler because browserify was the most flexible one and it was the low hanging fruit.

5. Introduction of Webpack Plugin and Beta Testing

Short description:

We're introducing a webpack plugin for those who don't want to use the browserify ecosystem. Webpack is the most flexible built system, and after four tries, we made the plugin possible. We're opening our beta for testing, so please let us know if you encounter any incompatibilities. This is an open source project, and we want to provide support and fix any issues that arise.

So it got developed a few years back and is now been powering metamask integration with laugh mode for a while. So we can take that and use it right away, but we're introducing a webpack plugin for those of you who don't wish to stay in the browserify ecosystem or even get back to it because yes, yes I know browserify is kind of dated. It was great at the time, but now it's kind of dated. Webpack was the most flexible of the built systems that are currently used. So we went with that. And while it initially seemed impassable, but after four tries we got to a point where the plugin is actually possible. And we're going to open our beta, which is a trial run. So no guarantees for security and production yet, but we want to test it out on your project. And please let us know if you find any incompatibilities where your Webpack plugins get interfered with by our plugin. So please get in touch in the discussion thread. This is the only chance to get life support for the plugin without paying for it in any way because this is an open source project. And while we will probably not support everyone all the time, this is the time where we really want to be in touch with you and look at what you're doing and what trouble you get in so that we can fix it for everyone in the future, okay?

6. Exploring Lavamote's Behavior

Short description:

Let's take a look at what Lavamote does live. It's a simple application that imports a package called Cookie Monster. The application sets a cookie, prints out the cookie and location host, and calls for a random quote from CookieMonster. The TypeScript file is also included, and the whole thing is built with webpack. The CookieMonster package is allowed to use fetch, math, and encode URI. However, it also attempts to steal cookies by sending them to a server.

So let's take a look at what Lavamote does live. So this is a very simple application. For the sake of brevity, what it's doing is it's importing a package I made called Cookie Monster. By the way, don't look for this package on NPM. It's a malicious package and publishing malicious stuff to NPM is not a good idea. I mean, I've been banned from NPM before. So let me tell you, you shouldn't do it.

And then there's another package just to prove that you can import some CJS old package and it's still gonna work. There's a bit of TypeScript that's being imported. This whole thing is getting bundled and sent into the browser for running. What does it do? It sets a cookie. And then it prints out the document cookie and the location host for context. And then it calls for a random quote from CookieMonster. And the CookieMonster gives us a quote, a famous quote from CookieMonster, it's always fun. We pass it through leftPad because why not? And then we get a reaction from the TypeScript file so that we know that the TypeScript is working. And this whole thing is built with webpack. So we have app.js as entry point. It gets bundled, and it has some plugins that webpack normally uses. But most of all, it has the ScoreTrop plugin. And we pass the policy in here. This could obviously be loaded from a file because why not, but we're passing the policy here. leftPad is not allowed to reach for any globals, that's normal because leftPad is not relying on any globals. And now, CookieMonster... We allow CookieMonster to use fetch, math, and encode URI. So these are the globals that CookieMonster is going to successfully access.

Okay, now let's look at the CookieMonster. CookieMonster is giving us a random quote from a bunch of quotes that are available, but then also attempting to steal our cookies. Well, is a CookieMonster, what did you expect? So yes, it's going to run a fetch and send your host and your cookies to a server to use them in the future. And this is not the best thing to happen to your cookies, mind you. Let's take a look at the behavior of this application.

7. Analyzing Application Behavior and Beta Testing

Short description:

Let's take a look at the behavior of this application. When running without the Scoretrot plugin, the request sent by the Cookie Monster package steals our cookie. However, when running with Lava Mode, the package is restricted from accessing certain properties, resulting in undefined values. If you want to learn more, I recommend watching earlier talks about hardened JavaScript and taking part in our beta. We provide support to help you set up Lava Mode in your project and appreciate your feedback to improve it.

Let's take a look at the behavior of this application. So I've built this application with and without the Scoretrot plugin, and now I can show you what it's like. So here we are on a page with dev tools open where Scoretrot plugin was not involved. Okay, let me reload the page and show you what happens. So we're on localhost name, chocolate chip is what we have as cookies. We get the quotes and we also get an error because cookie monster was not too discreet with sending this request, but you can see that the request contains our cookie that has been stolen. Meanwhile, if we run with lav modes, you can see that we get undefined. Why do we get undefined? Because, location and document were not listed in the policy. So they do not exist for cookie monster. Meanwhile, our application was successfully accessing them for printing out in the console. That's pretty much what happens here. We're controlling that, not the cookie monster.

Okay, want to know more? There's some earlier talks that I gave about hardened JavaScript, also known as Secure ECMAScript, short for SAS. And Mark Miller, the inventor of hardened JavaScript, had a nice talk with more details that I also recommend you watch. I do recommend you go and take part in our beta, and remember, you can get help to set up your Lava Mode in your project if you just get in touch, either through the beta channel or if you want to run something else than just the Webpack plugin, feel free to get in touch, and I'm offering limited support for limited time to get you up and running. And all that I get back is your issues that you stumbled upon, so we can make Lava Mode even better. Thank you, and stay safe.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

React Advanced Conference 2021React Advanced Conference 2021
39 min
Don't Solve Problems, Eliminate Them
Top Content
Humans are natural problem solvers and we're good enough at it that we've survived over the centuries and become the dominant species of the planet. Because we're so good at it, we sometimes become problem seekers too–looking for problems we can solve. Those who most successfully accomplish their goals are the problem eliminators. Let's talk about the distinction between solving and eliminating problems with examples from inside and outside the coding world.
Remix Conf Europe 2022Remix Conf Europe 2022
23 min
Scaling Up with Remix and Micro Frontends
Top Content
Do you have a large product built by many teams? Are you struggling to release often? Did your frontend turn into a massive unmaintainable monolith? If, like me, you’ve answered yes to any of those questions, this talk is for you! I’ll show you exactly how you can build a micro frontend architecture with Remix to solve those challenges.
Remix Conf Europe 2022Remix Conf Europe 2022
37 min
Full Stack Components
Top Content
Remix is a web framework that gives you the simple mental model of a Multi-Page App (MPA) but the power and capabilities of a Single-Page App (SPA). One of the big challenges of SPAs is network management resulting in a great deal of indirection and buggy code. This is especially noticeable in application state which Remix completely eliminates, but it's also an issue in individual components that communicate with a single-purpose backend endpoint (like a combobox search for example).
In this talk, Kent will demonstrate how Remix enables you to build complex UI components that are connected to a backend in the simplest and most powerful way you've ever seen. Leaving you time to chill with your family or whatever else you do for fun.
React Day Berlin 2022React Day Berlin 2022
22 min
Jotai Atoms Are Just Functions
Top Content
Jotai is a state management library. We have been developing it primarily for React, but it's conceptually not tied to React. It this talk, we will see how Jotai atoms work and learn about the mental model we should have. Atoms are framework-agnostic abstraction to represent states, and they are basically just functions. Understanding the atom abstraction will help designing and implementing states in your applications with Jotai
JSNation Live 2021JSNation Live 2021
29 min
Making JavaScript on WebAssembly Fast
Top Content
JavaScript in the browser runs many times faster than it did two decades ago. And that happened because the browser vendors spent that time working on intensive performance optimizations in their JavaScript engines.Because of this optimization work, JavaScript is now running in many places besides the browser. But there are still some environments where the JS engines can’t apply those optimizations in the right way to make things fast.We’re working to solve this, beginning a whole new wave of JavaScript optimization work. We’re improving JavaScript performance for entirely different environments, where different rules apply. And this is possible because of WebAssembly. In this talk, I'll explain how this all works and what's coming next.
React Summit 2023React Summit 2023
24 min
Debugging JS
Top Content
As developers, we spend much of our time debugging apps - often code we didn't even write. Sadly, few developers have ever been taught how to approach debugging - it's something most of us learn through painful experience.  The good news is you _can_ learn how to debug effectively, and there's several key techniques and tools you can use for debugging JS and React apps.

Workshops on related topic

React Advanced Conference 2021React Advanced Conference 2021
174 min
React, TypeScript, and TDD
Top Content
Featured WorkshopFree
ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.

The two together? Not as much. Given that they both change quickly, it's hard to find accurate learning materials.

React+TypeScript, with JetBrains IDEs? That three-part combination is the topic of this series. We'll show a little about a lot. Meaning, the key steps to getting productive, in the IDE, for React projects using TypeScript. Along the way we'll show test-driven development and emphasize tips-and-tricks in the IDE.
React Advanced Conference 2021React Advanced Conference 2021
145 min
Web3 Workshop - Building Your First Dapp
Top Content
Featured WorkshopFree
In this workshop, you'll learn how to build your first full stack dapp on the Ethereum blockchain, reading and writing data to the network, and connecting a front end application to the contract you've deployed. By the end of the workshop, you'll understand how to set up a full stack development environment, run a local node, and interact with any smart contract using React, HardHat, and Ethers.js.
React Summit 2022React Summit 2022
136 min
Remix Fundamentals
Top Content
Featured WorkshopFree
Building modern web applications is riddled with complexity And that's only if you bother to deal with the problems
Tired of wiring up onSubmit to backend APIs and making sure your client-side cache stays up-to-date? Wouldn't it be cool to be able to use the global nature of CSS to your benefit, rather than find tools or conventions to avoid or work around it? And how would you like nested layouts with intelligent and performance optimized data management that just works™?
Remix solves some of these problems, and completely eliminates the rest. You don't even have to think about server cache management or global CSS namespace clashes. It's not that Remix has APIs to avoid these problems, they simply don't exist when you're using Remix. Oh, and you don't need that huge complex graphql client when you're using Remix. They've got you covered. Ready to build faster apps faster?
At the end of this workshop, you'll know how to:- Create Remix Routes- Style Remix applications- Load data in Remix loaders- Mutate data with forms and actions
Vue.js London Live 2021Vue.js London Live 2021
169 min
Vue3: Modern Frontend App Development
Top Content
Featured WorkshopFree
The Vue3 has been released in mid-2020. Besides many improvements and optimizations, the main feature of Vue3 brings is the Composition API – a new way to write and reuse reactive code. Let's learn more about how to use Composition API efficiently.

Besides core Vue3 features we'll explain examples of how to use popular libraries with Vue3.

Table of contents:
- Introduction to Vue3
- Composition API
- Core libraries
- Vue3 ecosystem

Prerequisites:
IDE of choice (Inellij or VSC) installed
Nodejs + NPM
JSNation 2023JSNation 2023
174 min
Developing Dynamic Blogs with SvelteKit & Storyblok: A Hands-on Workshop
Featured WorkshopFree
This SvelteKit workshop explores the integration of 3rd party services, such as Storyblok, in a SvelteKit project. Participants will learn how to create a SvelteKit project, leverage Svelte components, and connect to external APIs. The workshop covers important concepts including SSR, CSR, static site generation, and deploying the application using adapters. By the end of the workshop, attendees will have a solid understanding of building SvelteKit applications with API integrations and be prepared for deployment.
React Summit 2023React Summit 2023
106 min
Back to the Roots With Remix
Featured Workshop
The modern web would be different without rich client-side applications supported by powerful frameworks: React, Angular, Vue, Lit, and many others. These frameworks rely on client-side JavaScript, which is their core. However, there are other approaches to rendering. One of them (quite old, by the way) is server-side rendering entirely without JavaScript. Let's find out if this is a good idea and how Remix can help us with it?
Prerequisites- Good understanding of JavaScript or TypeScript- It would help to have experience with React, Redux, Node.js and writing FrontEnd and BackEnd applications- Preinstall Node.js, npm- We prefer to use VSCode, but also cloud IDEs such as codesandbox (other IDEs are also ok)