Have you ever tried to reveal a secret value stored in your continuous integration/delivery service? No? Well, maybe
someone else did.
Automation (or "CI") services… We are all using them, or at least should be they are the standard these days, and yet they are rarely given the attention they need.
I recently decided to use Github Actions to build, test, and release one of my Node.js open source projects, so I did what every developer would, I read the documentation and ran a few experiments, and soon after that, I realized that I'll have to store the NPM registry token as a secret to automate the release process.
Whenever I hear the word "secret" the following questions pop into my head:
"What will happen if the secret is revealed? Can it be revealed?"
Automation services are nothing new - I've worked for several companies throughout my career, and there was always some automation
service being used - point is, most secrets I've encountered in those automation services always gave me the chills because deep inside of me I knew if I can (and I could) turn them into plain text so does someone with malicious intents.
A quick search of my questions came up with a two very interesting read-ups and I recommend reading them, they describe the inherent vulnerability automation services introduce, and why they are a prime candidate when it comes to bug bounty programs
- Shaking secrets out of CircleCI builds (I highly recommend reading this)
- CI Knew There Would Be Bugs Here
Typically automation services are set up to act on any change happening throughout a codebase - whenever a change is pushed, a revision of the change will be fetched and executed.
Automation services (unlike me), do not have trust issues, especially when it comes to open source projects, because now, instead of trusting a limited number of actors, they trust any actor. 🤯
Before we discuss the solution, let's discuss the possible changes a malicious actor can do in a codebase - A Node.js project for example:
- Adding a malicious module to the package.json dependencies
- Modifying your workflows (.github/workflows/** ) to reveal secrets
- Changing scripts that may be used during the build phase
The above risks are relevant to any automation service and project type, not just Github Actions + Node.js project.
… Scary stuff if you ask me 🙀
So what can we expect from Github Actions? Not much.
The only thing worth mentioning is workflows that are triggered by a pull request will not have access to the original repository secrets.
The above is only partially true. Read the following announcement:
GitHub Actions improvements for fork and pull request workflows
Wouldn't it be nice if workflow runs could be monitored and even canceled under specific conditions? Actually, that is possible!
The solution: Protected Workflows
Protected Workflows is a Github Application
and is designed to cancel workflow runs by enforcing rules you configure, you can for example:
- Specify user names who are allowed to trigger workflow runs
- Specify file paths that may be changed
- Specify paths that may not be changed (globs are supported as well)
Here is an example of how a config file may look like:
# Fallback rule in case nothing specific is set. anyEvent: trustOrgMembers: true trustCollaborators: true events: push: - &basic_rule trustAnyone: true paths: disallowed: - ".github/**" - "package.json" - "package-lock.json" pull_request: - *basic_rule pull_request_target: - *basic_rule
The above config is using anchors, which is a useful YAML feature that enables re-using certain text blocks, and has a single rule defined ("basic_rule") used by events "push", "pull_request" and "pull_request_target".
The shared rule simply trusts any actor and will cancel workflow runs
in case certain paths were changed during the contextual event.
Its a wrap!
If you are interested in learning more, head over to the official documentation.
Thanks for taking the time to read this article! 🤓
If you have any questions or feedback, please leave a comment below.