Skip to content

Add secure keyring storage for Slack token#5

Merged
alexec merged 11 commits intomainfrom
copilot/store-token-in-keyring
Oct 21, 2025
Merged

Add secure keyring storage for Slack token#5
alexec merged 11 commits intomainfrom
copilot/store-token-in-keyring

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Oct 21, 2025

Problem

The SLACK_TOKEN environment variable is visible in the process list (/proc/<pid>/environ), which poses a security risk in multi-user systems where other users can view running processes and their environment variables.

Solution

This PR adds support for storing the Slack token securely in the system keyring using zalando/go-keyring, which provides cross-platform keyring access:

  • Linux: Uses Secret Service (GNOME Keyring, KWallet)
  • macOS: Uses Keychain
  • Windows: Uses Credential Manager

Changes

New configure Command

A new slack configure command allows users to store their token securely:

# Interactive mode (password hidden)
slack configure

# Or pipe for automation
echo "xoxb-your-slack-token" | slack configure

The token is stored in the slack-cli keyring service with the name SLACK_TOKEN.

Password Hiding: When running interactively in a terminal, the token input is hidden for security. The command automatically detects if it's running in a terminal or receiving piped input, supporting both interactive and automated use cases.

Helpful Instructions: The configure command now displays helpful instructions showing users where to obtain their Slack API token, including a direct link to https://api.slack.com/apps and step-by-step guidance on creating an app and copying the Bot User OAuth Token.

Token Retrieval Priority

The token is now retrieved in the following order:

  1. SLACK_TOKEN environment variable (highest priority)
  2. Keyring (secure storage fallback) - NEW

Note: The -t flag has been removed to encourage use of the more secure keyring option while maintaining simplicity.

Security Benefits

  • Tokens in the keyring are not visible in process lists
  • Password input is hidden when typing interactively (prevents shoulder surfing and accidental exposure during demos/screenshares)
  • More secure in multi-user and shared systems
  • Credentials are encrypted at rest by the OS
  • Backward compatible with existing SLACK_TOKEN usage
  • Environment variable takes precedence for flexibility in CI/CD and automated environments

Example Usage

# Configure once (secure, interactive with hidden input and instructions)
slack configure
To get your Slack API token, visit: https://api.slack.com/apps
Create an app, install it to your workspace, and copy the Bot User OAuth Token
Enter your Slack API token: *********** (hidden)

# Or use automation (piped input still supported)
echo "xoxb-your-token" | slack configure

# Then use without exposing token in environment
slack send-message user@example.com "Hello!"

# Or continue using environment variable (backward compatible, takes precedence)
export SLACK_TOKEN="xoxb-your-token"
slack send-message user@example.com "Hello!"

Code Quality Improvements

  • Simplified code structure with configure command in switch block
  • Made internal functions private (sendMessage, configureToken)
  • Extracted getToken() helper function for cleaner token retrieval
  • Removed global api variable for better encapsulation
  • Added password hiding with golang.org/x/term for secure interactive input
  • Added user-friendly instructions for obtaining Slack API tokens

Testing

  • Added comprehensive unit tests for the configure command
  • All existing tests pass
  • go vet passes with no issues
  • CodeQL security scan: 0 vulnerabilities

Documentation

Updated README.md with configuration instructions and security notes explaining why keyring storage is preferred over environment variables in multi-user systems.

> [!WARNING]
>
>

Original prompt

I want another way to store the token. SLACK_TOKEN is not secure in multi-user systems as it is visible in the proc. Instead we should keep it in the key ring. Use zalando/go-keyring for key ring. Use the login key-ring and name the secret named SLACK_TOKEN. Add a slack configure command that accepts the token on Stdin. Store the token in the key-ring.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 3 commits October 21, 2025 18:34
Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
Copilot AI changed the title [WIP] Store SLACK_TOKEN in key ring for better security Add secure keyring storage for Slack token Oct 21, 2025
Copilot AI requested a review from alexec October 21, 2025 18:39
@alexec
Copy link
Copy Markdown
Contributor

alexec commented Oct 21, 2025

@copilot remove the "-t" option, now we have something more secure.

Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Oct 21, 2025

@copilot remove the "-t" option, now we have something more secure.

Removed the -t flag. Token now retrieved only from keyring or SLACK_TOKEN env var. (75a6153)

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • slack.com
    • Triggering command: /tmp/slack send-message test hello (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copy link
Copy Markdown
Contributor

@alexec alexec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good stuff, see also:

  • Anything you could simplify?
  • Any funcs that could be private?

Copy link
Copy Markdown
Contributor

@alexec alexec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make my requested changes in the comments.

@alexec
Copy link
Copy Markdown
Contributor

alexec commented Oct 21, 2025

@copilot make the requested changes.

Copilot AI and others added 2 commits October 21, 2025 19:58
…witch, update error message

Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
…e global api var

Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Oct 21, 2025

@copilot make the requested changes.

All requested changes implemented:

  • SLACK_TOKEN precedence (559d0e8)
  • Configure in switch block (559d0e8)
  • Error message updated (559d0e8)
  • Code simplified and functions made private (2a77e8f)

Good stuff, see also:

  • Anything you could simplify?...

Simplified code:

  • Made sendMessage and configureToken private
  • Extracted getToken() helper function
  • Removed global api variable, now passed as parameter
    (2a77e8f)

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • slack.com
    • Triggering command: /tmp/slack send-message test hello (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI requested a review from alexec October 21, 2025 20:03
@alexec
Copy link
Copy Markdown
Contributor

alexec commented Oct 21, 2025

@copilot when reading from stdin, can we hide the typed password?

Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Oct 21, 2025

@copilot when reading from stdin, can we hide the typed password?

Implemented password hiding using golang.org/x/term. When running interactively in a terminal, the password is now hidden. Still supports piped input for automation. (commit pending)

Copilot AI requested a review from alexec October 21, 2025 20:50
Co-authored-by: alexec <1142830+alexec@users.noreply.github.com>
Copilot AI requested a review from alexec October 21, 2025 21:02
@alexec alexec marked this pull request as ready for review October 21, 2025 21:22
@alexec alexec merged commit 8471c47 into main Oct 21, 2025
2 checks passed
@alexec alexec deleted the copilot/store-token-in-keyring branch October 21, 2025 21:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants