heroku-cli-command icon indicating copy to clipboard operation
heroku-cli-command copied to clipboard

fix(W-18094367): remove support for .netrc files

Open justinwilaby opened this issue 8 months ago • 4 comments

W-18094367

Remove .netrc support in favor of modern encryption and OS-level key stores

This PR modernizes credential storage by removing .netrc file support and implementing secure credential storage using OS-level key stores and encryption.

OS-Specific Keystore Implementation

The CLI now uses the following secure credential storage mechanisms:

  • macOS: Keychain Access
  • Windows: Windows Credential Manager
  • Linux: libsecret (GNOME Keyring/KWallet)
    • Requires libsecret library to be installed
    • For Debian/Ubuntu: sudo apt-get install libsecret-1-dev
    • For Red Hat/Fedora: sudo yum install libsecret-devel
    • For Arch Linux: sudo pacman -S libsecret

Breaking Changes

  1. No longer writes or reads token data from .netrc files

    • Any ancillary uses of the .netrc file will no longer contain Heroku credentials
    • Applications depending on Heroku credentials contained in the .netrc will need to be updated
    • The Netrc machines for 'api.heroku.com' and 'git.heroku.com' are explicitly removed - any existing .netrc files containing Heroku credentials will be permanently removed.
  2. Token storage implementation changes

    • New dependencies on file encryption and OS keystore. These are OS-level dependencies and are described below.
    • Token retrieval now uses retrieveToken() and getConfigContents()
    • Applications directly accessing token storage need to be updated to use new methods
    • *Applications using code patterns like Authorization: bearer ${this.heroku.auth} can safely continue to do so.

System Requirements

  • Linux Users:

    • Must have libsecret installed and a running keyring daemon (GNOME Keyring or KWallet)
    • Without libsecret, the Heroku CLI will fail to store credentials securely and alternative auth methods such as the HEROKU_API_KEY env var must be used
    • Desktop environments like GNOME and KDE include the above listed utils by default
  • macOS Users:

    • No additional requirements
    • Uses the built-in Keychain Access
  • Windows Users:

    • No additional requirements
    • Uses the built-in Windows Credential Manager

Testing Instructions

  1. Build the package:
    npm run build
    npm pack
    
  2. install this by file path
  3. fix above mentioned breaking changes in code and unit tests if applicable
  4. test your CLI

justinwilaby avatar Mar 22 '25 21:03 justinwilaby

I think using the credential storage makes sense but there is a minimal change in security posture: A local user who can read the .netrc file will also be able to execute heroku auth:token.

@tt - Exactly. This was an area of consideration for me as well. I understand the best practice to be:

  1. Generate a token and display it once and only once
  2. Regular Auth flows never display the token
  3. If a token is not securely saved by the user, it is lost and the user must generate a new one.

Thoughts?

justinwilaby avatar Apr 14 '25 16:04 justinwilaby

  1. Generate a token and display it once and only once
  2. Regular Auth flows never display the token
  3. If a token is not securely saved by the user, it is lost and the user must generate a new one.

Thoughts?

I think we should definitely implement these but it still doesn't change the fact that any user who can invoke the CLI can exfiltrate a token.

We could make heroku auth:token require explicit consent similar to when you sign in but that wouldn't prevent you from getting the token that the CLI itself is using. As long as you can run a plug-in, this.heroku.auth could be read and exposed. Even if we block that by, say, only exposing a way to issue API requests, a plug-in could communicate with the credential store directly because it's running inside the CLI process.

I'm not saying this because we shouldn't more in the direction of adopting better platform primitives. I only want us to recognize that we're making it more complicated to receive the plaintext token but not impossible.

tt avatar Apr 23 '25 09:04 tt

Do the "secure credential storage mechanisms" implemented by this change (Keychain Access, Windows Credential Manager, libsecret) prompt the user for a local password or biometric authentication, before saving or reading a credential?

mars avatar Apr 23 '25 17:04 mars

Do the "secure credential storage mechanisms" implemented by this change (Keychain Access, Windows Credential Manager, libsecret) prompt the user for a local password or biometric authentication, before saving or reading a credential?

Not in any of the tests I performed. AFAIK, these tools are intended to be used in this way and shouldn't need explicit input from the user.

justinwilaby avatar May 05 '25 14:05 justinwilaby