What you'll learn
- Defining Security Processes With SECURITY.md
- Basic Branch Protection
- Creating Simple Status Checks
- Protecting Branches With Status Checks And Reviews
- Challenge & Solution: Splitting Rulesets
Free 46-minute video lesson with a full transcript and knowledge checks. No account needed to watch.
Defining Security Processes With SECURITY.md
When most people think about software security, they think about elaborate systems and scans that spot vulnerabilities before they can be published. While these types of systems do play an important part in modern software development, the truth is far more down-to-earth: secure software starts by creating clear guidelines and set of simple processes followed first and foremost by humans. We'll be seeing plenty of examples of this in this course, but we'll start things off in this video by taking a look at the basics of the SECURITY.md file, as well as how it can be used to document your repo's security practices.
In case you're not keen on typing the full SECURITY.md file out yourself, here's the one that I created in this video:
# Security Policy
### Supported Versions
| Version | Supported |
| ------- | --------- |
| 1.x | Yes |
| < 1.0 | No |
### Reporting a Vulnerability
Do not report security vulnerabilities through public GitHub issues.
Instead, use GitHub's private vulnerability reporting feature.
Please include:
- A description of the vulnerability
- Steps to reproduce it
- Potential impact
- Suggested remediation, if known
### Response Targets
We aim to:
- Acknowledge reports within 2 business days
- Triage vulnerabilities within 5 business days
- Prioritize critical vulnerabilities immediatelyKnowledge Check
SECURITY.md is just a convention used by developers, and has no real meaning to Github.
Basic Branch Protection
Previously, we saw how creating a SECURITY.md file allowed us to document our repo's processes for reporting security vulnerabilities. However, this is just one of many pieces involved in a typical repo's security strategy. Wouldn't it be nice if, in addition to being able to secretly report and handle vulnerabilities, we could define processes that helped prevent those vulnerabilities from entering our repo in the first place? The first line of defense here is branch protection, which gives us greater control over who's allowed to push what code to which branches.
Knowledge Check
In Github, a ________ allows us to define rules related to our repo's branches.
Creating Simple Status Checks
Now that we've seen the basic mechanism for adding protection to specific branches in Github, it's time for us to learn about a very powerful technique that this enables. As we'll see in this video, Github Actions - Github's main automation platform - allows us to gate our PRs on the results of virtually any automation. This has profound security implications, but we'll talk about that in more detail later. For now, let's see how to get this set up.
Here's the code you'll need for this video:
# run-tests.yml
name: Run Tests
on:
pull_request:
branches:
- main
jobs:
test:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Set up Node.js
uses: actions/setup-node@v7
with:
node-version: 24
cache: npm
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test// test/app.test.js
const test = require("node:test");
const assert = require("node:assert");
const request = require("supertest");
const app = require("../src/app");
test("GET /api/issues returns an array of issues", async () => {
const response = await request(app)
.get("/api/issues")
.expect(200);
assert.ok(Array.isArray(response.body));
});
test("POST /api/issues creates a new issue", async () => {
const response = await request(app)
.post("/api/issues")
.send({
title: "Test issue",
description: "Created by the unit test"
})
.expect(200);
assert.strictEqual(response.body.title, "Test issue");
assert.strictEqual(
response.body.description,
"Created by the unit test"
);
assert.ok(response.body.id);
});
test("GET /api/issues/search finds an issue", async () => {
const response = await request(app)
.get("/api/issues/search")
.query({
q: "Test"
})
.expect(200);
assert.ok(Array.isArray(response.body));
assert.ok(
response.body.some(issue => issue.title === "Test issue")
);
});
test("GET /api/config reports that the API is configured", async () => {
const response = await request(app)
.get("/api/config")
.expect(200);
assert.strictEqual(response.body.apiConfigured, true);
});
test("GET /hello returns an HTML greeting", async () => {
const response = await request(app)
.get("/hello")
.query({
name: "GH500"
})
.expect(200);
assert.match(response.text, /Bonjour GH500/);
});And then replace the last three lines of src/app.js with this:
if (require.main === module) {
app.listen(PORT, () => {
console.log(`mini-issue-tracker demo app running on http://localhost:${PORT} !!!!`);
});
}
module.exports = app;Knowledge Check
The _________ option on a branch ruleset allows us to temporarily deactivate our rulesets instead of modifying or deleting them.
Protecting Branches With Status Checks And Reviews
Next, let's push our changes and modify our ruleset so that it gates PRs on the results of our unit tests.
Knowledge Check
The _________ option on a branch ruleset allows us to gate our PRs on the results of a workflow job.
Challenge & Solution: Splitting Rulesets
Now it's time for a challenge! In this challenge, you'll need to split a ruleset to prevent the "all-or-nothing" consequences of adding someone to the bypass list. Watch the video for more information.
And now that you've attempted the challenge, I'll show you how to solve it.
Knowledge Check
It's highly recommended that you put all the rules for branch protection into a single ruleset.
View Transcript
Defining Security Processes With SECURITY.md
0:00Hi, Sean here and welcome to this skill where we're going to be taking a look at the basics of designing a secure software development lifecycle on GitHub. All right, so first things first, because this is the first video in the course, I should probably introduce the project that we're going to be using. We're going to be using this mini issue tracker project and you should be able to clone this on GitHub if you want to. And the basic idea is that this is just a simple little demo application that we'll be using in order to or I suppose you could say as a starting point for a lot of the security related conversations that we're going to have to have. Right. Fact is that it's just a lot more interesting to demonstrate a lot of these security related concepts on an actual application, even if it is a simple one than just talking about them and pointing at stuff with my mouse. And so anyway, this is what we're going to be using.
0:51So feel free to clone this as a starting point. And also notice that at the moment I'm currently at the very first commit. Well, the second commit, the first one being basically just a blank repo. And so if you really want it to be at the at the point that I'm at right now, you're going to have to rewind to that commit. So I'll leave that up to you. You should already know how to do that if you're taking this course. And let's get started here by talking about how to define the security process for a GitHub repo by using a security dot MD file. Right. This, I think, is a good starting point because it's fairly simple. And and also it's just an effective way to start thinking about security as a process or as part of your processes versus as some extra thing that you just try and add on afterward. Right. So here's the basic idea. Let's imagine that this is a public repo that we expect to be used by other teams. Right. Maybe we've created an open source project or something like that here. Maybe someone discovers that this application has some sort of security vulnerability. And trust me, it really does. There's lots of intentional security vulnerabilities that have introduced into this application. So just keep that in mind
2:10as you use it. Well, if someone discovers a security vulnerability, you definitely don't want them just opening a public GitHub issue containing all the details of how to exploit these security vulnerabilities. Right. And so this is the first manifestation of the general need that you'll have with any GitHub repo to have a defined system. Right. Defined defined process for handling this sort of security issue. So here's what we're going to do. We're going to start off here by creating a security dot MD file. This is one of the many purpose driven MD files that you'll find in GitHub. Right. Like read me dot MD. That's what shows up on the homepage of a given repo, as we've already seen. I'm sure you're aware of that by now.
3:03What we're going to do is we're going to create another one called security all in caps dot MD. All right. Now that we've created this file, let's talk a little bit about what this file actually means. So as with other files that you're probably familiar with by now, like read me dot MD or contributing dot MD or code of contact MD. These aren't just files with fancy, you know, all caps names. These actually have a meaning in the GitHub ecosystem beyond their conventions that developers are familiar with. So in our case here, as we'll see security dot MD will actually cause GitHub to publish the contents of this file under our projects security policy area. I'll show you where that is shortly, but let's just get started creating this thing. What I'm going to do is just start off. And this is obviously in Markdown, just like the read me file. And most of the other files are. So we're just going to create a simple file here called security policy.
4:05And let's talk about some of the things that are typically involved here. One of the biggest things that you'll typically see with security dot MD is the supported versions. This is typically something that you'll see because most projects at some point or other will stop supporting older versions. And so this is just a good way to let everybody know about that. So we're going to say supported versions. And then underneath here, what we're going to do is we're just going to create a nice little Markdown table where we'll say version and then we'll mark whether it's supported or not.
4:39And here's just the where we tell GitHub that that's the header line like so. All right. And then in this first column, we'll say that we'll support all one point X versions, right? Anything that starts with one point something. And then here we'll say yes. And for the last one, we're going to say less than one point zero. There we go. I don't need that extra thing there. And then we're going to say no. All right. So obviously this could get much more complicated here. We could add many more rows, but I'm going to stop there just to show you what this typically looks like. All right. And the next thing that we're going to do here is we're going to detail how we want contributors to report a vulnerability on this repo. As I said earlier, we typically won't want them to just create a public issue. And this is exactly where we can tell them that.
5:30And just as a side note, that's really the beauty of these kinds of files is it gives us a specific place where our users will automatically know where to look for certain questions like this. How do I report a security vulnerability? Well, it's always in security.md. And so what we're going to do here is we're going to say reporting a vulnerability. And then underneath here, we'll just type something out. I'm just going to fast forward this part so that you don't have to watch me type at all. All right. This is just kind of a generic message. Feel free to use it yourself.
6:03And one more thing that it's typically a good idea to include in these instructions are things that you want your contributors to include when they report the vulnerability. You don't want someone just saying like, hey, I found a vulnerability THX, right? You want them to actually give you more details. And so what you'll typically see in these cases is we'll say something like please include, and then we'll have a description of the vulnerability. Maybe we also want steps to reproduce it. That can be very important for troubleshooting, obviously. Maybe we'll also have potential impact and suggested remediation if known, right? Maybe the person has some idea of how to fix this thing, which would be great. And so I'm going to leave that there. And the last thing that we're going to include in the security.md file is response targets. So this really is where we tell users what to expect when they report a vulnerability, right? Should they expect that we'll respond in five minutes? Should they be happy if they get a response within a week? That's where we set up our expectations. And so what I'm going to do here is just say something like we aim to, and then I'll just add something like acknowledge reports within
7:21two business days. And then we'll say triage vulnerabilities within five business days. Again, feel free to change these depending on what makes sense to you. If you're actually setting this up for a real world use case, we're going to say prioritize critical vulnerabilities immediately. And that's that. So this is a pretty solid starting point for a security.md file.
7:51So what we're going to do is we're going to commit this, and then I'll show you where GitHub makes this available to people who are using our repo. So I'm going to just open up the source control tab here. We're going to stage the changes that we made to security.md. And we'll say something like added security.md file. That's pretty much all we did here. And so let's commit this, push it up to GitHub and say, okay. And if we go back now to our repo, the place where the security.md file will show up and, you know, here, let's actually hit refresh.
8:22First of all, it will show up there. So if a user actually wants to open this thing like this, they can. It's a totally fine way of exploring that file if they already know what they're looking for, but it will also show up under security and quality. And if you go to the security policy area over here on the left-hand side, that's where you'll see that full document that we created, right? So there's the table that we set up. Here's our instructions for reporting a vulnerability. Here's our response targets. You get the idea. All right. And while we're at it, now that we've published this security policy document saying that we want people to report it through GitHub's private vulnerability reporting feature, in order for this to work, what you as the repository owner will typically have to do, at least this is how it works for public repos, is enable that feature by going to settings under your repo and then going to security and quality underneath here, and then clicking on the advanced security link.
9:22And then right up here at the top, we'll see this private vulnerability reporting thing. We're going to enable that. And now that we've done that, if we go back to the security and quality tab of this repo, what we'll see here, and actually we'll need to look at this from the point of view of another account in order to actually see what this would look like. So I'm just going to switch accounts here real quick. There we go. So I'm now looking at this same page from another account that doesn't own this repo. And sure enough, up here in the top right-hand corner, we see that there's this report of vulnerability button. And if we click that, that will bring up the form that we can put together in order to report that vulnerability.
9:59So it includes the title, summary, details, proof of concept, impact, et cetera, et cetera, et cetera. Any, any and all details that you might want someone to include. So I'm going to switch back to my owner account here. Let's just go back there and Oh, look, it lets us actually access this page. It just doesn't have the button that links to it. Um, one more thing that I wanted to point out about that is you may have noticed, let's just go back to the advanced security section here under settings that there's this little settings button next to private vulnerability reporting. After you enable it, if we click on that, this allows us to change a few things about that process. Really the most important one here is this daily advisory limit. If you accidentally do something like publish an API key in your repo, you can bet that you're going to receive hundreds or thousands of private vulnerability reports if you're working on a popular enough repo.
10:57And so by limiting that, basically this just helps make sure that you don't get overwhelmed with, uh, vulnerability reports on any given day. All right. So anyway, that is the basics of setting up and publishing a security.md file as well as where that appears in the repo and how the reporting process actually works when people want to privately report a security vulnerability.
Basic Branch Protection
0:00All right. Well, previously we saw how to create this security.md file, which as we discussed, gave us a place to document the processes for reporting security vulnerabilities that people have discovered in our code. Now, this is a very important part of your overall security posture in GitHub, but there are many other things that you're going to need to do as well. So for example, while the security.md file tells people how to report vulnerabilities that they've found, it's just as important, if not more important, that you have processes in place for preventing security vulnerabilities from entering your repo in the first place. And one of those strategies, probably the most common strategy for doing this on GitHub, is by adding branch protection to important branches like your repo's main branch.
0:55And so that's what we're going to talk about here in this video. All right. So the first thing to understand about this is that you'll almost never want developers pushing directly to important branches like the main branch. Are there teams where this is a normal thing? Yes. But as far as I know, that is the exception rather than the rule. And so typically it's recommended that you protect the important branches in your repo and allow changes to be made to them only through pull requests. Now, I'm assuming at this point that you already know what a pull request is and you've walked through the process of opening one and then merging it at least once. But in order to make this mandatory, there are a few settings that need to be put in place first. So in other words, if we want to actively prohibit people from pushing to the main branch by doing what we just did with this security.md file and just saying commit and push while they're still on main, really the first thing that we have to do is create something called a rule set on our repo. All right. So here's how we're going to do this. We're going to go to settings.
2:08And then over here on the left-hand side, under code planning and automation, we're going to open up this rule sets dropdown and go to rule sets. And what we're going to do here is we're going to click this little new rule set dropdown and say new branch rule set. Now, the first thing that I'll say here is that rule sets go much deeper than what we're about to see here with, you know, protecting our main branch. So, you know, if you're planning on becoming a GitHub admin, you'll want to know about these things at a lot more detail, but setting up a rule set just to protect the main branch and require pull requests is actually a pretty straightforward process. So here's what we're going to do for the rule set name. We're going to say something like protect main branch. And then for enforcement status, we're going to set this to active. Now, why would you ever want to create a rule set and set the enforcement status to disabled? Well, basically what that allows you to do is turn off a rule set temporarily without having to delete it. This is a very common thing that you'll see with, um, you know, policies like this one, but, uh, anyway, we're going to set that to active and we're going to just skip down here to the target branches section where we're going to say, add target.
3:24And we're going to click include default branch. Okay. So basically what this means is that any rules that we set up here in this rule set will apply to the main branch. And basically, once we've selected that, the rest of this is us choosing the specific rules that we want to apply to that branch. So in our case here, the one that we're looking for specifically is require a pull request before merging. So the basic idea here is that this will make it so that developers can no longer push directly to that branch. And you can even read this underneath, uh, in this description says require all commits to be made to a non-target branch and submitted via a pull request before they can be merged. Basically just meaning no more pushing to main. Okay. So here's what this is going to look like. Um, there's a lot of other options here, of course, but for the time being, the only other change that we're going to make is we're going to set required approvals here to one. Now you'll see what this does here in just a minute, but typically adding approvals via this rule set, like what we're about to do is an incredibly important part of, you know, any kind of GitHub security strategy. And really the truth is that without taking these basic steps
4:46from the very beginning, even if you have the most advanced AI powered, you know, pick your buzzword security scans enabled on your repository, they're going to be very limited in their effectiveness. Okay. So anyway, we're going to set required approvals to one. And for now we're just going to leave it at that and click create. All right. So we should see that it says rule set created. And now here's what this is going to look like. If we go back to code spaces and I've just been using code spaces to make changes, but you can obviously use, um, a local development environment.
5:19If you prefer it that way, what I'm going to try and do is make a change on this branch. So if I go in here and, um, you know, let's, let's say that I make a change to app.js, for example. Well, here's what we're going to do. And by the way, you'll start to see these intentionally vulnerable things here. Just noting that these are security vulnerabilities that have been intentionally introduced into this code. For examples that we'll see later, what we're going to do is, um, let's just scroll all the way down to the bottom where we start up our server. And then let's add some exclamation points after this, right? So just kind of a silly example there. But if we try and commit this, now what we'll see, we'll say something like made a message or we'll say made server message, more exciting. All right, there we go. We're going to say commit.
6:10And if we now try to sync these changes with GitHub, right? If we try to push those changes up to the main branch, we'll see that we get this error saying can't push refs to remote. And if we say show command output, sure enough, we get this message now that says changes must be made through a poll request. All right. So here's what we're going to have to do now that we've committed locally and can't push that commit. What we're going to do is we're going to use the get switch command. So we'll say get switch dash C, and then we get to name our new feature branch. So we'll say something like exciting server message, something like that. And now that will take the most recent commit, switch it over to that branch. And if we push this branch now, we'll say get push dash U origin, and then we'll say exciting server message. There we go. What we should see, and you could do this also through the source control tab. I was just doing it through there because it was a little bit more straightforward. What we'll see is that that will now push that branch up to GitHub and we can take the changes that that branch contains and open a PR with them.
7:18So sure enough, we see exciting server message had recent pushes 15 seconds ago. If we click compare and pull request here, what we'll see is sure enough, we can create a pull request that has those exclamation marks intact. And if we create this now, basically, and again, I'm sure you're already aware of the main idea of pull requests. But what we'll see is that we can't merge this until at least one other person approves this pull request. Now, from a security standpoint, this is already a big step forward because no longer can someone just insert whatever code they want into the repository and immediately have it affect anyone else who's using the repository. In fact, if you're working for an organization that does its own credit card processing via its website, things like this requiring a review are typically a must because the credit card company wants to prevent a rogue developer from inserting a script into your code base that scrapes credit card numbers. And so anyway, that's one layer of protection that we can add to our PRs. Another is if we go back to the rule set that we created earlier, let's just open that one back up. We should see protect main branch in there now. If we scroll down, another
8:36thing that we're allowed to configure is this require status checks to pass option. So if we enable this, basically what this allows us to do is use GitHub automations, right? Typically, this is under the umbrella of GitHub actions where we can create automations known as workflows that will do things like run our tests for us. Basically, what we can do is tie the mergeability of a PR, right? Whether we're going to allow someone to merge a PR or not to any status check that we can create a workflow for, right? So if we want to run our tests and require that our tests all pass before merging in a PR, this is where we would do that. All right, so anyway, that's something that we're going to take a look at in the next video.
Creating Simple Status Checks
0:00All right, well now that we've discussed the basics of protecting our branches using rule sets, the next thing that I wanna talk about in a little bit more detail is this idea of requiring status checks before we're allowed to merge a PR, right? So again, this is a tremendously flexible concept. And once you've really gotten familiar with this idea of running status checks, there's really not a whole lot that you can't do when it comes to enforcing rules around merging PRs, right?
0:31So if you don't want a PR to be able to be merged unless you have a minimum of let's say 95% test coverage, you can absolutely do that. If you don't want a PR to be able to be merged, if it contains changes to specific files, you can do that as well. Really, anything you can express in logic, and we'll see in just a minute here, the syntax that's used to create GitHub workflows if you haven't already worked with those, as long as you can express it in logic, you can make it sort of like a gate for merging PRs.
1:02And so here's what we're gonna do. We're gonna go back to our Mini Issue Tracker code space here and by the way, in case I haven't talked about the name, the reason why it's called Mini Issue Tracker is because it's a mini issue tracking app, right? So feel free to run the app if you want to based on what's in the readme file. But here's what we're gonna do. We're gonna open up this GitHub folder and inside there, notice that I have this workflows folder with, right now there's just this git keep file, which is just an empty file to make sure that GitHub captures that folder structure.
1:36What we're gonna do is we're gonna delete that git keep file and we're gonna replace it with our first workflow. Now again, whether you've worked with workflows or not, doesn't really matter. We're going to see how to use them to perform status checks that we can use to gate our PRs. And we're gonna call this file something like run tests dot YAML, right? Dot Y-M-L is the preferred extension for these kinds of files. And once you've created that file, what I'm gonna recommend is that you copy and paste the code from up above this video.
2:09It's gonna be the one that starts with name run tests at the top. So I'm gonna just copy and paste that now. And there we go. So what you see here is the typical syntax for defining workflows. And workflows have a pretty predictable structure. It starts at the top, obviously, with the name of the workflow. This is how you'll find it and refer to it from the GitHub interface. You'll see what this looks like shortly. The next thing here is the trigger, right? So this is what will actually cause the logic that this workflow contains to run.
2:43And in this case, we have this workflow set up so that it will run in response to pull request events. But only, as this extra filter here says down at the bottom, for pull requests that are targeting the main branch, right? So this is exactly what we want in this case. And the cool thing about this is that GitHub will automatically pick up on tests that run on pull requests. And it will sort of incorporate that into the interface when a PR is opened, all right?
3:15So we'll see that in more detail shortly. But down below this, we have the jobs. This is the section of the workflow that contains the actual logic that will be executed when this workflow is run. So all that we have going on here is just look at this steps section for now. You don't have to worry about the rest of the details. What we're doing is we're checking out the repositories, right? So this is sort of like saying git clone from a local machine, right? If you wanted to clone a git repo, just kind of gives this workflow access to the files that are in that pull request.
3:52After that, we're calling setup Node.js. Basically, this just provides our workflow with a Node.js environment. After that, it's installing the dependencies by running the npm ci command. And then it's running the tests by running the npm test command. So it's a pretty straightforward workflow as far as workflows are concerned. The next thing that we need to do is in order for this workflow to actually do anything, we need to make sure that there are actually tests to run. And so you may have noticed that there's more code up above this video than just this run tests workflow.
4:26So the next thing that we're gonna copy and paste is we're gonna start off by creating a new folder called test. And then inside this folder, we're gonna create a new file called app.test.js. This is just one of many sort of structural paradigms you can follow when organizing your tests. You can have them all in their own folder. You can have them sort of mixed in with the production code. Kind of up to you, but this is just how we're gonna do it for the time being. And here's where we're going to copy and paste the code that I mentioned.
4:57All right, so as you can see, this is just a simple Node test suite that uses the super test library, which is a library that's very commonly used to do things like test servers. And so the last thing that we're gonna need to do is go into the app.js file under the source directory and make one small change to the very end. Basically, you're just gonna copy and paste the code that I've provided and replace these last three lines. There we go. And basically, all that this does is it makes it so that the server won't start when it's run in test mode, right?
5:33We don't want a server running and then sort of hanging up the tests when we run unit tests on it, all right? Cool, so now that we've done that, that should be all we need to do in order for our tests to actually run, except, of course, we'll need to update the dependencies. Now that we're using that super test library, all that we need to do is open up a terminal here and we're gonna run npm install double dash save dash dev. This will install it as a development dependency. And then we're gonna install the super test library.
6:05That's gonna just install that. We'll add it to the package.json and package lock.json files, which is how Node.js projects keep track of their dependencies. And that should be all we need to do. So let's give this thing a try. But the problem that we're gonna run into here is that in order for this workflow to run, it needs to be on the main branch on GitHub. And so because we just set up a rule set that prevents that, that's gonna, you know, it's going to block us if we try to commit this and push it to the main branch.
6:36Now we could just push this to this exciting server message branch and then merge the PR, but I kind of wanted to use that PR for demonstration purposes. And so what I'm actually gonna do is go back to this rule set and I'm gonna just uncheck require status checks to pass for the moment. And you may have noticed this bypass list up here at the top. Basically, this allows us to add specific, well, what they call actors. In this case, this can be just our user account that this particular rule won't apply to.
7:09All right, so if we wanted to, we could just add ourselves. If we go to users, we'll say add bypass and then we'll just search for our own username here, right? If we were to select that, that would make it so that this particular rule set would no longer apply. But then I also wouldn't be able to demonstrate it. So what I'm actually going to do just for the moment is I'm gonna change this to disabled. We'll scroll down to the bottom and click save changes. I'm gonna just skip over this part here. Sometimes it makes you verify via email before doing something sensitive like this.
7:41All right, and there we go. So let's go back to our code space now and we're gonna just switch back to the main branch here. And actually, before we do that, because we accidentally committed to the main branch and then switched over, we're probably gonna wanna make sure that everything's okay there. All right, so let's just commit this here and then push it up to GitHub. So we're gonna say something like added tests and test workflow. Let me try spelling that correctly there. You're gonna see me misspell this word a lot in this course. But anyway, we're gonna say commit.
8:12We're going to say commit anyway. Our code space hasn't yet gotten the memo that pushing to main is allowed again. That can happen sometimes. And we're gonna just say okay. And if all goes well here, what we should see is that that will now be on the main branch. And one more thing I have to do, I did this by accident, is I accidentally added this without solving the merge conflicts. So let's just remove the old one here real quick. We don't need the updated upstream. That's just because we created that branch at a weird time. And so that's what our code should look like.
8:44So let's just stage that and commit that real quick. So we'll say resolved merge conflicts. We're gonna commit that. And we'll say commit anyway. And we're gonna sync our changes and say okay. And one last thing that I actually forgot the first time around that I'll show you so you don't have to go through the rather lengthy process of setting things up and then just watching the test fail. The last thing that we need to add here is in this package.json file, we need to actually add the test script that our workflow was referring to, right?
9:17We're saying npm test here. And npm isn't gonna actually know what that means unless we tell it. And so here's what we're gonna do. We need to just add the line test under scripts here in the package.json file. And then we're gonna say node double dash test there next to it. All right, so that should be all we need to do there. Let's just commit that final change. All right, so we'll just say added test script. All right, we're gonna commit that. And we're gonna push that up to main as well.
9:47We'll say okay. And now that we've done that, the next thing that we're gonna do is we're gonna see how we can link the results of running this runtests.yaml file, right? Basically running our tests that we just set up to whether or not someone is able to merge a PR. So that's the next thing that we're gonna be taking a look at here.
Protecting Branches With Status Checks And Reviews
0:00All right. Well, at this point, we've set up a workflow. And so the last thing that we need to do here is link this to whether or not we're able to merge a pull request, right? Right now, if we go back to our pull request here, let's just open up this one that we added there. What we'll see is that it's going to run this check, right? We see that it says one successful check. However, at the moment, this check isn't actually going to stop us from merging the pull request, even if it failed, right? So if we were to go in here and modify one of the tests or modify the production code in some way that caused the tests to fail.
0:35Maybe I'll do that here in just a minute. It wouldn't, you know, it would tell us one check failed, but that wouldn't have any impact on whether we're able to merge the pull request or not. All right. So in order to make this happen, and by the way, notice that we are able to merge this thing because we've actually disabled that rule set here for the time being. What we're going to do is we're going to go back to settings and then we're going to go to rule sets, rule sets, and we're going to open up our protect main branch rule set.
1:06And what we're going to do is we're going to set this back to active and we're also going to scroll down here to require status checks to pass and we're going to click that check box. And basically what this does is this allows us to select the specific jobs that we want it to depend on in order to allow the PR to be merged, right? So going back to this run tests dot yaml thing that we set up, remember that this job section is where we actually define what's going to happen when we run this workflow, right?
1:40And we gave this the name of unit tests. And the cool part about this is we can actually use this name to identify it back here in the rule set. So if we click on this little add checks drop down and search for unit tests, all right, there we go. It might take a second. We're going to select this one here. And if you click off of that, it should say unit tests. And then over here, it should say GitHub actions, basically indicating that this is a specific workflow that's part of GitHub actions that we're waiting for or that we're relying on the results of to allow a merge.
2:14And now that we've done that, let's go back and click save changes. And now that we've activated this thing, let's go back to pull requests. And in order to demonstrate this at this point, it's probably going to be easier for us if we just open up a new branch and a new PR. So here's what we're going to do. We're going to go back to the main branch here in code spaces. We're going to check out a new branch. So we'll say create new branch. We'll just call this one something like purposely break tests.
2:44All right, we're going to say create new branch. And now we're going to make a change to this. Hello endpoint. Basically, we have a test that's pointed at this part right here. And you can actually see that if you go to app.test.js, you see that it says get slash. Hello returns an HTML greeting, right? So it's looking specifically for this text here. Hello gh 500. So why don't we just change this because our purpose is to break it to Bonjour. All right. So now that we have that let's save this and what we're going to do is first of all, let's verify that this actually does break the test.
3:18So we're going to do that by running npm test in here and sure enough. We see that that test fails because it's looking for hello gh 500 and it's no longer finding that right because of our change. So now that we've done that let's commit this and open a PR and this will allow us to see that failing tests will now block us from merging a PR just as effectively as a lack of reviews. So we're going to stage this change. We're going to say modified greeting.
3:51All right, we're going to commit this. We're going to publish that branch and we'll go back to github once that's done and open up a PR. So we're going to say well here we should be able to hit refresh there. And there we go. We're going to say compare and pull request and just make sure that that is the correct branch there purposely break tests is what it should be called. I'm just going to skip over everything here. You can feel free to write a description if you want and we're going to say create pull request and now what we'll see is sure enough.
4:21It's blocking us from merging this anyway, because it still needs a review, but it's going to automatically run this unit tests job and wait for its result before deciding whether that particular gate should block us from merging. All right, so we're just going to I'll fast forward until this thing finishes here. And there we go. So we see that it failed. If you want more details about this, you can always click on it and it'll take you directly to the console logs from the job that failed. We see that they're pretty much what we just saw in code spaces. And so I guess the last thing that I wanted to demonstrate there is if we go back to the PR, even if we get a passing review on this PR this thing here will still prevent us from merging.
5:07And so just to demonstrate this let's actually add another user to this repo. You may or may not have another user account just laying around feel free to create one. If you want to follow along here, I'm going to go to collaborators here and I'm going to just select another person right another one of the accounts that I have for demonstration purposes here. So I'm going to say add people. I'm going to search for Sean WCBT nuggets, which is just another account that I've created for demonstration purposes here. I'm going to say add and then I'll actually have to go back to my email and accept that invitation in order for this to work.
5:41All right. So here's what that looks like here. I'm going to just click accept invitation from that account. You will have to log in on that account. And now what I'm going to do is go to pull requests under mini issue tracker. I'm going to open up the one that we just created here, which is modified greeting. And even if I approve this thing, which we can do by going to reviewers, I'm going to set myself as the reviewer or at least this other account is the reviewer. All right, and then up here. I'm going to click add your review, right? Even if we say something like looks good to me here and then we approve it and say submit review.
6:13Normally if that was the only gate, then this would allow us to merge this PR. But because we now have this other check that we've specifically said in a rule set needs to pass in order for us to merge a PR into Maine. Well, we really have no choice but to go in and fix this thing. So let's just quickly change our account back. I'm just going to go back to Sean Wassell here. All right, the owner account for this repo and let's go back to code spaces here. And what we should be able to do. Let's say that we actually do want to change this into French.
6:45Well, what we would do here is we would go back to app.test.js and we would just change the test or update the test in order for that to work. So let's just run our tests again locally here to make sure that that change did in fact make the tests pass sure enough. We see that we have five passing tests now. So let's just commit this and push it up to that branch and that should cause the tests to pass on the PR. So we're going to say updated tests be careful of commits with this commit message to by the way, unfortunately, it can often mean that someone just commented out a test.
7:20Anyway, we're going to sync those changes and say, okay, and now that we've done that let's go back and take a look at that PR once again. So we're going to go back to pull requests. Oh, actually I had it open there, but I'll just go back to it here so that I don't have too many tabs. We're going to open up modified greeting again. And now that it's passed we can merge our PR. So let's do that. I'm going to click merge pull request confirm merge. And now that we've done that we can safely delete that branch and that's the basics of using arbitrary workflow logic to protect a branch.
7:53So we've spent an awful lot of time on this demonstration. You might be wondering, you know, we're primarily concerned about security here. Why did we take so long just looking at running tests? Well running tests is just one of many possibilities out there for what we can use to block a PR from being merged. And as we'll see later on in this course, there are many different security related tools, right? Like security scans that we can use in our workflows in addition to running our tests.
8:24So just like how we had it run NPM test, we could have it run NPM security scan. If we have a security scan script and we could intentionally not allow PRS to be merged unless they pass that scan. So this is a very important concept here for making sure that your repos remain secure.
Challenge & Solution: Splitting Rulesets
0:00All right. Well, now that we've seen the basics of using rule sets to protect branches and these specific types of protection that we can add, it's time for you to do a challenge. And in this challenge, what you're going to be doing is splitting this rule set into multiple rule sets. Now, why would we want to do this? Well, as we noticed before, right, when we were going through the, uh, the example where we had to push up the run tests dot yaml file and other changes that we'd made to the main branch, it would have been really nice if we could have added our user account to this bypass list here, right? Essentially this bypass list allows us to say who a particular rule set does not apply to, right? So if we wanted to add ourselves here, right, let's just search for my user account here. We could add that. And basically what that means is that this rule set no longer applies to this actor, right? Actor being the general term for users, apps, teams, roles, et cetera in GitHub. All right. But the problem with this is that because we have so much concentrated in this rule set, and there's certainly other things that we may want to, uh, add to this, right? Like requiring signed commits, requiring deployments to succeed,
1:15requiring linear, linear history, et cetera. What you can end up with is one massive rule set where none of it applies to whoever we've added to this bypass list. And that's a very common sort of flaw in organizations security, right? Is if maybe we don't want to require this person to get reviews on their PRS before they merge, but we still want, say their tests to have to pass and their other status checks to have to pass before they're able to merge. Well, with this particular rule set, it's all or nothing, right? Either we turn it off or we turn it on.
1:52So that's going to be your challenge is to split this rule set into two rule sets, one of which requires reviews and one of which requires status checks. So anyway, that is your challenge. Feel free to give this maybe five to 10 minutes to complete. And once you've given it a try, you can move on to the next video where I'll walk you through the solution. And here I'm going to remove this person from the bypass list while I'm thinking about it.
Challenge & Solution: Splitting Rulesets
0:00All right, well, hopefully you gave this challenge a try, so let's take a look at the solution. So the first thing that I did here is I changed the name of this particular rule set to something like require a PR reviews, right? And then I scrolled down and removed this require status checks to pass thing from this rule set, right? We are going to add that of course, onto the other rule set that we're going to create. But in this case, we don't want that one here. And so now that we've done that, what we're going to do is scroll down and click save changes.
0:32And then we're going to create a new rule set here where we're actually going to put those status checks. So let's say new branch rule set. We're going to set the enforcement status here to active, and we'll call this one something like require status checks. And then I'm going to scroll down here. We'll add the default branch, right? The main branch as the target branch. And then I'm going to scroll down to require status checks to pass right here. We're going to select that and then we need to select the actual unit tests check that we had earlier, right?
1:05That's going to be that job that we set up in our workflow. And now that we've added that, that should be all we need to do. So let's click create here. And that's really all you needed to do. So what we should see is if we were to go in and open up a new pull request, everything would look the same as it did before. But now it's much more flexible when we want to allow someone to bypass one of these rules, because we can just add them to the bypass list for a specific rule set instead of just having one giant rule set where it's all or nothing. So anyway, hopefully this challenge helped you to take your skills with rule sets a little bit further.
Frequently asked questions
What does the SDLC Security Strategy Fundamentals lesson cover?
This lesson focuses on how to build a security strategy across the software development lifecycle, one of the core knowledge areas in the GH-500 course. It sets the foundation for the rest of the course, which moves into security alerts, secret protection, dependency security, and repository governance in GitHub Advanced Security.
How long is the SDLC Security Strategy Fundamentals lesson?
The lesson runs 46 minutes. It is one of 11 skills in the Microsoft Certified: GitHub Advanced Security (GH-500) course, which totals about 8.5 hours of video that most learners finish in two to three weeks alongside regular work.
How does this lesson fit into the GH-500 certification course?
Building a security strategy across the SDLC is the first knowledge outcome listed for the GH-500 course. The later skills apply that strategy through detecting and responding to alerts, remediating secrets and supply chain alerts, applying CODEOWNERS and roles, and managing organization-level security settings.
Who on an engineering team should take an SDLC security strategy lesson?
The course is built for developers, DevOps engineers, platform engineers, and GitHub administrators who own repositories or org-level settings. IT Directors and Team Leads who set security policy for development teams will also find it useful for establishing a shared understanding of where security fits in the release cycle.
Why should security be built into the SDLC instead of handled at the end of a release?
According to the course material, when security is left to a few people at the end of the release cycle, alerts pile up, remediation slows, and audit evidence becomes hard to produce. Building security into the SDLC helps organizations reduce late-cycle security escalations and create clearer accountability for code ownership and alert response.
How can a Training Manager track a team's progress through this GH-500 course?
Team reporting shows per-learner progress and completion, cohort and group views, and completion exports that can serve as audit evidence. The course material recommends assigning the course before changing security policy so the team shares the same understanding when new controls go live.
Team training path
Turn this skill into assignable team training
This free skill is a preview of the courses your team can assign, track, and report on with CBT Nuggets.
Free training library
More free lessons in GitHub
GitHub
Developing Projects with GitHub Codespaces
Free lesson from GitHub Actions Tutorial: Development Automation · 1h
GitHub
Deploy Terraform Templates with GitHub Actions
Free lesson from GitHub Actions Tutorial: AWS & Azure Infrastructure Deployment · 1h 6m
GitHub
Introduction to Source Control with GitHub
Free lesson from GitHub Tutorial for Beginners · 56m
GitHub
Automation Basics with Github Actions
Free lesson from Microsoft Certified: Github Actions (GH-200) · 46m
$59
seat / mo, billed annually
