Skip to content

fix(config): refuse to write secret keys to git-tracked config.yaml#3652

Merged
maphew merged 3 commits into
gastownhall:mainfrom
kevglynn:fix/refuse-git-tracked-secrets
May 2, 2026
Merged

fix(config): refuse to write secret keys to git-tracked config.yaml#3652
maphew merged 3 commits into
gastownhall:mainfrom
kevglynn:fix/refuse-git-tracked-secrets

Conversation

@kevglynn

@kevglynn kevglynn commented May 2, 2026

Copy link
Copy Markdown
Contributor

Summary

P0 security fix. bd config set for secret keys (api_key, secret, token, password) now detects whether the target config.yaml is tracked by git and refuses the write with an actionable error message.

This addresses the verified credential-leak-on-default-path: the documented setup (bd config set linear.api_key ...) writes to .beads/config.yaml which is git-tracked by default, leaking Linear API keys into git history.

Changes

  • internal/config/yaml_config.go — Added IsSecretKey, isGitTracked, CheckSecretKeyGitSafety functions. Secret key detection uses substring matching against api_key, secret, token, password. Git tracking detection uses git ls-files --error-unmatch.
  • cmd/bd/config.go — Wired the safety check into config set and config set-many. Added --force-git-tracked escape hatch flag.
  • cmd/bd/init_templates.go — Fixed stale comment that incorrectly claimed secrets are "stored in the database" — now documents they're in config.yaml and recommends env vars.
  • examples/linear-workflow/README.md — Replaced bd config set linear.api_key with export LINEAR_API_KEY=...
  • docs/CONFIG.md — Linear setup section now leads with env var approach.

Test plan

  • 3 new tests: refuses git-tracked secret write, allows untracked config, allows non-secret keys on tracked config
  • Full internal/config test suite passes (0 regressions)
  • go vet clean
  • --force-git-tracked escape hatch works for test environments

Backward compatibility

  • Existing configurations are read unchanged; only writes are gated
  • Non-secret config keys (linear.team_ids, linear.priority_map.*, etc.) are unaffected
  • --force-git-tracked provides an opt-out for CI/test environments

Charter compliance

Security hygiene of an existing flow. No new features, no new config surface beyond the --force-git-tracked flag.

Related


View in Codesmith
Need help on this PR? Tag @codesmith with what you need.

  • Let Codesmith autofix CI failures and bot reviews

P0 security fix. bd config set for secret keys (api_key, secret, token,
password) now detects git tracking of the target config file and refuses
the write with an actionable error pointing to env var alternatives.

Adds --force-git-tracked escape hatch for tests. Updates stale template
documentation and setup guides to lead with env var approach.
@codecov-commenter

codecov-commenter commented May 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 77.77778% with 14 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
cmd/bd/config.go 18.18% 9 Missing ⚠️
internal/config/yaml_config.go 88.63% 5 Missing ⚠️

📢 Thoughts on this report? Let us know!

@maphew maphew left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Found two issues that should be fixed before merge:

  1. cmd/bd/config.go:114: config set runs CheckSecretKeyGitSafety before checking IsYamlOnlyKey, so DB-backed secret-looking keys like notion.token are refused whenever .beads/config.yaml is tracked, even though they would not write to config.yaml. config set-many only checks yamlPairs, so the behavior is inconsistent. Move the check inside the YAML-only branch or make CheckSecretKeyGitSafety ignore non-YAML keys.

  2. internal/config/yaml_config.go:126: secretKeyEnvVarHint generates generic env vars like AI_API_KEY for ai.api_key, but the code paths that use that config read ANTHROPIC_API_KEY. For a tracked config, the remediation message can tell users to set an env var Beads does not consume. This needs either key-specific env var mapping or the message should avoid suggesting unsupported env vars.

Verification performed locally:

  • go test ./internal/config passed.
  • go test ./cmd/bd -run 'Test.*Config|Test.*Notion|Test.*Linear' could not build in this environment because ICU headers are missing: unicode/uregex.h.

Use real environment variable hints for known secret config keys and avoid blocking database-backed secret-looking keys such as notion.token.

Maintainer follow-up for PR gastownhall#3652.

@maphew maphew left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Maintainer follow-up pushed to the contributor branch in b3ab06b54 per PR_MAINTAINER_GUIDELINES.md instead of leaving this blocked on review rounds.

The follow-up addresses the two findings from my prior review:

  • Secret git-tracking safety now ignores non-YAML-backed secret-looking keys such as notion.token, avoiding the config set / config set-many inconsistency.
  • Env var remediation now uses real known env vars (LINEAR_API_KEY, GITHUB_TOKEN, ANTHROPIC_API_KEY) and falls back to BD_... for Viper-backed YAML config keys.

Local verification:

  • gofmt on touched files
  • git diff --check
  • go test ./internal/config

Full PR CI is running on the new head commit.

The map contains environment variable names, not secret values.
@maphew maphew merged commit 918eb8e into gastownhall:main May 2, 2026
39 checks passed
@maphew maphew added the triaged Issue has been reviewed and responded to label May 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

triaged Issue has been reviewed and responded to

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants