The CI/CD-Goat project allows engineers and security practitioners to learn and practice CI/CD security through a set of 10 challenges, enacted against a real, full blown CI/CD environment. The scenarios are of varying difficulty levels, with each scenario focusing on one primary attack vector.
The challenges cover the Top 10 CI/CD Security Risks, including Insufficient Flow Control Mechanisms, PPE (Poisoned Pipeline Execution), Dependency Chain Abuse, PBAC (Pipeline-Based Access Controls), and more.
The different challenges are inspired by Alice in Wonderland, each one is themed as a different character.
The project’s environment is based on Docker images and can be run locally. These images are:
- Gitea (minimal git server)
- Jenkins
- Jenkins agent
- LocalStack (cloud service emulator that runs in a single container)
- Lighttpd
- CTFd (Capture The Flag framework).
The images are configured to interconnect in a way that creates fully functional pipelines.
Download & Run
There’s no need to clone the repository.
Linux & Mac
curl -o cicd-goat/docker-compose.yaml --create-dirs https://raw.githubusercontent.com/cider-security-research/cicd-goat/main/docker-compose.yaml cd cicd-goat && docker-compose up -d
Windows (Powershell)
mkdir cicd-goat; cd cicd-goat curl -o docker-compose.yaml https://raw.githubusercontent.com/cider-security-research/cicd-goat/main/docker-compose.yaml get-content docker-compose.yaml | %{$_ -replace "bridge","nat"} docker-compose up -d
Usage
Instructions
- Spoiler alert! Avoid browsing the repository files as they contain spoilers.
- To configure your git client for accessing private repositories we suggest cloning using the http url.
- In each challenge, find the flag – in the format of flag# (e.g flag2), or another format if mentioned specifically.
- Each challenge stands on its own. Do not use access gained in one challenge to solve another challenge.
- If needed, use the hints on CTFd.
- There is no need to exploit CVEs.
- No need to hijack admin accounts of Gitea or Jenkins (named “admin” or “red-queen”).
Take the challenge
- After starting the containers, it might take up to 5 minutes until the containers configuration process is complete.
- Login to CTFd at http://localhost:8000 to view the challenges:
- Username:
alice
- Password:
alice
- Username:
- Hack:
- Jenkins http://localhost:8080
- Username:
alice
- Password:
alice
- Username:
- Gitea http://localhost:3000
- Username:
thealice
- Password:
thealice
- Username:
- Jenkins http://localhost:8080
- Insert the flags on CTFd and find out if you got it right.
Troubleshooting
- If Gitea shows a blank page, refresh the page.
- When forking a repository, don’t change the name of the forked repository.
Contributing
Development
- Clone the repository.
- Rename .git folders to make them usable:
python3 rename.py git - Install testing dependencies: pip3 install pipenv==2022.8.30 pipenv install –deploy
- Run the development environment to experiment with new changes: rm -rf tmp tmp-ctfd/ cp -R ctfd/data/ tmp-ctfd/ docker-compose -f docker-compose-dev.yaml up -d
- Make the desired changes:
- All services except CTFd are completely configured as code so desired changes should be made to the files in the appropriate folders.
- To make changes in CTFd, use the admin credentials.
- Shutdown the environment, move changes made in CTFd and rebuild it: docker-compose -f docker-compose-dev.yaml down ./apply.sh # save CTFd changes docker-compose -f docker-compose-dev.yaml up -d –build
- Run tests: pytest tests/
- Rename .git folders to allow push: python3 rename.py notgit
- Commit and push!
Checklist
Follow the checklist below to add a challenge:
- CTFd:
- Write challenge description.
- Choose category according to difficulty level.
- Make sure the challenge is visible and has value according to difficulty.
- Write hints in order of usage.
- Add a flag. Make sure to select if it’s case-insensitive.
- Gitea:
- Configure a new repository in gitea.yaml.
- Create the repository under gitea/repositories. Use an open-source repository that use the MIT license as a template for the challenge repository.
- Jenkins:
- Configure Jenkins and add new jobdsl files in the casc.yaml file.
- Make sure jobs don’t run periodically. Jobs should be triggered by events / polling.
- Validate that the new challenge doesn’t interfere with other challenges.
- Make sure the flag is not accessible when solving other challenges.
- Write tests.
- Write the solution.
- Update README.md if needed.
- In order to run the CI, make sure you have a CircleCI account and that you’ve clicked “Set Up Project” on your fork of the project.