← All talks

Breaking Build: Red Teaming CI/CD Pipelines and GitHub Actions [BSidesPDX 2024]

BSides PDX · 202442:58380 viewsPublished 2024-11Watch on YouTube ↗
Speakers
Tags
CategoryTechnical
TeamRed
StyleTalk
About this talk
Breaking Build: Red Teaming CI/CD Pipelines and GitHub Actions Craig Wright (@werdhaihai , Medium , GitHub) CI/CD pipelines are a major component of most modern organizations, enabling the movement of code from development to production, automating software builds and deployments, and even managing infrastructure changes. These pipelines also present a significant attack surface, making them prime targets for adversaries. As a red teamer, I’ll guide you through the structure and vulnerabilities of CI/CD systems, with a focus on GitHub Actions. Through real-world examples, personal case studies, and live demos, we discuss how these systems can be exploited as well as tips for hardening these environments. Craig Wright is an Adversary Simulation Consultant at SpecterOps, specializing in red teaming and offensive security. Craig Wright enjoys hacking Active Directory, CI/CD systems, developing offensive tooling, and writing ridiculously long bash one-liners. --- BSides Portland is a tax-exempt charitable 501(c)(3) organization founded with the mission to cultivate the Pacific Northwest information security and hacking community by creating local inclusive opportunities for learning, networking, collaboration, and teaching. bsidespdx.org
Show transcript [en]

[Music] all right so um I guess quick show of hands does anybody use GitHub actions at work sweet all right cool I hope I have something valuable for you um first of all my name is Craig Wright I am a uh adversary simulation consultant uh at spectr Ops which means that basically I uh get paid to break into systems uh perform red team operations and penetration tests uh in my spare time uh I pretend to be a professional chef uh although my partner tends to think I just make a big mess uh so quick agenda uh we're going to be going over a sort of very brief uh introduction to what cicd systems are uh

and then we're going to go into uh the ways that they can be attacked uh that we will follow that up with a deep dive sort of into uh GitHub actions and after that we will do some demos um I did all of the things this morning the demos should go smoothly but if not I've prepared some videos uh and then some defensive strategies and options for uh people to hopefully protect these systems so what is a cicd pipeline uh this is going to be a set of systems which enable a sort of repeated and an automated way to uh analyze test and integrate your code uh build it and deliver it somewhere um that's kind of

like uh whatever annoying definition but I have harnessed the power of AI to uh create a diagram and uh as we can see this is like complete nonsense and so AI doesn't know what it is uh a lot of us don't know what it is and so uh these are definitely uh places to try and understand uh in more depth so what is it um so first up we have the version control system this is going to be uh something like GitHub or gitlab or bit bucket uh this is the place where you're going to have your actual source code stored this is going to generally be get backed and uh provide some nice features such as

branching and we can track changes and see who's done what and verify that the actual uh people pushing code are who they say they are the then there are the uh continuous integration systems and the deployment pipeline systems uh we have circleci Jenkins team City uh there's probably more uh this is a very interesting place to be because a lot of these systems generally are going to have a lot of credentials on them uh for potentially uh very very sensitive systems uh they can access and then finally we have the artifact repository this could be something like uh GitHub as well or this could be S3 or jrag uh jrog artifactory where you're actually storing the compiled and built code uh

out in a location so it can be accessed by other systems in order to uh talk about attacking cicd we are going to talk about a few things here we're going to talk about the attack surface so what is the actual attack surface for cicd systems um my favorite or one of my favorite is the developers workstation this is a wonderful place to live um developers have access to uh Min systems sometimes that they don't actually need they also often times do not have the best hygiene and there can be uh credentials just laying around and then this is also a potential entry point into the cicd system uh then we have the repositories this is going to be either the local one

on the developer workstation or the repository that's actually stored up in your uh in your Source control uh such as GitHub and finally or not finally but third party dependencies these are one of the more uh scary uh this is one of the more scary components of the attack surface here because you don't always I mean who's actually verifying that the compiled stuff that they're using for their uh builds is actually not malicious so this is a very scary place to be we'll have some examples to talk about this uh and then build systems as I said this is a really interesting place to be for an attacker if we can get onto that build system we

can potentially modify source code as it's flying through uh we can also maybe steal Secrets uh there's often times secrets for deploying things or uh if we're talking about an infrastructure as code situation there may be credentials for uh AWS or Azure in there and then the artifact storage uh just I don't know two or three weeks ago we found credentials in someone's bash history for artifactory uh we were able to upload a updated version of uh a package into artifactory and then the client later told us that this was pulled down into two uh additional Stacks which is uh a scary thing to think about because this sort of sidesteps a lot of the protections that

can be laid in place ahead of um ahead of time so here's a nice little diagram uh as I mentioned we have the developer uh this is a wonderful place to be for us the developer generally is going to be pushing code into the uh repository the repository is going to have some sort of Trigger or configuration file which tells a build system or a runner how it should interact with the source code and then the runner is either going to push this out to uh artifact storage and then we have the consumer who is either going to pull the code from the repository or from the artifact storage uh and as an attacker we can enter pretty much

anywhere in this uh in this whole uh uh path here so the main places we're going to be talking about are the repository and the build system uh section we will touch briefly on artifacts uh but yeah so a couple of real world examples so the first one I'm sure everyone is probably tired of hearing about solar winds I think that this is a work of art uh this is really really impressive stuff um the actual malware consisted of two components uh there was the Sunspot uh malware which was the sort of first stage and this ran on the actual build system now what it did is it ran as a scheduled task and it would monitor for

any new instances of the msbuild.exe process and if you're not familiar with Ms build this is the uh program that is used for compiling source code on Windows systems uh so this scheduled task it would monitor for instances of Ms build and then it would grab the command line uh arguments and determine if this specific build was building uh something for a specific product that solar winds makes it's called Orion and if it was if it matched that criteria it would modify a C file and this would be compiled into a dll uh the second part was the Sunburst and this is the actual malicious code that existed inside of the uh Orion dll the

back door dll now the thread actors here were quite smart they intended to sort of blend in with the expected traffic from Orion and so like if you're familiar with Cobalt strike malleable C2 uh profiles how you can modify what your egress traffic is looking like uh this is essentially what they did here with their custom C2 and then this is commonly thought to be probably apt29 AKA Russia or Cozy Bear um but the interesting part here is they were first in around uh September in 2019 and they weren't actually notified by a third party until December of 2020 now that's a pretty long time to be in there uh and it's it's quite scary to think about

this could this could happen and so looking quickly at the public repositories for solar winds we can see that uh they are making use of two different uh CI systems so we have Circle CI on the bottom and then on the top we see 124 instances of uh matches for a yaml file inside of a folder. GitHub workflows and people who are familiar with uh GitHub actions this is going to be a workflow containing whatever uh build based on event our next one is going to be XZ now this got a cve and this doesn't really fit the standard uh cve sort of definition in my in my opinion uh because this is just like back doored

code but uh a helpful Dev PRS a null check if we look back at the history of what this gean uh user did on Hub the very first thing that they did was they checked is this pointer they they they made a poll request and said hey this pointer we not checking to see if it's null and so they added just a simple null check it got merged in and then slowly over time this user build rapport and they're able to uh eventually become good friends with the original developer and gain more trust and their code is getting merged in a lot quicker now one thing that's kind of interesting in about cicd systems is we have the

ability to run like tests on our code now for XZ this is a uh archiving utility and it makes sense that testing uh an archive utility you probably want to be verifying that it is able to actually uh decompress files and you want to give it uh broken uh files that are compressed and decrypt those now there there is this uh there's some wonderful trolling if we go and look at the actual uh when the actual malware is injected um stuck net levels of subtle uh but here is the binary files that uh gean had added one of these contains a binary stream which is actually an encrypted payload and so the the full process here is that we have a malicious

build script which does some regular expression searching and if you look at what it's actually going to find inside of the code it's going to find one of these compressed files it's going to pull out the encrypted blob and then it's going to place it in it's an object file and it'll be compiled into the actual resulting XZ binary and if we look here we can see uh that XZ is actually also using GitHub actions um and this is quite interesting and so we can look back and see when did when did GitHub actions actually get introduced uh giaan thank you for uh your your wonderful uh commit here where you're are creating the initial version

of the cicd workflow so quick terminology we have GitHub actions uh I feel like they did a interesting job uh picking these names they all sound almost like they mean the same thing if you look at them from a distance but we have GitHub actions and this is the actual cicd platform uh and then we have workflows now these are going to be the yaml configuration files which are used to define what actions are taken uh in certain events and events are going to be the activity which triggers a workflow so we'll talk about this a little bit more but this can be things like uh issues or poll requests um we also have jobs now

this is going to be a set of steps and the steps are the things that are actually performing something now this could be a shell script or this can be an action uh an action is actually a separate uh separate repository containing code which should execute in a sort of repeatable way so these are meant to like help developers throughout the process one of the classic actions that you'll see is actions checkout and then this one's just going to pull the actual code from the repository and so you can work with it inside of the runner the runner is the actual server or container which performs the build building steps now this could be as I

mentioned this could be uh this is doing you know modifications to Cloud infrastructure or compiling a binary or something like that so workflows here's an example workflow this is a yaml workflow for uh the name here is PR slack notification uh you'll if you want to know if a repository is using GitHub actions you'll look for this folder uh GitHub workflows uh this will be at the root of the repository and these are going to be triggered by an event or on a schedule um I guess you could say a schedule is an event but uh and then uh the other thing to note is that repositories can actually have like many many of these

and so when you're looking at these to try and understand how they all relate to each other can sometimes be challenging because there's dependencies on each other and so we need to go and look through all of this um so events uh as I mentioned this can happen on a schedule this can happen uh whenever you push a release or make a PLL request in this case here we have the trigger or uh the trigger or the event for this workflow is going to be whenever a poll request is opened or synchronized and in this example uh workflow we also have our jobs down here and this is going to be a set of steps

and we can see that this job right here is named notify and we could see that this was going to run on the latest auntu uh machine that GitHub is providing this is a GitHub hosted uh runner and then we have the steps and these can be a shell script or these can be an action I think we're talking about actions on this next slide so we can see here app actions are going to be the uh application that's actually used in the workflow and in this case we're actually pulling a action from slack API SL slack GitHub action and we can see that it takes two parameters the first is a message and the second is the web hook

um if we go to if we want to go check out what the actual code for this action does we can go to we can take that string slack API GitHub action and we can just appin that to github.com and we can see that this one is used to send data to slack using a GitHub action and so uh if we look in here a little bit deeper we can see that the action. yaml file this is where you're going to actually provide a sort of definition for people who want to use your action on what parameters are required what parameters are possible and so forth so Runners I am going to reiterate this several times because I think that

this is a super crazy and dangerous thing but uh GitHub all over the place recommends that you never use a self-hosted runner for a uh public repository they should only be used on private repositories and we'll talk about that a little bit more when we go into the demo and actually prove how sketchy this is uh so GitHub hosted Runners these are going to be free for a bit uh you get a certain number of Runner hours per month uh after a while um you have to pay them and I I don't actually know what the cost is so uh I'm I'm not like in a giant organization where we're developing a bunch of stuff

in these uh Runners so uh the uh the thing about these GitHub hosted Runners which is really nice is you have a build run and then they destroy it for you they also manage and maintain this you don't have to worry about secrets and stuff hanging around or bad builds leaving uh artifacts in a runner you just have this thing run once and then uh it does what it's supposed to do and then leaves forever with the self-hosted runners however uh these are going to be free for you to use uh you just have to set it up whatever the cost of you know your Cloud infrastructure for running this thing or whatever the uh resources

internally you need to allocate to run one of these things uh but these are going to be persistent hosts the way that this runs is it's going to run as a shell script or a PO shell script or a binary uh these are available for OSX uh Windows and Mac and these are going to be managed and maintained by you but yeah the big thing here don't run these on a public repo so what kind of a tax do we have for GitHub actions the most obvious and probably uh easiest is probably stealing secrets so we can look at any public repository or if we've already breached the perimeter and we're internal and we're on a

developer's workstation and we find a bunch of repositories we can go looking for this uh this sort of syntax here with this uh dollar sign bracket bracket Secrets dot now that's going to indicate that this repo or this organization uh has access to a secret which can be used inside of Runners depending on what this is doing this may be really valuable to attackers uh and so these can be scoped to a repository or an organization and they are going to be available regardless of any kind of Branch protections you have in place so I can just make a new poll request and grab this secret out of here uh this isn't only going to work on Main uh and then

uh GitHub does a pretty good job of trying to prevent this but they're also like if you do something crazy you can expose uh your uh secrets in the logs so when we're talking about actions and repositories and public repositories we're going to be uh able to go to these public repositories and click the little actions button and we can see the logs for everything that's ever run uh and if something is done incorrectly you can potentially have credentials sitting here all right so event context injection uh this is when so whenever an event is triggered there is a context associated with it and this context contains values made to assist developers and uh make things easier uh

in this case uh you can potentially have attacker controled data in one of these uh pieces of uh stored in one of these in event contexts and if the event context is taken and put in the wrong place uh it can be executed so in this example here uh we have a variable title uh this is taking the GitHub issue title and this whole workflow here is meant to just check if the issue title is begins with bug because you know we're we're going to be mean to people and we're going to say hey you need to put bug at the beginning of your issue title and then we take uh this next variable down

here content uh comment and we're going to to pass that variable directly into there and this is going to get executed so um the problem is that we can potentially inject commands if we make a goofy issue title uh and we'll we'll go over that in the demos uh this is again when I mentioned don't run your uh self-hosted Runners publicly uh this is the reason uh so you can basically inject your own workflows into someone else's Runner uh GitHub this is another quote from GitHub Forks of your public repository can potentially run dangerous code on your self-hosted Runner uh by creating a poll request that executes code in a workflow I'm not really sure why the default is

set this way it seems really dangerous uh I'll show you how to fix it in a little bit but this is totally crazy to me um but this is awesome for attackers uh it's simple we can just make a poll request and we can fix something innocuous like a typo and then have it merged into Main and now we are a contributor and once we're a contributor none of our following PLL requests are actually going to be uh requir approval so if we make a workflow where the uh the poll request uh we make a workflow on a pull request event and then we make a PLL request it's going to get executed and it's not going to get executed on

our runner it's going to get executed on their Runner uh and we'll do that also in the demo now another interesting attack uh is artifact poisoning uh this this could be poisoned in a bunch of different ways uh and we're not going to actually cover this because mostly because the implementation of this is going to vary really wildly uh but to briefly talk about it um we have the third party components themselves if we go Downstream somewhere or I shouldn't say we because ethically this is not really something possible uh in most red teams but a third party could have potential and uh malicious code injected into it which you use and then that gets pulled

in and compiled with your stuff um we can also potentially modify the source code uh that is used on the runner so the runner pulls down the code we modify the code and then that gets build we can also just replace the compiled code after it's been compiled um and then we can wait for something to push this up to the uh artifact storage now this is pretty uh this is a prettyy interesting attack and there I there's some pretty serious uh danger uh options here so uh again the the problem here is that in in one case there's a great uh blog post here by legit Security on artifact um poisoning and this existed

in the rust langing now what happened was they used that poll request trick that we just talked about where a poll request is going to uh execute inside of a runner now that Runner is able to upload artifacts and it does not upload artifacts on behalf of the user who made the poll request it uploads artifacts on the repository so when they pulled down they made a fork of the GCC project and they modified modified a workflow and they added one thing in there to upload the artifact it went into GitHub artifact storage now what rustang was doing was they were pulling down the artifact from GitHub artifact storage but GitHub artifact storage doesn't make

a clear uh delineation between forked uh forked artifacts and uh and the main branch or the uh the base branch of uh the artifacts so they pulled down a malicious version and they they used that in uh in their work flow uh cash poisoning this is a really really cool idea I think um you are probably going to break everything uh but there's a really really great uh great blog post by Adnan uh con who wrote All About a journey into looking into how to actually poison the cash the long story short is in my opinion if you're able to get onto a runner uh which is required to be able to poison the cach there's probably

an easier way to do what you're trying to do so the idea is that you have this cache which is scoped down to your repository and that Cache can be up to 10 gbt uh in size and we are going to if we need code for part of our compilation process and we're using this GitHub action uh cache we can store versions of the uh dependencies here here so we don't have to pull them a bunch of times and have all this bandwidth so we can potentially inject code uh or inject into the cache and we have to fill up and make sure we overwrite everything that already exists there so that's one of the reasons why it's not really a

super viable attack because trying to upload 10 gabt of data overwriting uh whatever's already in there and still being able to put dependencies back there uh and not break everything thing uh this makes this makes it pretty challenging and if you read this blog post you'll find uh he had success but he broke everything um so yeah uh now we're going to we're going to do the demo I have a virtual machine running here um we have whenever you see this uh Black Background that's going to be me acting as an attacker um this is my personal repository here where we have a simple simple repo and if we go into the workflows the first

thing I'm going to demo is the um uh extracting Secrets here now the way that we're going to do this is kind of uh not not exactly the best way and I don't recommend anybody who's in the offensive world to do it exactly like this but this is meant to illustrate the uh the issue that we can sort of circumvent which is they're not actually going to protect the secret here um so by simply taking this uh and piping this to base 64 piping this to base 64 again um we are going to evade their uh their sort of attempt at hiding this um and so we can go ahead and commit this change uh

commit straight into main man all right uh if we go back over to our actions we can see we have this workflow

running and if we wait for the uh uh uh action or the runner to initialize then we have the output and we can see we have a base 64 encoded blob here if we go ahead [Music] and that small that better yeah we can just Echo I know how to type

thank you and we can see we have our hacking in the rain with Sasquatch here so uh the the thing I mentioned is that we should not actually do this on an operation because we risk exposing Secrets like this um and also it looks pretty sketchy so probably you want to do something like uh maybe a COR request to an endpoint that you control uh and have the encrypted secret be sent out to there uh but that's an exercise for you to um handle there um the next um the next one that I want to cover is the uh the event injection so if we go back to our workflow uh we have our uh one

second cancel this stop running oh I know that's something else okay so if we go back into our code here um we can look at this issue real or this uh check issue title workflow and we can see that this is going to execute whenever an issue is opened or edited uh we can also see that there are uh two Secrets associated with it and we have the permissions of the GitHub token here which are scoped down as they should be to just issue right um and if we look here we have that vulnerability that we were kind of looking at earlier where we're going to have execution of whatever potential execution of whatever gets put in here so if we go into create

an issue uh we'll create a new issue you can already see what I was doing before um but we can we can run like uh command substitution like this lsla um I don't know who am I uh and then we can submit this issue and if we wait a minute uh we'll actually have the GitHub actions bot respond respond with the output from this

command and there we have it so the validation failed because uh yeah this is not what it's expecting uh so we now have uh who am I Runner uh we can see two files we didn't pull anything down as part of our workflow so there's nothing here but um okay so the next the next one I want to demo here is the actual malicious pull request and so over here we have uh a different user and this uh GitHub actions besides PDX repository now we can come in here and we can take this URL and we can go back over to our attacker machine and we can be friendly and we can say Hey you know um we're going to

Fork this and then we're going to fix something for you

so if we look here we have now a fork repository and we can go ahead and we can update this uh this read me here and we can say Hey you know you forgot

punctuation okay commit and then we are going to go back to the root of our repository and we are going to uh contribute we're going to open a poll request and we are going to say yeah you forgot punctuation uh you need that create poll request now over here we are going to uh jump over to our other unsuspecting uh user here they're going to take a look they're going see hey I got a poll request here what is this and they're going to do their due diligence they're going to come in here and they're going to see uh okay we have a we have one commit we have uh one file was changed and this is

simply adding a period all right looks good to me let's uh all right

approve now uh merge merge poll request confirm confirm here we are okay so if we come back we can see now we have uh the uh merged merged poll request and we can also see that where is it we have two contributors uh one is me and one is the original author now if we come back over here and we can make a new change which is going to be we're just going to Simply add a new workflow here in the uh we're not on the right Branch

okay okay uh if we come in here we can come into the workflows and we're going to add a new file um I'm going to do this all in the goey uh okay so so we want to call this I don't know um checkin do yaml uh and if we I have a previously built uh workflow here which is also very very small text uh let's see uh and so this is just simple yaml and this is going to uh use a action that I created and the reason I made this this action is so that it looks a little bit less sketchy than straight up curling something and executing it but but um this action basically just curls

something and executes it which is a uh a good thing to know so go away go away here we go okay so come over here we're going to put our yaml here really quick let's take a look at the actual uh malicious action that I created and if we go in here to Source we can see there's just one typescript file uh this is not really doing much but it's taking a URL and it's going to write it to this crazy path uh and then it's going to uh Run download which is basically just an https git we're going to then run exec sync which is going to change the uh uh file to be executable and then execute

it so pretty simple but we're relying on the fact that somebody's going to look at this and be like I don't know what that is or I'm going to have to go and take a look and we can already delete the repo or something like that so if we go ahead and we commit our changes here uh we are going to run this and then we will uh go ahead and contribute here we're going to open a poll request to the original uh repository we're going to go ahead and yes open create poll we want that and if we wait for just a second we can see now we are on the uh we are on the actual

snoa uh users thing and we can see that we have the yaml file executing and if we go ahead and take a look here we can see uh it's running get run now if we go to our super awesome C2 besides

pdx.com we can go ahead and log in here and we have a uh call back here from the repo interact and we're now running inside of this Runner and so we could run get in to uh access the credentials or uh whatever might be on this Runner and again this is crazy because we don't have permission to run things why do we why do we have permissions to run things inside of this uh this is the default so um yeah I don't know okay so back to uh back to our presentation let's go defensive strategies so first don't run a runner on a public repository a self-hosted runner on a public repository this is that default configuration I was showing

you or I was talking about where we require approval for firsttime contributors uh only first-time contributors will require approval to run workflows this is in my opinion an insecure default and this should be changed uh we should switch that over to this one uh require approval for all outside contributors um additional security for the actual Runners I would say that uh if you can minimize the actual access that it has to any other resources and minimize the actual outbound internet access it has to things to only what it needs um that would be my recommendation for these uh GitHub documentation is quite good uh they do definitely a million times remind you do not use a self-hosted

runner on public repositories and I'm not going to say anybody's name but I looked around at a couple of organizations um in Portland and uh some some people are doing this so don't don't do that question for you yes how does the adversary know when you're using a selfhosted runner it's in the yaml file I can show you in a minute um we'll get there okay so for repositories I recommend using a code owners file and this is going to be uh this is going to be similar to a get ignore file uh but this basically is saying this repository is owned by or this folder or file is owned by a specific user we can add specific

folders into there which require approval so even internal uh employees can't actually modify files in certain places um then uh you know enable Branch protection which will get you commit signing uh this is going to cause me a lot of problems as an adversary if I'm on a uh developer workstation and I need to uh I want to grab Secrets uh if if you have Commit signing enabled I need to kind of wait until the actual developer comes and makes a legitimate push and doesn't notice that I have modified anything so um this this would uh knock out a lot of that uh for the actions um I don't know if you can see this but

this is a typo up here uh it's atci NS uh I created this the other day it was pretty easy it looks pretty legit too I think um but use use caution with your actions make sure that you're doing some amount of validation or vetting of like what it is that you're running um and then uh make sure that whenever you are going through to modify these things that you're always using the most upto-date version um and then the secrets in the GitHub tokens um so this was a quick search that I did here uh on the right in the bottom we can see there are a bunch of uh secrets and they are defined

as vars now if we look in the top uh top right we have secrets and variables when you go to add these secrets to your repository uh you can choose to add Secrets or variables it does not protect the variables in the same way that it protects uh the secrets and so if something errors ever any of these pretty juicy looking Secrets could be exposed um and then as always you know limit the scope of the actual secret like if you need AWS creds in a runner for some reason uh you should just make sure that that can only do what it needs to do uh and not admin star star um that is oh acknowledgements yeah

so while I was doing a lot of this uh research and looking into this stuff uh I kept coming across these two names Adan con and John stawinsky so I definitely wanted to give them a huge shout out because a lot of uh a lot of whenever I was like o what is the attack surface here I would end up on a blog post by one of these two individuals um if you are a developer and uh you are using GitHub actions there's a pretty cool tool that the two of them have worked on uh called gate gate X the extreme Edition um I would definitely recommend that you do not do any of the

like sort of uh exploit attacks that are possible with it but stick to it has like a sort of analysis you can uh scan for vules um yeah I think that is all I have oh I wanted to show you the self-hosted runner thing real quick so if we go real quick to the um this is what you'll be looking for this runs on it'll say either aun to latest or it'll say self hosted in this case we know that this one is selfhosted you can also go to the actual uh repository here I just everything okay uh if we go into actions this is how you can see you have that GitHub workflows folder and

then we can see that my C2 agent is still running um which we can go ahead and kill and yeah so we can look in here and we can see details about these uh merge requests we can go ahead and view the uh the specific action and like if this is a public repository we can see all of this stuff as anybody so we can come in here and we can see like okay it's doing some setup here we have the uh runner information uh this is a different workflow which is just made to show like the repo that it's running as um but yeah that that would be how you look for it is that self-hosted string in the um

um yeah file yeah what's the um GitHub signing with a hardware tokens like on a map do it work yeah yeah I I think there's a so the slide um there's a link on the specific page where I talk about that why is this here and this is a uh QR code to the slide deck so all the links are on the bottom there um but yeah so you can set up for UB key I know they just had a interesting uh Fiasco uh but yub key uh you can get your UB key to sign your commits so gitlab I didn't actually focus on gitlab here but yeah there's a similar thing going on I'm not sure what

the poll request into the uh into the actual Runner if that works the same it possibly does I don't know it'd be fun to test thank you guys [Music]