Skip to content

[Security][Low] Harden local credential-at-rest handling (plaintext tokens, TOCTOU perms, unvalidated bearer target) #33

Description

@data-wamf

Severity: Low · Category: Credential-at-rest / hardening
Assessed at: main head 673a32d9699e869be910ed1caa3cef3aa87d94ce (read-only security health-check, 2026-07-29)

Summary

slack_cli is well-hardened overall — GitHub Actions are SHA-pinned with least-privilege permissions: contents: read (resolving closed #24/#25/#26), and no secrets are committed (.env.example is an empty template, .env is gitignored). The items below are Low-severity hardening opportunities in local credential handling; filing one consolidated issue rather than several.

Findings (all Low, confirmed)

  1. Plaintext token storage. OAuth access token (xoxp-…) and Socket Mode app token (xapp-…) are written unencrypted to ~/.dart_slack/:
    • lib/src/auth/credentials_store.dart:37-40
    • lib/src/auth/app_config_store.dart:47-51
      Standard for CLIs but no OS-keychain integration.
  2. File permissions applied after write (TOCTOU) and not on Windows. _setFilePermissions() runs chmod 600 only on macOS/Linux and only after the file is created with the default umask:
    • lib/src/auth/credentials_store.dart:59-63, lib/src/auth/app_config_store.dart:68-72, lib/src/auth/oauth_flow.dart:174-179 (TLS key/cert).
      Brief world/group-readable window; on Windows no restriction is applied.
  3. Bearer token forwarded to API-supplied URLs without host validation. lib/src/slack_api/slack_api_client.dart:307-313 attaches Authorization: Bearer to whatever url_private_download URL the API returned; lib/src/socket_mode/socket_mode_client.dart:690 connects to the API-supplied WS URL. Low (relies on authenticated TLS Slack responses).

Minor (informational): command_runner.dart:1026-1028 prints full stack traces to stderr on parse errors (gate behind --verbose); credentials_store.dart:17-19 interpolates HOME without the resilient fallback used by AppConfigStore; .gitignore ignores pubspec.lock (commit it for reproducible builds of an executable package).

Remediation

  • Create credential/key files atomically with mode 0600 (temp-file + rename) and apply an equivalent ACL on Windows.
  • Optionally integrate an OS keyring (Keychain / libsecret / Windows Credential Manager).
  • Validate API-returned URL hosts against a Slack-domain allowlist before attaching the bearer token.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions