fix(slack): warn when slack_tokens.json is group/world-readable - #60009
Closed
AlexFucuson9 wants to merge 1 commit into
Closed
fix(slack): warn when slack_tokens.json is group/world-readable#60009AlexFucuson9 wants to merge 1 commit into
AlexFucuson9 wants to merge 1 commit into
Conversation
The OAuth multi-workspace token file contains plaintext bot tokens for all saved Slack workspaces. Unlike the Google Chat adapter which sets 0o600 when writing credentials, the Slack token file has no permission enforcement — a default umask 022 makes it world-readable. Fix: check file permissions on read and emit a warning log with remediation instructions if the file is group- or world-readable.
Contributor
|
Thanks for the focused Slack credential-hardening change. The current loader reads Problems
Suggested changes
This is an automated hermes-sweeper review. |
teknium1
added a commit
that referenced
this pull request
Jul 23, 2026
…ds, widen token-file perms warning Follow-up hardening on top of the C14 cherry-picks (#57860/#44026/#66742/#60009): - Slack file downloads (_download_slack_file/_download_slack_file_bytes) now require an https URL on a Slack CDN host (files.slack.com, *.slack.com Enterprise Grid, *.slack-files.com legacy shares) before attaching the bot token. url_private/url_private_download only ever point at the Slack CDN, so a forged file object from a malicious workspace app or compromised event stream pointing the Bearer-token download at an arbitrary PUBLIC host (token exfiltration) is now refused — a hole #44026's generic private-IP SSRF check alone could not close. - The same two download paths now use create_ssrf_safe_async_client (from #57860) so the preflight-validated hostname is resolved once, validated, and dialed by IP — closing the DNS-rebinding TOCTOU window for the token-bearing inbound fetches as well. - #60009's slack_tokens.json permission warning is generalized into utils.warn_if_credential_file_broadly_readable() (POSIX-only, fail-quiet) and wired into the other read path with the same gap: google_chat's load_user_credentials(). google_chat already writes 0o600 via _write_private_json; the read-time warning covers hand-provisioned/legacy files. Nothing in-repo writes slack_tokens.json (user/OAuth-provisioned), so there is no write path to chmod for Slack. Security tests both directions: non-CDN/lookalike/http URLs and connect-time DNS rebinds are blocked before any TCP connect; real files.slack.com, Enterprise Grid, and slack-files.com URLs still reach the network layer; 0o600 files stay silent while 0o644/0o640 warn with a chmod hint. A/B: all 10 new download-guard tests fail with the hardening reverted and pass with it applied.
teknium1
added a commit
that referenced
this pull request
Jul 23, 2026
…ds, widen token-file perms warning Follow-up hardening on top of the C14 cherry-picks (#57860/#44026/#66742/#60009): - Slack file downloads (_download_slack_file/_download_slack_file_bytes) now require an https URL on a Slack CDN host (files.slack.com, *.slack.com Enterprise Grid, *.slack-files.com legacy shares) before attaching the bot token. url_private/url_private_download only ever point at the Slack CDN, so a forged file object from a malicious workspace app or compromised event stream pointing the Bearer-token download at an arbitrary PUBLIC host (token exfiltration) is now refused — a hole #44026's generic private-IP SSRF check alone could not close. - The same two download paths now use create_ssrf_safe_async_client (from #57860) so the preflight-validated hostname is resolved once, validated, and dialed by IP — closing the DNS-rebinding TOCTOU window for the token-bearing inbound fetches as well. - #60009's slack_tokens.json permission warning is generalized into utils.warn_if_credential_file_broadly_readable() (POSIX-only, fail-quiet) and wired into the other read path with the same gap: google_chat's load_user_credentials(). google_chat already writes 0o600 via _write_private_json; the read-time warning covers hand-provisioned/legacy files. Nothing in-repo writes slack_tokens.json (user/OAuth-provisioned), so there is no write path to chmod for Slack. Security tests both directions: non-CDN/lookalike/http URLs and connect-time DNS rebinds are blocked before any TCP connect; real files.slack.com, Enterprise Grid, and slack-files.com URLs still reach the network layer; 0o600 files stay silent while 0o644/0o640 warn with a chmod hint. A/B: all 10 new download-guard tests fail with the hardening reverted and pass with it applied.
Contributor
|
Merged via #70193 — your commit was cherry-picked/reapplied onto current main with your authorship preserved in git history: your token-file permission warning was cherry-picked and widened to chmod-on-write for the file class. Thanks for the contribution! |
randlee
pushed a commit
to randlee/hermes-agent
that referenced
this pull request
Aug 11, 2026
…ds, widen token-file perms warning Follow-up hardening on top of the C14 cherry-picks (NousResearch#57860/NousResearch#44026/NousResearch#66742/NousResearch#60009): - Slack file downloads (_download_slack_file/_download_slack_file_bytes) now require an https URL on a Slack CDN host (files.slack.com, *.slack.com Enterprise Grid, *.slack-files.com legacy shares) before attaching the bot token. url_private/url_private_download only ever point at the Slack CDN, so a forged file object from a malicious workspace app or compromised event stream pointing the Bearer-token download at an arbitrary PUBLIC host (token exfiltration) is now refused — a hole NousResearch#44026's generic private-IP SSRF check alone could not close. - The same two download paths now use create_ssrf_safe_async_client (from NousResearch#57860) so the preflight-validated hostname is resolved once, validated, and dialed by IP — closing the DNS-rebinding TOCTOU window for the token-bearing inbound fetches as well. - NousResearch#60009's slack_tokens.json permission warning is generalized into utils.warn_if_credential_file_broadly_readable() (POSIX-only, fail-quiet) and wired into the other read path with the same gap: google_chat's load_user_credentials(). google_chat already writes 0o600 via _write_private_json; the read-time warning covers hand-provisioned/legacy files. Nothing in-repo writes slack_tokens.json (user/OAuth-provisioned), so there is no write path to chmod for Slack. Security tests both directions: non-CDN/lookalike/http URLs and connect-time DNS rebinds are blocked before any TCP connect; real files.slack.com, Enterprise Grid, and slack-files.com URLs still reach the network layer; 0o600 files stay silent while 0o644/0o640 warn with a chmod hint. A/B: all 10 new download-guard tests fail with the hardening reverted and pass with it applied.
prmartinow
pushed a commit
to prmartinow/hermes-agent
that referenced
this pull request
Aug 26, 2026
…ds, widen token-file perms warning Follow-up hardening on top of the C14 cherry-picks (NousResearch#57860/NousResearch#44026/NousResearch#66742/NousResearch#60009): - Slack file downloads (_download_slack_file/_download_slack_file_bytes) now require an https URL on a Slack CDN host (files.slack.com, *.slack.com Enterprise Grid, *.slack-files.com legacy shares) before attaching the bot token. url_private/url_private_download only ever point at the Slack CDN, so a forged file object from a malicious workspace app or compromised event stream pointing the Bearer-token download at an arbitrary PUBLIC host (token exfiltration) is now refused — a hole NousResearch#44026's generic private-IP SSRF check alone could not close. - The same two download paths now use create_ssrf_safe_async_client (from NousResearch#57860) so the preflight-validated hostname is resolved once, validated, and dialed by IP — closing the DNS-rebinding TOCTOU window for the token-bearing inbound fetches as well. - NousResearch#60009's slack_tokens.json permission warning is generalized into utils.warn_if_credential_file_broadly_readable() (POSIX-only, fail-quiet) and wired into the other read path with the same gap: google_chat's load_user_credentials(). google_chat already writes 0o600 via _write_private_json; the read-time warning covers hand-provisioned/legacy files. Nothing in-repo writes slack_tokens.json (user/OAuth-provisioned), so there is no write path to chmod for Slack. Security tests both directions: non-CDN/lookalike/http URLs and connect-time DNS rebinds are blocked before any TCP connect; real files.slack.com, Enterprise Grid, and slack-files.com URLs still reach the network layer; 0o600 files stay silent while 0o644/0o640 warn with a chmod hint. A/B: all 10 new download-guard tests fail with the hardening reverted and pass with it applied.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Warn at startup when
slack_tokens.jsonis group- or world-readable.Problem
plugins/platforms/slack/adapter.py:985— the OAuth multi-workspace token file contains plaintext bot tokens for all saved Slack workspaces. Unlike the Google Chat adapter (google_chat/oauth.py:329) which explicitly sets0o600permissions when writing credential files, the Slack token file has no permission enforcement. With a default umask of022, the file is world-readable, exposing all saved workspace tokens to any local user.Fix
Check file permissions when reading
slack_tokens.json. If the file is group-readable (S_IRGRP) or world-readable (S_IROTH), emit alogger.warningwith the current mode and remediation command (chmod 600).This follows the defense-in-depth pattern: don't refuse to load (that would break existing setups), but make the misconfiguration visible so operators can fix it.
Testing
1-file change. The warning is a log-only side effect that doesn't affect existing functionality.