Hello and welcome to Secure JavaScript programming with Vladimir de Turckheim. In this course, we will do some refreshers about npm. I already hear you out. You might not be using npm, but you might be using pnpm, cnpm, or any other package manager. In this video, we will more focus on the features of npm, what security impacts they may have, and all the roles JavaScript ecosystem works in terms of module management. If you're not an npm heavy user, you probably at least use the npm package repository, and that we will see in depth. Before starting, let's create a repository on GitHub. It can be anything actually. We'll make it public, so you can track it. Let's create a node,.gitignore. Let's put an MIT license in it because why not, and an empty README. Now that we have created it, GitHub is pretty happy. It tells us, "Hey, here you have a repo." Let's clone it locally. Set up cd Documents Infosec, 2C07, project, git clone. Then we put our URL, it's cloning and now we can open our ID directly inside the project. Give me a second. That's where it goes, screen recording and this window. Now, we have the project and WebStorm has opened the right page directly. Now, let's start to do things with npm. I opened a terminal at the bottom of the screen, and I start by typing npm init. When I do that, it starts to ask me questions. The first thing it wants to know is the name of the package you're able to create. Let's keep npm-demo. By default, that's the one it offer because it's the name of the current directory. Now, it wants a version. Let's do 0.0.0, because we already have a description, an awesome repo to showcase npm features. We want the main part, it's to index.js. That's a convention, a test command. Let's ignore that for now, I will show later what it means. Right now since we're already within a git-enabled directory, it will detect that there is a git repository available. It will even detect that it is a GitHub directory. Let's put a few keywords. Author, well, that's me. License, it asks for the license. Remember on the repository, we put MIT, so we have an MIT license file already generated. But my default npm suggests to use ISC. Is this okay? Sure. Now, we see that a new file has been created. Let's add it to git, and it's the famous package.json. It has pretty much everything we said, a name, a version, description, entry point, no command for testing, but we will see that later. Npm detected that it was a git repository. It actually took metadata from the git repository and put them here. That's pretty handy. Remember, I added two keywords. I separated them with a comma, and npm now puts them in a list, which means if I publish this package on npm repository, they will be linked with these keywords. Author field is here, license field. Because it's a GitHub repository by default, it will say that there is an issue page that is available and a homepage as the README. The first thing we need to do now is decide if we want to publish this ever on npm. I want to say yeah, true, this is a private package. If you want to make sure that your package is never publicly published, well, you want to put private here because it will prevent npm from uploading that through a remote server and that's pretty handy. Now, another thing we want to do is to give news about the engine version because this might not be targeting all Node.js versions. Let's say that we want to be at least 12.0.0. Now if you install it with lower versions of node, well, it will complain and it will tell the user you're probably doing something wrong. Are you sure you want to do that? It might not work. That's safeguards we can have to protect our package from being used with wrong versions of Node. That's pretty cool. Now, as you know, npm is also used for package management. Historically, it used to say node package manager, but not anymore. They decided just stand for npm. If you don't like that, complain to Isaac, the creator of npm. I'm sure he will be happy to have discussions of that. But npm doesn't stand for node package manager anymore, just stands for npm. Now, we want to add dependencies. Let's say we want to add a very famous web server Express or web framework express, we do npm install --save Express. That will install Express. For most npm commands, they're actually shorthand where a few things end. Npm install can be replaced by npm i and dash dash saved by -S. But since this is an online course, I need to show you the most viable way of doing it. Let's do it this way. Now, npm just does its magic of downloading your package. It created a node module directory where the dependencies are. If I want to list everything that has been installed, I can do npm ls and it will list the installation of Express here. We also have a package-lock.json. Usually, except if you build a library that will be used by other people, if you build a final project, you want to commit and publish this package, this file. What does it contain? Well, it contains the hash of integrity for all the dependencies, which means that as long as this file is not tempered with, your dependencies are not tempered with. Installing something with a same version, but different integrity hash will fail and npm will protect you. That's actually very important if you want to protect yourself against supply chain attacks. That's a topic of another video of the use npm course of the secure JavaScript programming learning track, and we will see that in detail in this video. But as a rule of thumb, either that end project you're handling going to prod with that. In that case, well, you want to commit that and to make sure that it stays, either you're building a library that you will distribute. In that case, don't commit it, or at least don't publish it, it will make the life of your end user very painful. Npm also loves to have devDependencies. If I do install save-dev, I can install the Mocha test library. I could shorthand this by npm i-D for development. Now, if check my package.json, I've got a piece with dependencies and a piece with devDependencies. As you can see, there is a little hat here. What does it mean? Well, npm trains to enforce semver by default. If you're never sure of what it means, you just go to npm semver calculator. You type the name of your package, and you put a range expression. Then you [inaudible] old versions that are actually pinpointed like this. If you want the exact version, you can type the exact version, but you can do a lot of things by playing with the semver range calculator by npm. You need to be aware of that because each time you do npm install, it will take the last updated version, of course, based on what's allowed base package-lock. It will take the biggest version that it's allowed to take. Make sure that you understand these range things, and you can definitely play with that. To be honest, I never know what to do. I usually just use the semver calculator to make sure I don't miss stuff. You've got other ways of adding dependencies in npm. You've got npm peerDependencies. These dependencies are actually expected to be installed also by the end project. If you want dependency a, it needs b, but it won't install b, you are responsible for installing b. Also, it has what's called bundledDependencies. This one is actually pretty interesting because it allows you to add specific dependencies that must be delivered with the package. If you use bundled dependencies, you know that the package will actually contain, when published, the dependencies in an archive file. You also have optional dependencies that might not install for some reason, but that means that's in your code, you know that it may not install and you are okay with that. Usually using a try-catch statement around the import, when it requires or a dynamic import, you won't be able to do a static input on that, will actually enable you to have optional dependencies in your code. Let's try an example and let's install the SQLite 3 package. Let's check what's inside this package. I made a typo, sqlite, not sqlit. It download and we see in the console that it did some other things a bit more. It called something named "node jeep", so let's go in depth in what this is. If I go to "SQlite3", I open it and I want to open its package to JSON. We can see a few extra fields that we are not used to. It has scripts. Scripts enable you to create specific scripts to run at some part of the life-cycle of your project. Here, we've got by default, a script for tests that just logs something but let's do a script for "hello it's me". Now let's even do a script that we will name "pre-hello". Of course, it doesn't mean anything because I missed echo, my Unix app echo. Let's add a past-hello, sorry about that, "echo" done. Now if I do "npm run hello", it will first call the script named "pre-hello" by default, so it will say ''hello''. Then it will call a script named "hello, it's me," and it will call a script named "post-hello," which means that you can define different scripts that be called at different levels. One interesting script to create is the one named install, which means it's time your package is installed, this script will be executed. In the case of SQLite 3, when you do install it calls a script name "node pre-gyp" to install a narrative dependency or download it from the internet. This is actually pretty dangerous because you can actually use that to attack someone by running an install script on their machines, and that happened in the past. If you want to prevent a script from being arbitrarily run when you install, you would usually do npm install, dash, dash ignore scripts. That will ignore the scripts from being executed. But some modules, like a SQlite3, won't work because they will miss something at the install, so you will need to go into the modules and patch the install yourself, but at least you will be protected against malicious scripts running at install. There is one last interesting thing I wanted to show you here is that in your package.json, you can define a bin part where you define scripts. That will actually enable you to build a special executable from that, that can be installed by npm with things like npm install general. But that's more npm in depth. The main security takeaways here are what I said about a package log and install scripts that you want to keep an eye on. Also, it's extremely important that when you install your project in prediction, you use the prediction flag. Let me show you something. I remove package-lock and node modules because they may be [inaudible], and then I do npm i, dash, dash production. What happens is that it will not install dev dependencies. What you want to do is to install the lowest number of dependencies at any time. If you install dev dependencies in prediction, you might bring vulnerable modules to your predictions, modules that are actually okay to have in dev mode but not in predictions. Here it tells me I don't have "mocha" and that's okay because it's a dev dependency. Make sure that this is clean in your repository setup, and that you never install dev dependencies in prediction. Thanks a lot for watching this video. See you soon for more video about security of NPM ecosystem.