JS Security Testing in GitHub Actions

Bookmark

This workshop will focus on automating software composition analysis, static application security testing and dynamic application security testing using GitHub Actions. After a brief introduction covering the different types of application security and the importance of finding security vulnerabilities before they hit production, we'll dive into a hands-on session where users will add three different security testing tool to their build pipelines.

by



Transcription


All right. Thanks everyone for joining us today. We are going to be talking about JS security testing in github actions. So as we mentioned in the previous slide, the only thing you need to follow along is a GitHub account, and we're going to be doing everything in the browser. So one more time, this is the workbook hosted over on our CACA workshop github actions page. And then don't forget to join the Discord server. We will be watching that for questions and posting snippets along the way. Yes. And Brandon, I'm just going to, I continue to post the directions for joining the Discord server in the Zoom chat because we're having a lot of people join. So apologies to people that have seen me post that three or four times. I'm sure you're thinking, why is Rebecca spamming us with how to join the Discord server? But just as we have new people trickling in, really want to make sure anyone and everyone is able to join that Discord server that has the link to the GitHub guidebook that Brandon just had up on his screen. And we're also going to be sharing YAML and code snippets, which works so much better in Discord than it does in Zoom chat. I think in a workshop, someone was like, YAML and Discord equals yelling at my laptop, which is what we definitely want to avoid. So please join us there and we'll be watching both, but highly recommend everyone join us over in that Discord. Thanks Brandon. Of course. Yeah. Thank you. And Rebecca will be watching the Discord to help me stay on top of any questions that come up. So we will get to them for sure. And then a little bit about myself. I'm a software engineer over here at Stackhawk. I'm actually a Kotlin enthusiast, even though this is a javascript conference, but I'm a developer, mentor. I love automating things and I'm always learning. In my free time, I like to snowboard, occasionally I get to play video games and I love tinkering around with my smart home. It's a lot of fun. A little bit about Stackhawk. We help developers find, triage, and fix application security bugs before deploying to production. And then a little bit about this workshop. As I mentioned, all you'll need today is a web browser and a GitHub account. And we're going to be walking through three types of automated security testing that you can do on your own applications. So using github actions, we're going to be building a node application. We're going to add Dependabot to that, which is an SCA or software composition analysis tool. We're going to then add CodeQL, which is a SAS tool or a static application security testing tool. And then lastly, we're going to add Stackhawk, which is a dynamic application security testing tool. So the idea is to look at the application from all the different angles to find vulnerabilities before they get to production. So the first thing we need to do is we will set up some github actions for this workshop. github actions, for anyone who's not familiar, is GitHub CICD offering. It's a simple YAML-based configurable tool. It's got a large marketplace of actions, similar to Jenkins plugins. If anyone's familiar with that, it's event-driven, which means actions that happen on your repository will trigger things for your github actions pipelines. So things like commits to a specific branch or pull requests to your repository can all make things happen to your github actions pipelines. They have built-in secrets management so that you don't have to do any of the other things so that you don't have to keep any secrets in the source code. You'll be able to keep those hidden and linked to the repository that way. And then it comes with 2,000 free minutes per month, although I believe public repositories are free forever and the minutes per month is specific to private repos. So lots of cool stuff there. So the first thing we want to do is we want to get our github actions set up. So if you're on this lab page and you come down here to step one, the first thing we want to do is we want to fork this Vulnerable Node Express app. This will be the app that we will be using today. So come down here to step one, here's your link. And then when you're on this repo, go ahead and click the Fork button. Awesome. And Brandon, just as you're doing this, I put the link in the Discord and I put a thumbs up emoji. We're going to be using this kind of to guide the flow of the workshop. So as you're following along with Brandon, once you fork the repo, if you could react to that with a thumbs up so we know folks are ready to move on, that would be super helpful. Keep going, Brandon. Perfect. Thank you. So yeah, once you get to this screen, just go ahead and pick where it's going and then click Create Fork. GitHub will work under the covers to get this done for us. Now you can see I've got our Node app in my own organization. And I'll be ready to rock and roll. So yeah, as Rebecca said, when you guys are done forking it for yourself, go ahead and give a thumbs up emoji. We'll wait just a couple more seconds for folks to go ahead and get that done. Yeah, I think some folks are having difficulty opening the thread in the workshop channel. It looks like we're the last thread in that channel. If you scroll all the way to the bottom of the RSWorkshops channel, you should see the JS security testing github actions. And for me, it pops up kind of in the right modal, right side of my screen. And I can click the dot, dot, dot to open in full view. So it looks kind of like a regular channel. Christine, I don't know if you've had other folks struggle to open the thread and how you've been helping there. I do experience any issues with opening the thread. Okay. All right. Nilo, let us know if you're able to get it open if you're in the react Summit group, the react Summit Workshops channel, and then the JS security testing and github actions. Like I mentioned, we'll be in there a lot. So I want to make sure people are able to get in there before we move on. And like I said, if you want to fork that app and then give us a thumbs up, that's great. Brandon, will you just go and show us how to do that once more? Yeah. I know you already forked it, so you won't be able to fully do it. But maybe you can just show us where to click and those sorts of things. Yeah, no worries. So once you have the repo pulled up, the fork button is over here on the top right. So if you fork it, you can see that I've already forked it into this organization. So I can't fork it again there, but I can fork it to other places. Awesome. All right. Well, I think it looks like we have a group of folks following us in the Discord again. We kind of always look for the same number of thumbs up before we move on. So if you want to, you're following along, feel free to give us a thumbs up there. But I think, Brandon, let's keep going. Perfect. So the first thing we want to do is we want to get our first GitHub action on this repository. So if you're following along in the guidebook, we want to create this file. The folder structure is very specific to github actions. So it has to live in the dot GitHub slash workflows folder. And then we can name the YAML file anything we would like. For this example, we will name it build and test dot YAML. So from wherever you forked it, you can go ahead and add a file directly from the repo screen. We can paste in the file name that we copied from the workbook. And then the file contents are going to be this first YAML snippet in step one. I think Rebecca is also going to paste this into the Discord. Yeah, Brandon, give me just one second to catch up so everybody can follow along. So I'm going to be dropping in that name for the YAML file into the Discord right now. Perfect. You're too fast. Too good. Like Brandon mentioned, that dot GitHub slash workflows is essential. And this won't work if you don't name your file with those conventions. So make sure you drop that dot GitHub slash workflows slash build and test dot YAML into that header so that we can we can follow along. OK. Now, Brandon, I'm caught up. We're going to keep going through that file. Perfect. Yeah. So here's the contents of this file. So the first thing we're doing is we're going to give it a more readable name for our action. Otherwise, the default would just be the file name. And then this next section are all of the events that the GitHub action will trigger on. So for this particular action, we're going to run a build every time there's a push to the main branch and then any time a pull request is opened. The next section details the jobs. So the jobs for a GitHub action can all be run in parallel. For this example, we're only going to have one job, the build and test job, and it's going to have a couple of steps. So the first thing we have to do for the job is we'll give it a name. So we'll call this one build and test. Again, we will specify the virtual machine that it's going to run on. So this particular one will run on Ubuntu. GitHub will provide this VM for us, and they have a couple of different OSes that you can pick from. But we will stick with just the base Linux for this. And then our first step is a step that's actually provided in that github actions marketplace. So this one is to check out the code and it's a predefined action called action slash checkout. And this will make sure that our action is working with our version of the code. The next thing we want to do is use a predefined action to set up nodes since we're going to need node to be able to build and test this application. So we named this particular step install node 14. And then if you notice, this is a parameterized action. And so one of the parameters it gives us is the ability to specify node version. So we're telling this action that we need node 14. There's other versions available. Just so you guys know, we're not on the latest, but that's OK. And then the next step is a custom command that we're going to be running for this build. So we named it install dependencies. And then I'm sure many of you guys are familiar with this, but we're just going to run an npm install to make sure we've got all of our dependencies pulled down for this build. And then the last thing we're going to do is just run our unit tests. And then this will just use npm test. Again, this is just a custom command indicated with this run keyword instead of a uses. So I think before we move on, it looks like we don't quite have everybody caught up with us before we commit it. Feel free to drop questions into the Discord if you haven't been able to accomplish this or if you're not sure where all this goes or how Brandon created the new file, please tell us what step what step we went too quickly through so we can show you again. Like Brandon mentioned, this is the step that's going to set up our full ci cd pipeline. So we got to make sure we get this deployed so that when we're checking in code later in the workshop, this piece is kind of the fundamentals that allows all those tests run further down the line. So definitely drop us chats or questions in Zoom or in Discord. And then we'll be there. We did get a question, which is I can't find the channel on Discord. I can only see JS Nation, not the react Summit actually know how to fix this one. If you are having this problem. So in the pick your role channel and get Nation react with the react Summit emoji, it's kind of like I think it's the Adam emoji on a purple background that should populate a whole new group of channels, which will get that react Summit. Group and then you can get into the react Summit workshops from there. So again, pick your role, click on the emoji, and then that will populate that new group and you should be able to find us in that RS workshops, JS security testing and github actions thread. Perfect. It looks like that worked. Any other questions, please tell us now. We want to we want to help. Definitely. And for anyone who couldn't find out the add file button, just from the Rupa, the repo you forked, it'll be up here. Now bring you to this. And Brandon, sometimes I know in other workshops, we've run into challenges where people are trying to edit the kaka repo. So just make sure that what is before that slash is your GitHub account name. Brandon's is Brandon, our word slash won't express to make sure you're working in the right repo. What other questions are folks having before we commit that file? Anything, any goshes you can think of Brandon? Make sure that the spacing of this file matches the snippet that was posted in Discord. YAML is very picky with spacing. Yes, yeah. Okay, Brandon, I think let's commit. Looks like we have a group of folks with us in the Discord. Looks like we have a group of folks with us in the Discord. But again, if you have any questions, if you're not sure what we're doing, please ping us. Okay, we got we got a question actually, which is how to access this interface after the fork step. So Brandon, after you click fork, what happens in GitHub? So after you click fork, what it's going to end up doing is it's going to copy the repo to your organization or your user account. And so whichever account you copied it to, if you go to that account's homepage, which is just github.com slash account name, you should see the repo there. If you don't see it, you can always search for it. It'll it'll pull it up down here. And then we are just doing most of this work from the landing page of that repo that you forked. You'll just click add file to get that interface that Brandon had and it will be create a new file. I think is the one you click. And we got another question, which is can we use npm CI instead of npm install? Let's see, I don't know if we oh, we might be able to. So there's a package lock JSON. So there's a package lock JSON. So I believe you can also use npm CI as long as Node 14 has a new enough version of npm installed. So you're welcome to try it. I have not tried that myself. I know they flipped npm versions on Node 14, I think halfway through its lifecycle. So just be wary of that, but it might work. 50 50. Let us know what you find out. All right. I think Brandon, I think I see a couple people typing, but why don't you go ahead and commit it. And if you have questions, just keep them coming. It's so much more fun when we get questions from the audience than Brandon just listened to me. So please give us questions if you're running into any problems. We want to help. Brandon is great. github actions and all this wants to help everybody be successful today. Definitely. Yep. So the commit file button is just at the bottom of that add a new file. And then once you've committed. It will start to trigger an action. Let's see. It looks like in the discord, someone's install node stage failed. Yeah, I saw that too. I'm like, did the yaml not paste incorrectly? Double check the spacing on your action yaml. Another place you can copy this. If you have the workshop open is just from step one. And then there's this copy button too, which can help with the spacing. If you need to edit the file. You can do it right from here. There's this little pen. And then you can check the spacing couple of things to point out name on and jobs are the three top level. Yaml entries. And then everything else is children under those three. Yes. And if there's any specific. Error information. Let us know. So we can help you troubleshoot as well. Looks like it's a passing for some folks. But of course, if you're failing, if it's failing, you want to help. Your dependency lock file is not found. Gotcha. So this is the last one. And then once you've committed. And then once you've committed. And then once you've committed. And then once you've committed. And then once you've committed. Gotcha. So this must be. So I guess to answer your question, it looks like our test project is not set up to work with npm CI. CI. Yeah, I'm sure. I'm sure some folks are familiar with npm CI, but the difference between npm install versus npm CI. Is that install is looking at. The package JSON. And will potentially upgrade dependencies that it can. Whereas the package lock dot JSON is specifically for npm CI. And this is a receipt of all the versions that were installed and npm CI will install those versions. Exactly. Whereas npm install may try to do some, some magic to upgrade dependencies that it can. We got a question on that npm CI Brandon in Zoom chat, which is, does it, does that mean it's better to use npm CI as it uses a fixed version? For your ci cd pipelines, I would recommend npm CI. That's going to create more reproducible builds. And then when you're developing locally, you can use npm install that away as you're. Innovating on your application. If any version upgrade were to break your application, you can handle it in your dev workflow and not when you're trying to release to production. But I think for the purposes of this app, npm CI is not supported. So this app definitely use npm install. Yep. Awesome. We'll work on fixing that for this workshop after this. But for today, just go ahead and use npm install. What other questions? Who has been, are people having success? Are the tests passing? I guess I can. RGG successfully. Awesome. Jenny, the test passed. Perfect. We're getting thumbs up. It looks like things are going well. If you are running into any questions, let us know. Or if you're getting any other error messages. Got to put Brandon to work on troubleshooting. So definitely drop those in too. We'd love to get you help. Definitely. All right. I think Brandon, now that we've kind of set up that GitHub action, I think we got to keep going. We have our CI pipeline going. Yeah. So yeah, our build passed. The next thing we want to do is we want to start adding some security testing to our application because that's where things are going to get interesting. So as I alluded to before, we're going to be working through three types of security testing today. The first is SCA or software composition analysis. A couple of tools that do this are Dependabot, Sneak, and Fossa. For today, we're going to be using Dependabot since it works really well with GitHub and github actions. Software composition analysis always operates on static code, and it's pretty quick. What it does is it catalogs all of the libraries and dependencies that are being used in your application and then reports on those known vulnerabilities in specific library versions. It's fairly low on false positives. There's a little nuance to that because SCA testing doesn't necessarily know to what extent you're using a library. All it knows is that you are using a version of a library that has a reported vulnerability. So something to keep in mind there. These will all be things you'll want to fix, but it doesn't necessarily know to what extent your application is vulnerable to that specific issue. The next type of security testing is SAST or static application security testing. Some examples of that are CodeQL, Sneak Code, and Sonar Cube. This one's a little bit different from SCA because it also operates on static code, but it's specifically looking at your code. SAST is looking at your source code and doing some pattern matching on your code, and it's looking for code smells and things in your code that could be vulnerabilities. This is specifically finding bugs in your application, not related to dependencies. It has higher false positive rates since this is a really hard problem. And so because of that, static application security testing doesn't necessarily know if the vulnerable things it's finding are reachable from the outside world. This kind of scanning is slower because, again, looking at all of your code and running pattern matching on it, looking for vulnerabilities, is a really hard problem, and so it takes a little bit of time. And then the last type of security testing we're going to work on today is DAST or dynamic application security testing. So some tools that do that are Stackhawk, which is built on top of OWASP Zap, but you can also use Zap directly yourself. It's a desktop app. And then another one is Burp Suite. So DAST operates on the running code, and it sends web traffic against your running application and looks for patterns in that web traffic that can indicate a vulnerability. So, again, this is looking at your application, finding your bugs, and it's reporting on those vulnerabilities based on input and output to the application, and it has a lot lower false positive rate since it's specifically looking at web traffic that an outside user could use with your application. It's also slow because, as you can imagine, this is also a hard problem, and so there's a lot to look for when you're hitting a live application. So moving on to Dependabot. So Dependabot is a free service for all GitHub repositories, all public GitHub repositories, I think, or no, I think it's all GitHub repositories. So it's enabled by default on public repositories and easy to add to private ones. And what it does is it looks for libraries with vulnerabilities. A cool feature of Dependabot is it will actually raise pull requests for fixes, and then there are a few false positives with this simply because Dependabot doesn't know how you're using the library, but it will find libraries that have vulnerabilities in your application. So if we flip back to our forked repo, let's get Dependabot rolling on this. So if you go into your repo settings, and then I think I see some questions too about slides popping up. They should be linked in the workshop page, and then you'll be able to access that after as well. Perfect. Thank you very much. Yeah. So from the settings to add Dependabot, we're going to go down into this code security and analysis, and we are going to enable these first three options. The dependency graph, Dependabot alerts, and then Dependabot security updates. Don't worry about the code scanning for now. We will come back to this. So this is going to start working. If you notice, as soon as you enable the Dependabot alerts and Dependabot security updates, some things are going to appear in the security tab, specifically under this Dependabot alerts page. And so this is just a description of all of the vulnerable libraries Dependabot has found in this application. You can drill into any one of these, and it'll give you some insight about what's going on. It'll tell you why it's vulnerable, the kind of vulnerability that could impact your application, and it'll also give you a fix. So let's see, this specific one is for Lodash, and it wants us to upgrade above 4.17.21. This should pull, there we go. It took a little bit of time, but if you notice here, this security alert has a little PR symbol. What Dependabot did was they actually raised a pull request for us to be able to fix this. So you can click that review security update button or find the pull request in your pull requests tab. And you'll notice, since we've already set up our build and test GitHub action, even though Dependabot didn't control this necessarily, but we raised a pull request against main, we are building and testing our applications so that we know it's compatible before we go ahead and merge this version upgrade. So we'll wait there while this build is going, while we wait for people to catch up. Yes, if you've run into any problems, as usual, drop us questions in the Discord and the Zoom chat. Also, if you were able to enable those alerts, definitely give us a thumbs up so we know people are having success. I think the thing I love most about Dependabot alerts is it's so simple to turn on. And especially if you're starting early in your project and you're not coming into a huge app that has tons of dependencies, it's really simple to push those pull requests through and make sure that your app is secure. I always thought so easy the marketing team can use it as a person on the marketing team that will sometimes dabble in this stuff. So I really love that. Yeah, I know, Brandon, you kind of covered the typical questions we get when we go through this, but if there are other questions, please ping us so we can get those answered. If you're wondering a question, you're probably not the only one with that question, so we'd love to help you get that answered. Yep, definitely. So my pull request, my build has passed, so I'm going to go ahead and merge this particular fix in. And then over the course of the workshop, we should see there. So it's already happened. We used to have 17 alerts. This one might take a little while to update, but a couple of those Dependabot alerts have dropped off since we have merged the fix. Got a great question in the Discord, Brandon, which is I think with Dependabot or whenever you update dependencies, it's easy to have your build be green, but the app is broken. For example, some function call was removed even in minor updates. Any automation here or is that only possible through manually checking the app? So what I recommend there is it comes down to the quality of your tests. So in our GitHub action, we are running the tests, and so the hope is that our action would catch if the app was going to break because the test would fail. But yeah, I mean, Dependabot really does depend on how good your actions are and how good they are at preventing merges if the app is broken. So it may not be the best answer, but it comes down to how well you test your app in your CI-CD pipeline as to how effective Dependabot can be for you. Awesome. All right, we got another question on Dependabot. I'm loving this, saving me from asking boring questions. So thank you, everyone, for sending these. So Dependabot looks at the package.json and sees what the problems are. But what if I have a mono-rebroke micro front-end application like multiple projects with multiple package.json? That's a great question. I'm not 100% sure how that would work, but I believe there's a way you can add a configuration file to help Dependabot understand your repo. I would have to double-check that, but I want to say that they've provided something along those lines for the advanced use case such as a mono-repo with multiple package.jsons. Yeah, awesome. Great question. We're going to have to look into that. Now I've got to go find my answer after this. Oh, it looks like someone just posted in the Zoom chat an answer about using Dependabot with a mono-repo. I'm going to just reply to the original question as well. Oops. Let me get that for you. Except it doesn't want to let me do that. Perfect. Thank you, Nikhil, for sharing that. Really helpful. Yeah, I really appreciate the article. That's awesome. Awesome. All right, everyone, if you're feeling good about Dependabot, make sure you give us that thumbs up. If you're still having troubles or maybe your pull request didn't pass or you missed how to navigate to that portion, we're happy to show you once more. But otherwise, I think you want to get going with CodeQL? Definitely. All right. So the next thing we want to do is add some SAS scanning to this project. So to do that, we're going to use CodeQL. CodeQL is another service provided by GitHub. It is free for public repositories, although I do think it costs something for private repos. Anyways. Yeah. I think you have to be an advanced security user maybe for private repos, but don't quote me on that. Yeah. So CodeQL, as we mentioned before, since it's a SAS tool, it's going to scan the code in this app or it'll scan your code, and it's going to look for patterns that can be related to a vulnerability or code smells, and the database of patterns that relate to vulnerabilities is constantly growing and changing. So as you're going to see when we integrate CodeQL, what we're actually going to do is we're going to set it up on a cron as well so that it can constantly be looking at our application. That way, if any new vulnerabilities come up, we will be covered. So if you flip back over to the repo, go back into Settings and back into this Code security and Analysis, we're going to come back to this code scanning section and click Setup here, and then we're going to configure CodeQL alerts. So if you notice what this is going to do for us is it's creating another GitHub action. This one's going to be called CodeQL analysis, and I can walk through what's happening here in this actions YAML. So it named this build CodeQL. It's going to happen on a couple events. Anytime we push to the main branch, anytime a pull request is opened against the main branch, and then looks like once a week on Sundays, it'll also trigger this CodeQL scan. This action also is only going to have one job. It'll be the analyze job. It'll run on Ubuntu, and then this one is unique in that it needs a couple of GitHub permissions because as you'll see, it's going to decorate our repo with some additional information to help lift it up and make it visible for us. When we click Setup, GitHub auto detected that this is a javascript project. This language matrix, you can do multiple languages in case you've got a mono repo or a use case where you have more than one language that you need to scan. You can see it supports a good number of languages, and then this javascript language also works for typescript in case you use that. A couple of steps to this CodeQL task. It'll first check out our repository again with that precanned checkout action. It will initialize CodeQL with our languages. This is unique in that we're passing it a matrix. If you had more than one language, it would initialize CodeQL for each of those. This auto build step is another predefined action for CodeQL, just so that it can understand your application. If you're working with a Java or a C Sharp application, it needs to scan the compiled code. Lastly, what it's going to do is using one more predefined action, it will analyze our code. Let's see, should we wait for everyone to get caught up or should we start this commit? I think since that was all pre-populated, why don't we go ahead and start the commit. Then as we commit this, if folks have questions, we are here to get you answers. I will. Then if we commit that and then the steps pass and we get the pull requests generated. Now when you flip over to your actions tab after you've committed that, you'll notice we have two jobs running. We have our CodeQL job, which we just created. Then we've got our build and test, which is the first action we created. GitHub will run these in parallel for us. We have both going at once, which is super cool. I think the reason that's so helpful is that if you are parallelizing those, your CI-CD pipeline is going to take less time, which is always critical. If you are a developer, you know you don't want to sit around waiting hours for tests to run. If you may be a devops or a VP of engineering, you realize you probably have an SLA, you have to be held to to get that CI-CD pipeline going. Another great thing that we've done is we've been able to do a lot of work to get the CI-CD pipeline going. Another great thing to love about github actions and how they can parallelize these workflows. Then this scan is pretty quick. You can watch it from the Actions tab, but then this will show some pretty cool things when the analyze is done. We'll go ahead and wait for that here. It usually doesn't take too long with this project since it's relatively small. All right, so it looks like that is done. And then if you jump back over to the security tab, you notice we've got one code scanning allowed. This was generated by code QL, and basically it looks like it's telling us that this application is vulnerable to SQL injection. So as you can see here, we're basically just passing user input directly to our database query, which is only good if you want to give the end user dramatic results. But code QL correctly indicated that this was in fact SQL injection. So pretty cool stuff. Now what code QL can't tell us is if this is actually accessible to the outside world. And I think it's nice in code QL, and we'll get into this with Starbob too, but it's nice in code QL, but it's nice in code QL, and I think it's nice in code QL, and we'll get into this with Starbob too, but you get a little bit of information around kind of the error that they've found down below the issue, and I think that show more will give you even more details about kind of the issue you've run into. So if you aren't super familiar with security, resources kind of built in to help you understand what this error is if you haven't heard about it. Brandon, we did get a question, which is where can I find the contents of the code QL-analysis YAML? So that was auto-generated. When you went to settings and code security analysis, when we set up code scanning, GitHub provided that. And then, let's see. I can also post this link, which is just the direct link to the file that it generated for me, if that's useful as well. But yeah, this was all auto-generated by GitHub. What else? Has anyone else run into any questions on this one before we move on? Another pretty easy to get deployed, and it's nice that it also generates those pull requests for you. Or I guess, does code QL generate those pull requests, or did I just make that up? You're a dealer. Yeah, this one doesn't generate any pull requests. This one will just tell you it sees something that you should probably fix. I wish it was smart enough to help with the fix, but it's hard enough to find these issues, let alone fix them. Sure. All right. Well, I think, Brandon, we have two under our belts. I'm not seeing any other questions come in in Discord or the Zoom chat, but again, if you have them, feel free to drop them there. Otherwise, Brandon, I think let's get going deploying dynamic testing. All right. So the next tool we're going to use is Stackhawk for modern dynamic application security testing. So this is really cool because it will test the running application, and it will be able to tell you if a vulnerability is actually accessible from the outside world. So like we mentioned before, this is testing based on how an end user would use the application, and it's all with web traffic. And so, yeah, our scanner is built on top of OWASP's app, as I mentioned before, and then it's packaged as both a Docker container and a CLI that you could brew install if you're on Mac. The YAML configuration is very simple, easy to get going with. We recommend using it in your CI-CD pipelines, as we'll show here in a little bit. And then the platform itself helps you with your scan tracking, and it's got some notifications, integrations, project management tools to handle Slack, MS Teams, JIRA, those kinds of things. And then if there's an integration that you don't see, we have webhooks for everything else. So you can build anything you want to track your DAST findings. So from the workshop page, in order to get a DAST scan going, if you come down to step four, the first thing you'll want to do is sign up for a Stackhawk developer account. When you come here, we've got a couple of ways you can sign in. You can do SSO with GitHub or Google, or you can do email and password. If you use email and password, it'll be a little bit slower, because you'll have to do two-factor authentication and wait for the email. I'm going to use Google, and I've got a pseudonym account so I can make a quick Google SSO org. When you sign up, the first thing you'll be prompted to do is just name your org. I'm going to call this my react Summit org. And then I will go ahead and continue. I'll wait just a couple of seconds for people to catch up before I continue through this page. On this page, we provide a way for you to see some canned data through Google Firing Range, but for this workshop, we're going to be scanning our vulnerable node.js application. So when you get to this page, make sure you pick Scan My Application. It's a lot more interesting, too, to scan your own app. So we'll do fun stuff with that. Brandon, I know if you're doing email signups, you'll probably have to go verify your email. If you want to go ahead and throw us a thumbs up in the Zoom chat or like the Sign Up for a Stack Web account in the Discord, there's just a couple of welcome screens we're going to walk through together, and I don't want to lose anybody. So before we move on, if you just want to hit us with a thumbs up so we know everyone is good, that way we won't lose anybody. Yep. Yeah, the emails are pretty quick, but it's still a few more clicks than Google and GitHub SSO. All right. We got a question, which I think will be a great way to kind of give folks that are sending up an email a little bit of accuracy for time, which is, so if we fix some of the DAST security findings, would it also fix some of the SAST security findings or catch SAST false positives if it doesn't show in DAST scanning? That is the goal. So the cool thing about DAST and SAST is we actually recommend that you do both, because they are looking at different things and they scan your app in different ways. And so to be sure that you're fixing all the vulnerabilities like you said, to catch a SAST false positive or get some more insight, a DAST scan would help you know if that vulnerability is reachable from the outside world. I think Brandon might have a cool DAST and SAST integration he might show us later in this that helps not only identify like the top priority fixes, both tools are finding them, but also correlates findings so that you can quickly take action on those as a developer, be like, oh, this DAST finding lives in this line of code. So we'll show that a little bit later. But great question. All right, Brandon, I think let's keep going. Hopefully everyone now has had some time to get those account signups in. Perfect. All right. So when you get to this page, the first thing you'll notice is that it's going to give you a Stackhawk api key. So I'm going to grab this and I'm going to turn this into a GitHub secret. So if you go back to your forked application, go into the settings, expand secrets down here and then open up actions. We want to make a new repository secret. We're going to call this Hawk api key and then paste your api key into the value box. This will be unique for everyone, the value. And then if you name it Hawk api key, you'll be able to copy paste the next portion of the workshop directly into your action. Can you show us that once more, Brandon? Yep. So from this page, you'll see the api key generated. So you'll want to copy it here from the settings tab. You'll want to come into this secret section and make sure you're clicking on actions. And then you can make a new repository secret up here. Or if you think you mistyped your api key, you can always update it from here. Once you create a secret, though, GitHub won't show you the value again. It'll just let you override it. And I know sometimes when we run these workshops, we have had people that have joined us at previous workshops, so they aren't getting this prompt in the modal. If you're in that scenario, we're happy to help you learn how to generate another one. I think it'll kind of confuse folks. If we aren't having that scenario, we won't dive into it. But if you are, please let us know, and we can certainly walk you through that as well. Give us a thumbs up in the Zoom or in the Discord if you've stored your api key. If you haven't stored this, nothing will work moving forward. So this is, again, kind of one of those steps we don't want to breeze past. Make sure you're calling it hawk underscore api underscore key, and you have it saved as a secret. Brandon, I think sometimes we run into people that are asking, why do I need to store a secret here versus hard coding? Kind of all known as a security, an important piece of security for repos and secrets, but maybe you can just add a little bit of color there while people get caught up. Yeah, so especially with this project. This project is a public repo, which means anyone on the Internet could find it. And so if you are directly committing your api key to your build YAML, then anyone could come in and hijack your Stackhawk account. And we don't want that to happen. And this goes for any build secret you might have. You don't want to put it directly in the source code. So GitHub provides this wage so that you can access them during your build, these secrets without letting them be public, which is super cool. And I think there are other tools out there as well that can help with this, or identify secrets in repos. Like I think Hashi Vault helps with this and a few others out there. But not a formal type of security testing in making sure your secrets are stored securely, which is a really important part of security in code security broadly. Okay, Brandon, I'm hoping. Oh, we got a question. Is it also possible to put secrets in an environment file? By that, do you just mean your environment when you're running the application or I guess I need. Okay, so I believe there is and some of that depends on how you're using the action. So the action GitHub provides a way for your secret to get to the action. And then if you're using that action to deploy as your build is running the deployment, it would have any secrets that you would need to put in your environment file while it's running that. Is that kind of what you were asking or? Let's see. So any secrets that I use in GitHub workflows should be added in secrets. Yep, exactly. So anything you put in this action section will be available to any of your github actions workflows, whether that's building security scanning or even deploying. Okay, perfect. All right, let's keep going. Brandon, thank you for those great questions. You weren't I'm sure you weren't the only one that had questions about GitHub secrets. Action secrets. I mean, all right. If you wanted to run Huxcan locally, this is just some tips or some things you can do to your local shell that would make it work seamlessly. I'm not going to go too far into that today since we're going to be running it from github actions. The next thing we'll want to do is create our first application. I'm going to name mine bone node express. For an environment, I'm going to pick the development environment. And then the host that this will be running on in github actions will be HTTP. And I know it's muscle memory these days to add the S, but this this app won't be running secure locally for the scan. HTTP local host port 3000. The application type will be a dynamic web application slash single page application. And as you can see, we support a bunch of api types. But for now, I'm just going to click other for this particular application. I'm going to go ahead and click next. And then on this page, it'll prompt you to download the stack hockey animal. So I'm going to go ahead and download that because we'll need it for the next step. The. So the selections that I picked, those are all in the discord in case you aren't sure. I'm actually going to add the app type. The dynamic web page slash single page app right now. Yep. And then just other for the api. And don't forget to download your stack hockey animal. Maybe when you just click back to app details and show that once more. Back one further. Perfect. So my app details, I just named it bone node express scanning the development environment on HTTP local host 3000. Not HTTPS. You'll get a failure HTTP. The app type is a dynamic web application, the api type. We're just going to pick other for now. And then when you get here to the last step, make sure you download your stack hockey animal will need that for the next step. Couple other things about what you see on this page. If you wanted to try running the scan locally, we've got a super cool CLI that we've been working hard on. That is now GA. The next question I haven't seen before. Yes, which is the next button is disabled. Which page is the next button disabled on? Maybe we can help troubleshoot. Yeah, I would just double check that you filled out everything on the app details. Those are all mandatory fields. So if you didn't fill one of those. Oh, I put in a trailing slash. Thank you. Let me edit that. That is my fault. Yeah, I think we do some host validation on this field to make sure it's a valid URL. And we disable it if it doesn't look quite right to us. Thank you, Sid. And the person I was asking the question, the session is being recorded. It certainly is. Yep, and it'll be uploaded. I'm not exactly sure the timeline, but I'm sure it'll be uploaded soon. Yes, I think they're usually pretty quick. That's a question for Christina when she comes back. Someone asked how long is it available to watch? I don't know. Unfortunately, the recordings are owned by Git Nation, not Brandon. So is there a little bit out of our control? We do have previous versions of this workshop, not run by Brandon, unfortunately. On our YouTube, though, that you can feel free to DM me and I can share those with you as well. Or go to the Stackhawk YouTube in there. We have a link in the workbook. There's a link to a YouTube version of this talk. Awesome. All right. We got the trailing slash worked out. That's my fault again. Thank you, Sid, for catching that. We owe you one. If you have any questions, let us know. Otherwise, give us a thumbs up once you've downloaded that Stackhawk YAML. And we will show you how to get this into your github actions pipeline. All right. Looks like people are ready. All right. Let's keep going, Brandon. Cool. So I'm going to go ahead and click Finish on that modal. Come back to my repo. And first, we're going to add another file. So this one's just going to be at the root of the repo. And it's going to be called Stackhawk.yaml. And then what you'll want to do is find the Stackhawk YAML that you just downloaded from before and then go ahead and paste it in to the editor. You'll notice that it copied over our host selection and our environment. And then it generated an application ID that matches the account you created. So this UUID will be unique for each person. Oops. I messed up the formatting in Discord. That's okay. Yes. So I did not, for folks that are following along, I did not include the exact replica of that YAML because the app ID is different for every person. So just make sure that you are naming the file. You're in your Vulnode Express repo. You've created the file called Stackhawk.yaml. And then you're just going to, like Brandon did, paste in that YAML file that you just downloaded out of the Stackhawk UI. Yeah. And if for some reason you lost your app ID over in Stackhawk, you can copy that again right from here, just on this top header. Awesome. So I'm going to go ahead and commit this file. It won't quite do anything yet because we haven't told it to run the hawk scan yet, but we will get it in the repo first. Yep. So again, Stackhawk.yaml, paste in the YAML file that you just downloaded out of the platform. Brandon, I mean, you can certainly speak to this, but we're going to reference this file here as we update our ci cd pipeline. But if you're having any questions or not sure what parts you need to include in that file, for example, let us know so we can get you answers. Yep, definitely. Yeah. And so the next step we're going to do is we will add the Stackhawk GitHub action. And by default, it looks for the Stackhawk YAML at the root of your repo. So that's why this name matters. But there is a way to rename it. It's just easier if you just use the default. All right. I think we might have lost some folks just based on the number of thumbs up we're getting here. So if you have questions or something isn't working, let us know so that we can slow down. We did get a question, which is, is the application ID safe to be in a public file? Yes. So this ID is fine to be public. The way that Stackhawk links it back to your account is the combination of your app ID and your api key. And if someone's not authorized to see this application ID, they just get a generic error message. They have no idea whether this application even still exists in the Stackhawk platform. So this particular thing is okay in the public repository, but that's a great question. All right. Okay. Let's keep going. We're so close to getting this. So the last thing we're going to do is we're going to come back to this GitHub workflows folder. We're going to go into our build and test YAML. And we're going to edit this file. And we're going to add a couple of steps at the end here. So if you go back to this, our workshop on GitHub, and Rebecca is also going to post this in the Discord, these last two steps are what is new, but we haven't done yet. So basically what we're going to do is we are going to start our node application during the GitHub action run. And this ampersand at the end of the command is really important because what it's going to do is it's going to do npm run start and then push it to the background so that it doesn't hold the GitHub action up. So it's going to start our application and then move on. So that way it can use our predefined GitHub action to run a hawk scan. You'll notice that the one piece of configuration is to read the hawk api key out of the secrets. So this is where that api key comes back into play. And then, yeah, everything else we'll be able to take directly from the defaults of this hawk scan action. It will read our stack hawk YAML and we'll get a dynamic scan going in no time. Brandon, just one note on my end. I did paste in the whole YAML file. We have run into problems before where Discord doesn't like when I just include the new portions that run hawk scan in the run and start and. So you can either just take those new portions or you can just kind of entirely copy paste what I just posted in the Discord and replace what was in that file before. Discord just doesn't like the spaces which then causes problems for people that are running this which is why I included that full file. But we're back in that same build and test file that we started this workshop at. So we're adding two steps to that bottom piece of that YAML file. Yep. And a quick sanity check is that these should all be stacked up with the rest of the steps and then this one configuration to add the api key is pushed over. Right. This is the final step to get this test going. So make sure you give us a thumbs up if this is working for you, if you are able to commit, if you have questions as to what on earth we've done here or why there's a whole other YAML or anything like that, you know, drop us questions in the Discord, drop us questions in the Zoom chat, but I think Brandon let's commit it and see what happens. All right. So if we flip back over to the actions tab, it again has triggered our code QL scan and our build and test. This time around, we are interested in the build and test because we've got two new steps. Start our node application and then run a hawk scan. So this will take just a little while to get through installing the dependencies and running the unit tests. But then we will be doing our dynamic scan. All right. This should all look familiar, right? That was at least the first four steps we ran at the very beginning of this workflow or at those workshop to get our workflow set up. And then we just added in a couple new ones. So hopefully this looks familiar. But again, questions, comments, concerns, feedback, anything you're running into, let us know and we'd be happy to get you some help. Yep, definitely. So yeah, you can see it started our application. It's a really lightweight application, so it didn't take long at all. And now it is preparing hawk scan. We got a question on this, Brandon, which is, is the hawk scan action pre-set up in GitHub? It is. This is a public GitHub action that Stackhawk publishes to the marketplace. It's got sensible defaults baked into it. So an example of that is how it knew to look for our Stackhawk YAML that's baked into this default GitHub action. It's ready to use out of the gate with your github actions pipelines. I will get a link to that action in the Discord flow. Yeah, so you can see the actions started our hawk scan. It passed our api key. And since it was a secret, it's not public here, which is exactly what we want. It syncs up to the platform. It finished too quickly on me. So it fired up the scan engine. And then what it started to do is it spidered this application. So it walked through the app, looked for all the endpoints in it. As it was finding those endpoints, it checked those requests and responses for anything suspicious. And then once the passive scan was complete, it started attacking our application. So this is where some really interesting things happen. And it'll look for a ton of vulnerabilities. And then when the active scan is done, it will provide a summary of everything it found here in the GitHub action workflow. And then it also gives us a link back to Stackhawk to see more information about the scan. So I noticed a couple questions popping up in the Discord. Yes. The first one is, is this scanning private packages that are dependencies of the package that runs the pipeline? I think, so is it scanning private packages or is it public? I think is the question. It's looking at your running application. And so if you used a dependency that had a vulnerability that could be exercised from the outside world, this would be scanning the usage of it. But it's not looking at the dependency directly. It's looking at your application as it's running first and sending web traffic to it, if that makes sense. Awesome. I think we're getting a couple filled errors. I want to say the file does not exist. I'm wondering if it's, sometimes we run into this error when the name is slightly off. So if you did .yaml or one time we had someone that had a space in their file name with this error or it was saved in a different repo. So I would just make sure you're in your right repo and that that file name matches stackhawk.yaml exactly with no spaces or extra goodies. I'm trying to think when else we've seen that error, Brandon. Yeah. If you want as well, if you post a link to your repository, we can take a quick look and see if we notice anything. Awesome. Let me look at this too. So I think looking at this, you just have it misnamed. So you swapped the W and the A. So in this one, we just have the one that was just shared, your file name is, I'll actually just reply directly to you. Okay. No problem at all. We have run into this problem lots of times. So you're not the first. Then it looks like the .yaml to .yml extension worked. Perfect. Any other errors people are getting that we can help troubleshoot? Okay. Well, Brandon, so we saw those results. I think we are probably getting a couple more questions here in the chat. But we saw the results come into that GitHub action log. But it looks like you have something teed up to show us how this is reporting out in the UI as well. Yeah. So if you notice, Stackhawk also found SQL injection, just like CodeQL did, which is really interesting. So we can drill into that specific finding. And then what Stackhawk is going to do is it will show you the request that was sent along with the response that came back, which indicated to Stackhawk that this is in fact accessible to the outside world. So what's really interesting about this is now, since you ran the CodeQL scan first and then you followed it up with the Stackhawk scan, not only do you know the line of code that it was in, but you also know how to use it from the outside world or how to exercise it. So when you go to fix this vulnerability, Stackhawk also provides a curl, which lets you quickly reproduce the vulnerable request locally, which is super cool for iterating and fixing these security vulnerabilities fast, especially because some of these vulnerabilities can be really hard to reproduce locally or prove that they're there. And so we wanted to make it really easy to execute the vulnerability locally. I think a huge area we see that be helpful for folks too is validating fixes. So if you get an SQL injection here, you think you fixed it, but you don't really want to have to redeploy the ci cd to make sure that that fix worked. You can bring your app up locally. You can run that curl command. And if you get the same response data as is shown there, you didn't fix it. And otherwise you did. So also huge for findings validation. Exactly. Let's see what other questions are. Is everyone seeing these results in the Stackhawk UI? Are there any other errors we're getting in github actions that we can help with? I want to make sure everyone got three types of security testing done this morning or evening or every time a day it is for you. Very biased towards the morning here. Yeah. All right. Brandon, I'm wondering if you could answer the question we got earlier about DAS and SAS correlation and maybe show a little bit about that new integration Stackhawk has. Yeah. So we recently released our first SAS integration. And we'll get into some of the other integrations that Stackhawk has. But we have an integration with sneak code, which is another SAS integration tool. We're working on others, but essentially the goal is to give you the complete picture all at once. And so an example is that we've got this vulnerable node application hooked up to sneak code. I ran a scan of it locally after setting up the sneak code integration. And what you can see happening here is that the SQL injection finding has this little sneak code logo, which indicates that sneak code found the same vulnerability. And then that side panel had a new tab once that integration was hooked up, which is showing the results from sneak code. And it is showing us the line of code that sneak found this vulnerability on. So you have all of the same Stackhawk dynamic information combined with the information that was coming out of that SAS provider. So it really is the complete picture of the security vulnerability you're looking at. Awesome. Yes, we have a great video on that integration. But just to go back to that question about like SAS and DAS and how those two are related. So like Brandon says, in the instance that we had a SQL injection and sneak code and Stackhawk, those findings would be correlated. And in addition to the request and response evidence you see in that Stackhawk UI, you'd get the exact line of code, which just makes fixing so much easier. We've got some more questions, Brandon, in the Discord chat. I know you mentioned you were going to show off the other integration Stackhawk has, which would be super helpful. I shared the docs, but we got a question, which is, can we add Stackhawk to other CI-CD pipelines, for example, Jenkins, or does it only work with github actions? Yeah, so we've packaged the scanner as a Docker container. So it can run anywhere Docker can run. And we've got a bunch of different guides and tooling and support to help you get it into whatever CI-CD environment you're using, including Jenkins, I think I heard. So yes, we want to work wherever you are. We want to meet you at your code pipelines. All right, we got a great question, which I'm excited was asked, which is, is there a way to make the workflow fail in case we have a high-risk vulnerability? So I don't allow to merge a PR while the vulnerability is not fixed. Great question. We love this. Definitely. So if you flip back to the guide workbook, the last thing we wanted to show was how you can set a hawk scan failure threshold. And so this little snippet, this hawk failure threshold high, if we copy that. Not the workflows. From the root, what we actually want to edit is our Stackhawk YAML. And what you'll want to do is go ahead and paste this at the bottom of your Stackhawk YAML. This is a new configuration section all the way to the left. We support low, medium, and high, which means if the scanner finds a new, in this case, high finding, it'll cause your GitHub action to fail. You'll still get all of your scan data in the Stackhawk platform so you can see what's happening, but then it won't let your action continue. So an example would be if you're running this scan before your deploy step, this would prevent your deploy step from happening, so you would effectively prevent your deploy if there was a high security finding. So I'm going to go ahead and commit that so I can showcase this. Some cool things about the platform would be if you're actively working on a high finding or you determined that it was a false positive, we let you assign, mark something as false positive or mark something as risk accepted. And basically what that means is that if you've triaged a finding, since these are all of our triage actions, we won't prevent the build from breaking if all of the high findings have been triaged. So an example of that, I'm going to assign this one to me just so I can show what that does in here. So now from this view, since we haven't started our next scan yet, but you can see that it's got one high vulnerability unhandled and one that's been triaged. And then the scan that we just kicked off from editing our StackHockeyML will remember that selection, and it will still fail because we still have one high vulnerability in there that's untriaged, but it's only complaining because of the SQL injection now and not the one that I triaged. And we love this. I think ultimately if you're a developer or you're running a development team, the best time to fix any type of issue, security issue or not, is when a developer is checking in the code for a few reasons. One, they're in the right context. They know what they just wrote. But two, you know where the issue exists. Like if you're checking in 50 lines of code, it's like, okay, I've introduced this issue somewhere in these 50 lines versus traditional security testing, which can be like there's an issue somewhere in your production application. It's like, okay, well, how do I find this? I wrote this code six months ago. I don't know what I was thinking when I wrote that. So this is huge for making great increases to developer productivity and helping security issues be fixed without rework. So we love this feature, and a lot of our customers love that too. It's all about shifting it left. It's a lot cheaper to fix if you're in the zone working on the code. You find the issue right away. You don't have to dig up ancient history when the external testing team comes back six months later and says you've got SQL injection. Exactly. Exactly. Okay. We did get one question, which I want to get back to, which was not about Stackhawk, which is someone noticed that my CodeQL scan didn't find anything. Any idea why? Have you ever seen that, Brandon? I have not seen that, and I have no idea. Yeah, it might depend on the configuration. Since CodeQL is very context-specific to the repo, you might want to double-check that it was configured correctly once I can figure out where I'm going in here. There we go. There's some context-specific things with CodeQL, one of them being the language. Then it's got a couple of things that it needs before it can actually run the analysis. There's an initialization step that GitHub provides a pre-canned action for. Then if you're scanning something that is pre-compiled or needs to be compiled, like a Java app or a .NET app, this auto-build step helps CodeQL understand what it's looking at. It could be something with the configuration there. Yeah. I know Brandon shared his CodeQL config file. If you just paste it in that file, I'm not sure GitHub will recognize that you're asking it for CodeQL if you haven't enabled CodeQL alerts. If you just paste it in that file, but in your settings you haven't turned on CodeQL, I would imagine that might be the cause of this problem. Maybe, Brandon, you could just show us once more how to turn on those alerts in case someone missed that step. Yeah. Then one other thing I was thinking about too, this permissions block is giving the GitHub action, GitHub permissions to make edits to your repo. This gives it the ability to read your source code, which it will need to scan. Then this gives it write permissions so it can update that CodeQL tab. Those are probably important. Then if you haven't set up CodeQL yet, from the settings tab over here in code security and analysis, you should see a code scanning option that will tell you or let you set it up. Then this shouldn't have any impact for what we're doing here. Basically, this is configuring pull requests. Since we have SQL injection in this application, if I were to raise a pull request against main, I believe this would fail since SQL injection is a high vulnerability. It'd be something very similar to what we're doing with the Stack Hockey Amul where we're breaking on high vulnerabilities, but this should only impact pull requests. The setup button should be here if you haven't enabled it yet. Awesome. All right. Well, I know, I think, Brandon, are we reaching the end of our content for the workshop? I think so. We're getting really close. A couple of things to leave you with. The fun does not stop here by any means. So if you're curious to learn more, go ahead and check out our docs. We've got this getting started page right at the top, which is kind of the, this is our world class welcome and gives you a really good idea of how you can take this scanning to the next level. So we support different kinds of APIs like RESTful, graphql. We can interpret open api specifications. We can even scan SOAP APIs if you still use those. You've already checked number three off the list because we are done automating Stack Hawk into your ci cd. And then if you have an authenticated app, the next best thing you can do is take a look at this authenticated scanning so that you can really see what's going on with your own api. Other than that, thanks everyone for following along and we hope you enjoyed this workshop. I'm Brandon. Rebecca has been awesome helping me out and we really appreciate your guys' time. Guys, thank you, Brandon. You did all the hard work. I just do the chat. So thank you for watching us through three different types of security testing. Hopefully, you know, you can find at least one of those to be useful in whatever projects you are working on, whether they're personal projects or projects you're working on for work. Like Brandon said, if you have any questions, feel free to ping either of us. And I know our solutions architects and engineering team will be happy to schedule anyone that's interested, like a custom hands-on demo if you have a specific app that maybe requires api support or difficult authentication scenarios. Like we believe security testing is just security is just another aspect of code quality. So any way we can help you make that part of your development process, we would love to support you on. So thank you, Brandon. Thank you, everybody that joined. This was tons of fun. We really appreciate all the engagement in the Discord and the Zoom and feel free to ping us there as well throughout the rest of react Summit if you have any questions. Yeah. Thanks, everyone. All right. Thanks, Brandon. Have a good one. Thanks, everybody. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you.
01 Jul, 2022