-
Notifications
You must be signed in to change notification settings - Fork 5.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Store authentication token in encrypted keyring #7023
Conversation
This quits saving the token to a plain text file on disk. Instead, it tries to save it to: - Keychain on macOS - GNOME Keyring on Linux - Wincred on Windows If all else fails, the fallback is to store the token in the config file as before.
"os" | ||
"path/filepath" | ||
|
||
ghAuth "github.com/cli/go-gh/pkg/auth" | ||
ghConfig "github.com/cli/go-gh/pkg/config" | ||
"github.com/zalando/go-keyring" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason why you are not using https://github.com/99designs/keyring besides the cgo problem? The zalando one forks a security
command on MacOS, which is not a secure practice really.
I have to grant access to the security
cli for the github auth token access, and security
can then be invoked with any other shell script after that, losing control of who I grant access to those creds.
The 99designs lib does not have this problem, as it uses native API-s, so MacOS would prompt me to grant access to gh
only.
Using the security
cli tool directly opens up people's hosts to malicious shell scripts also being able to use the security
cli tool and gaining access to the credentials, partially defeating the purpose of storing those secrets in the keychain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checking a bit with the cgo with 99designs, it's only required for macos. None of the other arch needs cgo. With macos builds I think it makes sense to build on MacOS though, as this security feature is more important than being able to build the mac binary on linux, as you're throwing away the security advantage of keychain in the process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@reegnz I believe the CGO is the main reason Mislav chose not to use the 99design/keyring package. I am not sure I am following how shelling out to security
opens up people's hosts to malicious shell scripts though, could you elaborate on that? It seems to me that security
is a tool that already exists on MacOS so gh
utilizing it wouldn't open up any security holes that do not already exist.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On macos when a program accesses a secret in the keychain it prompts you to grant access to the caller application to the given secret. It prompts for your OS password. For convenience you can allow access to that specific secret permanently so the program can access the secret withput havong to type the password on every access.
If you use the security
cli, you're allowing access to the security
binary, not gh
, and this leads to weakened security, as now I cannot restrict access to the secret to only gh
having passwordless access.
This leads to a bad pattern, as now access to the secret is not scoped to your app. The more apps shell out to security
the more access you need to grant that single tool.
This leads to security
having broad access to secrets of unrelated use-cases, and instead of having a clean control in the form of an access matrix of what program accessing which secrets, you now grant access to a single binary no matter the use-case.
If you use the security cli just for github cli this is not a pronlem, but it perpetuates a pattern that weakens the security on macos.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@reegnz Thanks for explaining, I understand your concern now. I think it is definitely a valid concern and have taken it back to the team to discuss further.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TBQH even using security
cli in this flawed way is still much better than plaintext files, so don't let it block rolling out this change completely. I just wanted to highlight that it doesn't fit correctly with the MacOS security model. Eventually improving the implementation to use the native API-s instead of shelling out to security
would be ideal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@reegnz We agree that the security
approach is a bit flawed and could be improved, but is better than plaintext files. We also decided that we do not have the bandwidth at the moment to use a library that requires CGO
. Our release process would need a major overhaul to support this library and we are trying to address this security concern in a timely manner as it has been outstanding since the start of this project. We hope that in the future we can improve our implementation and use the native API's instead as you suggested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, most important thing is awareness that there's some points of improvement that could/should be made at a future date.
This comment was marked as spam.
This comment was marked as spam.
Closing in favor of #7043 |
"fmt" | ||
|
||
"github.com/MakeNowJust/heredoc" | ||
"github.com/cli/cli/v2/internal/config" | ||
"github.com/cli/cli/v2/pkg/cmdutil" | ||
"github.com/cli/cli/v2/pkg/iostreams" | ||
ghConfig "github.com/cli/go-gh/pkg/config" | ||
"github.com/spf13/cobra" | ||
) |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Switch from github.com/zalando/go-keyring to github.com/99designs/keyring that uses native bindings on macOS and Windows. Originally suggested in cli#7023 (comment) Fixes cli#7123
Switch from github.com/zalando/go-keyring to github.com/99designs/keyring that uses native bindings on macOS and Windows. On darwin, github.com/zalando/go-keyring encodes secret data in hex or base64, adding a prefix indicating that. If new library returns this prefix, convert the secret to plain data to keep using existing token and not require reauthentication. Originally suggested in cli#7023 (comment) Fixes cli#7123
Switch from github.com/zalando/go-keyring to github.com/99designs/keyring that uses native bindings on macOS and Windows. On darwin, github.com/zalando/go-keyring encodes secret data in hex or base64, adding a prefix indicating that. If new library returns this prefix, convert the secret to plain data to keep using existing token and not require reauthentication. Originally suggested in cli#7023 (comment) Fixes cli#7123
Switch from github.com/zalando/go-keyring to github.com/99designs/keyring that uses native bindings on macOS and Windows. On darwin, github.com/zalando/go-keyring encodes secret data in hex or base64, adding a prefix indicating that. If new library returns this prefix, convert the secret to plain data to keep using existing token and not require reauthentication. Originally suggested in cli#7023 (comment) Fixes cli#7123
Switch from github.com/zalando/go-keyring to github.com/99designs/keyring that uses native bindings on macOS and Windows. On darwin, github.com/zalando/go-keyring encodes secret data in hex or base64, adding a prefix indicating that. If new library returns this prefix, convert the secret to plain data to keep using existing token and not require reauthentication. Originally suggested in cli#7023 (comment) Fixes cli#7123
This isn't *great*, but it does significantly improve local developer ergonomics. Prior to this change, things worked just fine (WRT the keychain parts), but the ergonomics kinda sucked. This is because, by default, only the application that writes the keychain entry is allowed to read from it. So what would happen during development is that you'd compile, go through the oauth device flow then realize you have to fix some bug, fix the bug, then try to run the application again: 💥 macOS password prompt. The changes here in this commit work around the issue by using `security` (the macOS built-in CLI for handling this stuff). That results in the keychain entry always being read/written by a stable binary so debug builds/re-builds don't have issue. The downside here, is that "anyone" that can execute `security` can read the password. For what it's worth, this is exactly what `gh` does. See some references below: - cli/cli#7043 - https://github.com/zalando/go-keyring - cli/cli#7123 - cli/cli#7023 (comment)
Switch from github.com/zalando/go-keyring to github.com/99designs/keyring that uses native bindings on macOS and Windows. On darwin, github.com/zalando/go-keyring encodes secret data in hex or base64, adding a prefix indicating that. If new library returns this prefix, convert the secret to plain data to keep using existing token and not require reauthentication. Originally suggested in cli#7023 (comment) Fixes cli#7123
Switch from github.com/zalando/go-keyring to github.com/99designs/keyring that uses native bindings on macOS and Windows. On darwin, github.com/zalando/go-keyring encodes secret data in hex or base64, adding a prefix indicating that. If new library returns this prefix, convert the secret to plain data to keep using existing token and not require reauthentication. Originally suggested in cli#7023 (comment) Fixes cli#7123
Previously, upon completing
gh auth login
, GitHub CLI was storing the GitHub API authentication token in its~/.config/gh/hosts.yml
file:This introduces a change where the token is stored in the system keyring (encrypted storage) instead:
I've chosen the zalando/go-keyring library for this because it's pure Go, i.e. does not require cgo to be enabled. Currently we disable cgo in our precompiled binaries to increase portability.
If none of the storage providers were found, or the store operation failed, the token will be written to the config file as before to ensure as little disruption to our users as possible should something go wrong with the new approach.
After this change, after completing
gh auth login
orgh auth refresh
, the config file will look like this:Note the omission of the
oauth_token
key. Instead, the key is saved in encrypted storage. Note that depending on the OS and circumstances, gh communicating with encrypted store might spawn a system dialog to approve access. The recommended setting is to “always allow”.Those who use environment variables (e.g. GH_TOKEN) to authenticate gh will not be affected, as in the case of environment variables, the token is neither read nor stored in the config file.
oauth_token
key will not be found anymore.Fixes #449
Depends on cli/go-gh#107