This is a proof-of-concept for a potential exploit that can be used to steal secret keys associated with your Netlify website.
This is current as of November 3, 2019.
Yes.
Even though Netlify's useful for static websites, they offer a lot of extra functionality that enable you to build super extensive web-apps without needing your own server, thanks to features like serverless functions. Essentially, they're Lambda functions that you can roll into your Netlify website without worrying about having to configuring them beyond Netlify.
As such, they're incredibly useful for abstracting away secret keys that the function will use on behalf of the front-end.
In other words, welcome to the JAMStack.
The exploit involves an interaction between two components: deploy previews and your environment variables.
Netlify offers the ability to generate deploy previews, which are status checks for PRs that build a live-preview of the changes. They're incredibly useful since you can review a PR's changes without having to pull, build, and verify your changes yourself as Netlify will do that for you by generating a preview at deploy-preview-<PR#>--<sitename>.netlify.com
.
This feature is on by default.
Environment variables, as the name suggests, are variables that are accessible during your build. They can either be set through your team settings, your site settings, or the netlify.toml
file. Your netlify.toml
configuration will override your site settings, which will override your team settings. In other words, it will read the netlify.toml
file first, then your site settings, then your team settings to determine the environment variables.
In addition, you can set variables (and also basically every other configuration setting) per build context. Those build contexts can be production
, deploy-preview
, or branch-deploy
. This will be important later.
Assume a scenario where you have a public repo that Netlify builds. Within the repo, you have a lambda function that consumes a secret key to access an external service. We wouldn't want to commit those secret keys in the repo so we set them through the UI on Netlify's website.
A bad actor can then come along and submit a PR that uses (and prints) your environment variables on the front-end; this malicious code will be automatically deployed by Netlify, which will expose the key.
Sort of. You're able to specifiy a deploy preview-specific environment variables in your configuration file, which can override the secret keys in your production context. However, a bad actor can simply comment out those lines in your netlify.toml
that sets those context-specific environment variables, effectively bypassing those values. As mentioned previously, the build will then fall back to the environment variables set by your site (the UI). At the time of writing, there is not way to set context-specific environment variables through the UI, so it will expose the production keys.
This repo was set up as a Netlify website with all the default settings; it's a very simple site that uses webpack to generate some front-end JS that consumes (during the build) and prints (when the front-end loads) the CONTEXT
and SECRET
environment variables. The only change to the site's configuration on the website was within the build settings, where SECRET
was set. In addition, we have a netlify.toml
configuration which sets the deploy preview variables to mask our prod variables.
You can view the production site here.
Now, a non-malicious PR was submitted, which generated a deploy preview. Notice that our secret is now the value we set in the configuration file.
Finally, a malicious PR was submitted, which commented out the deploy preview settings in our configuration file. The deploy preview now exposes the production secret.
You're correct, it is. It requires a project to be public, deploy previews to be on (it is by default), and also for the project to consume secret keys. But given that combination, and you're (very unlikely, but still) in for a bad time.
Or you could simply turn off deploy previews.