You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: jekyll/_cci2/security-recommendations.md
+96-4Lines changed: 96 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -21,16 +21,108 @@ If you are getting started with CircleCI, there are some security best practices
21
21
- It is important to rotate secrets regularly in your organization, especially as team members come and go.
22
22
- Rotating secrets regularly means your secrets are only active for a certain amount of time, helping to reduce possible risks if keys are compromised.
23
23
- Ensure the secrets you _do_ use are of limited scope - with only enough permissions for the purposes of your build. Understand the role and permission systems of other platforms you use outside of CircleCI; for example, IAM permissions on AWS, or GitHub's [Machine User](https://developer.github.com/v3/guides/managing-deploy-keys/#machine-users) feature.
24
-
- Sometimes user misuse of certain tools might accidentally print secrets to `stdout` which will land in your logs. Please be aware of:
25
-
- running `env` or `printenv` which will print all your environment variables to `stdout`.
26
-
- literally printing secrets in your codebase or in your shell with `echo`.
27
-
- programs or debugging tools that print secrets on error.
24
+
- Follow the advice in [Handling secrets securely](#handling-secrets-securely), below, when writing scripts and working on the command-line.
28
25
- Consult your VCS provider's permissions for your organization (if you are in an organization) and try to follow the [Principle of Least Privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege).
29
26
- Use Restricted Contexts with teams to share environment variables with a select security group. Read through the [contexts]({{ site.baseurl }}/2.0/contexts/#restricting-a-context) document to learn more.
30
27
- Ensure you audit who has access to SSH keys in your organization.
31
28
- Ensure that your team is using Two-Factor Authentication (2FA) with your VCS ([Github 2FA](https://help.github.com/en/articles/securing-your-account-with-two-factor-authentication-2fa), [Bitbucket](https://confluence.atlassian.com/bitbucket/two-step-verification-777023203.html)). If a user's GitHub or Bitbucket account is compromised, a nefarious actor could push code or potentially steal secrets.
32
29
- If your project is open source and public, please make note of whether or not you want to share your environment variables. On CircleCI, you can change a project's settings to control whether your environment variables can pass on to _forked versions of your repo_. This is **not enabled** by default. You can read more about these settings and open source security in our [Open Source Projects document]({{site.baseurl}}/2.0/oss/#security).
33
30
31
+
## Handling secrets securely
32
+
{: #handling-secrets-securely }
33
+
34
+
Many builds must reference secret values. When these secrets are entrusted to CircleCI, we make sure they stay safe. We understand that security is critical to every organization’s success. However, there are some things that you can do to help protect secrets at the boundary between CircleCI’s systems and yours.
35
+
36
+
### Risks of using secrets on the command-line
37
+
{: #risks-of-using-secrets-on-the-command-line }
38
+
39
+
There are several ways that Unix and Linux shells can expose sensitive data. It is important to consider all of them when working with CircleCI on the command-line.
40
+
41
+
***Command history**: If you include a secret in a command’s parameters, such as `export MY_SECRET='value'` or `curl --header 'authorization: Basic TOKEN'`, that value could be written into your shell’s history file, such as `.bash_history`. Anyone with access to that file could then retrieve the secret.
42
+
***Process arguments**: While a process is running, any user on the same system can view the command that started it. The easiest way to see this is by running `ps -ef`, but there are other methods as well. Critically, this information is exposed after environment variables have been interpreted, so that when running `mycommand "$MYVAR"`, `ps` will show `mycommand <value of MYVAR>`. On some older variants of Unix, such as AIX, it is also possible for all users to see all environment variables for any process.
43
+
***System logs**: Many systems log all commands executed using `sudo` for auditing. There are many auditing services that record all commands. Such services could potentially export those logs into systems that are not designed to keep secret data safe.
44
+
***Console output**: Depending on your threat model and what kind of console is in use, simply printing a secret to the console could carry risk. For example, use of screen-sharing tools for activities like pair-programming can lead to accidental, persistent exposure of secrets transited through untrusted videoconferencing providers, possibly even in video recordings. It is best to choose tools that print secrets to the console only when necessary and explicitly told to do so by the user.
45
+
***Persistent, unencrypted secrets on disk**: Although it is common practice for command-line tools to store and use secrets stored in files in your home directory, such files' availability to all processes and persistence over time may be a significant risk. Some of the techniques below can help avoid the need to leave secrets on disk.
46
+
47
+
### Mitigation techniques
48
+
{: #mitigation-techniques }
49
+
50
+
There are many techniques to help mitigate the risks discussed above. Here, we will focus on methods for using `curl` and [the CircleCI CLI]({{site.baseurl}}/2.0/local-cli) securely with the Bash shell.
51
+
52
+
#### General precautions
53
+
{: #general-precautions }
54
+
55
+
Avoid running `env` or `printenv`, which will print the values of all environment variables, including secrets.
56
+
57
+
Avoid writing secrets into your shell history with these two techniques. However, note that turning off history will not prevent commands from being exposed through audit logs and `ps`:
58
+
- Running `set +o history` before the sensitive commands will prevent them from being written to the history file. `set -o history` will turn history logging back on.
59
+
- If your shell supports the `HISTCONTROL` environment variable, and it is set to `ignoreboth` or `ignorespace`, placing a space before your command will prevent it from being written to the history file.
60
+
61
+
Be aware that `export` is built in to Bash and other common shells. This means that, with precautions, you can avoid exposure of secrets to the history file, `ps`, and audit logs when using `export`:
62
+
- Make sure to avoid writing to the shell history by using `set +o history` or `HISTCONTROL`.
63
+
- Next, if unsure, verify that `export` is really a shell built-in by using the `type` command: `type export`
64
+
- Remember that information will still be exposed in your console, and make sure you are OK with that risk.
65
+
- Follow the rest of the precautions on this page related to the use of environment variables.
66
+
- As soon as you are finished using a secret you have `export`ed, consider using `unset` to remove it from the shell. Otherwise, the `export`ed environment variable will still be available to all processes spawned from that console.
67
+
68
+
`read`, another shell built-in, can be used to set an environment variable without exposing it to the console.
69
+
```
70
+
# Check that your version of read supports the -s option
71
+
help read
72
+
73
+
IFS='' read -r -s MY_VAR
74
+
# (enter your secret; press return when done)
75
+
76
+
# Alternatively, read from a file
77
+
IFS='' read -r MY_VAR < ~/.my_secret
78
+
79
+
# Or a process
80
+
secret_producer | IFS='' read -r MY_VAR
81
+
82
+
# Export the variable so that it is available to subprocesses
83
+
export MY_VAR
84
+
```
85
+
86
+
#### Using the CircleCI CLI
87
+
{: #using-the-circleci-cli }
88
+
89
+
Use the [the CircleCI local CLI]({{site.baseurl}}/2.0/local-cli) instead of `curl` when possible. The CLI takes extra precautions to avoid leaking secrets when performing sensitive operations. For example, when [adding a secret to a context]({{site.baseurl}}/2.0/local-cli), the CLI will prompt you to enter the secret rather than accepting it as a command line argument.
90
+
91
+
If writing a shell script that uses the CircleCI CLI, remember that in Bash you can avoid exposing secrets stored in environment variables or text by using the `<<<` construct, which does not spawn a new process while piping a value: `circleci context store-secret <vcs-type> <org-name> <context-name> <secret name> <<< "$MY_SECRET"`. This is more reliable than using `echo` or `printf`, which may or may not be shell built-ins and therefore could spawn a process.
92
+
93
+
#### Using curl safely with the CircleCI API
94
+
{: #using-curl-safely-with-the-circleci-api }
95
+
96
+
##### Protecting the API token
97
+
{: #protecting-the-api-token }
98
+
99
+
When calling the CircleCI API with `curl`, you need to provide an API token. There are several ways you can mitigate risk while doing so:
100
+
101
+
* Use a `.netrc` file: The [netrc file format](https://everything.curl.dev/usingcurl/netrc), which is supported by several different tools, allows you to provide HTTP basic auth credentials in a file, rather than at the command-line.
102
+
- Create a file at a location of your choosing. The default used by some tools is `~/.netrc`. Be sure to `chmod 0600` this file before adding the secret, to prevent other users from viewing its contents.
103
+
- Add a line in the following format: `machine circleci.com login <your token> password`
104
+
- When invoking `curl`, tell it to look in your `.netrc` file for credentials: `curl --netrc-file ~/.netrc`
105
+
* Write the `Circle-Token` header into a file. This requires curl 7.55 or later, but is a more reliable solution than `.netrc`, because some tools that use `.netrc` files do not understand an empty password field:
106
+
- Create a file at a location of your choosing. Be sure to `chmod 0600` the file to prevent other users from viewing its contents.
107
+
- Add a line in the following format: `Circle-Token: <your token>`
108
+
- When invoking `curl`, tell it to read the header from a file: `curl --header @your_filename`
109
+
* Pull the token directly from a tool designed to store secrets, such as 1Password. In this case, you can use [process substitution](https://en.wikipedia.org/wiki/Process_substitution) to retrieve the header without exposing it:
110
+
-`curl --header @<(command_to_retrieve_password)`
111
+
- If you are sure that `printf` is a built-in in your shell, it should also be safe to write `curl --header @<(printf '%s\n' "$MYVAR")`, allowing you to use environment variables without exposing them through `ps`.
112
+
113
+
##### Protecting your secrets
114
+
{: #protecting-your-secrets }
115
+
116
+
Some API endpoints, such as [addEnvironmentVariableToContext]({{site.baseurl}}/api/v2/#operation/addEnvironmentVariableToContext), may require secrets to be sent in the body of `PUT` or `POST` requests. There are several options to help conceal these secrets:
117
+
118
+
* Use a file to compose and store the request body. Be sure to `chmod 0600` this file before adding the secret value to prevent other users from viewing its contents.
119
+
- Point `curl` to this file by using the `@` directive: `curl --data @myfile`
120
+
* Use a heredoc to compose the request body, and pass it to curl on stdin:
0 commit comments