{"slug": "claude-code-permissions-where-your-crm-token-ends-up", "title": "Claude Code permissions: where your CRM token ends up", "summary": "Apiiro reported on November 5, 2026, that it found 104,185 public copies of Claude Code's `.claude/settings.local.json` on GitHub, of which 1,122 held a real secret, and 2,539 distinct secrets across 1,994 repositories when file history, shared settings files and agent transcripts were counted. Relaticle's own test of Claude Code v2.1.319 with Sonnet 5.5, run November 9, 2026, against its MCP server found that approving a pasted-token curl command saved the broad rule `Bash(curl *)` and that a database password typed into a command was stored in plain text in the allow list, while an OAuth connection kept the CRM token out of Claude Code's config files. Boris Cherny of the Claude Code team wrote on Hacker News on November 7 that \"Historically Claude Code has not done secret scrubbing (there are many good tools for that), but we are looking into what we can do to prevent this,\" naming auto-mode detection and basic secret scanning as approaches to prototype.", "body_md": "Claude Code permissions decide which commands run without asking. Picking \"Yes, and don't ask again\" writes a rule to `.claude/settings.local.json`, and some rules carry the secret itself. For a CRM connection, the MCP config can hold the token. In our test, connecting over OAuth kept the token out of Claude Code's config files. We tested all of it against Relaticle's MCP server on November 9, 2026.\n\n## \n\nApiiro published its findings on November 5, 2026. It updated them on November 8. It found 104,185 public copies of `.claude/settings.local.json` on GitHub. Of those, 1,122 held a real secret. Counting file history, shared settings files and agent transcripts, it found 2,539 distinct secrets in 1,994 repositories.\n\nThe failure starts with a familiar choice. For Bash, \"Yes, and don't ask again\" stores a command rule in `.claude/settings.local.json` at the git repository root. The saved command can include a secret. Apiiro also found that common secret scanners missed passwords inside commands, including bearer headers in curl calls.\n\nClaude Code adds the file to the developer's global git ignore when it creates it inside a repository. Apiiro notes that this misses a clone on another machine and a file someone already committed. The repository's own `.gitignore` gets no entry. That matched our test: our global ignore covered the file, and the repository's `.gitignore` did not.\n\nBoris Cherny of the Claude Code team [replied on Hacker News](https://news.ycombinator.com/item?id=50408126) on November 7. He wrote: \"Historically Claude Code has not done secret scrubbing (there are many good tools for that), but we are looking into what we can do to prevent this.\" In a [follow-up comment](https://news.ycombinator.com/item?id=50408176), he named two approaches to prototype. One makes sure auto mode catches this, and the other is basic secret scanning. Read the [Apiiro post](https://apiiro.com/blog/coding-agents-leaking-secrets-github-dont-ask-again) for its repository-level remediation advice.\n\n## \n\nWe tested Claude Code v2.1.319 with Sonnet 5.5, in Manual mode plus one run in auto mode. That version shipped on November 6, 2026. We used a local Relaticle build, a throwaway git repository, and a read-only token. We deleted the token after the test.\n\n| Scenario | What Claude Code saved | Where | \n|---|---|---|\n| MCP read approval | `mcp__crm__list-companies-tool` | `.claude/settings.local.json` | \n| Token read from `.env` , used in curl | Nothing (no \"don't ask again\" option offered) | Nothing written | \n| Token pasted into the chat, then inlined in curl | `Bash(curl *)` | `.claude/settings.local.json` | \n| Database password in a command | `Bash(PGPASSWORD=Fake-Pw-4417-crm psql *)` | `.claude/settings.local.json` | \n| Auto mode database password command | No rule | No `.claude/settings.local.json` write | \n\nAn MCP tool approval saved a tool name, not a secret. With the token in a gitignored `.env` file, Claude Code referenced `$RELATICLE_TOKEN` instead of the value. The prompt then offered only a one-time yes: \"A variable in this command can't be checked before it runs.\"\n\nA CRM token pasted into the chat was not saved on this version. The resulting rule was still `Bash(curl *)`. Every curl command in that repository now runs without another prompt. Apiiro published on November 5, a day before v2.1.319 shipped. We cannot tell from our runs whether the behavior changed or the command shape differed.\n\nThe database case matters for self-hosters. Claude Code saved an environment-prefixed password in plain text in the allow list. `Fake-Pw-4417-crm` is a fake password we typed for the test, but a real one would sit there the same way.\n\n## \n\nOur [MCP connection guide](https://relaticle.com/blog/how-to-connect-claude-to-your-crm-with-mcp) and our [Claude Code pipeline session](https://relaticle.com/blog/let-claude-code-run-your-sales-pipeline) connected Claude Code with a personal access token in a header:\n\n```\nclaude mcp add relaticle --transport http https://crm.example.com/mcp --header \"Authorization: Bearer YOUR_TOKEN\"\n```\n\nDefault local scope stored our token in plain text in `~/.claude.json`, outside the repository. Project scope changed the exposure:\n\n```\nclaude mcp add relaticle --scope project --transport http https://crm.example.com/mcp --header \"Authorization: Bearer YOUR_TOKEN\"\n```\n\nThat command wrote `.mcp.json` at the repository root, with the token inside. Git listed it as untracked and not ignored. A `git add .` would stage it. The [Claude Code MCP documentation](https://code.claude.com/docs/en/mcp) describes project scope as shared with the team through version control.\n\nUse an environment-variable reference if a personal token remains necessary:\n\n```\nclaude mcp add relaticle --scope project --transport http https://crm.example.com/mcp --header 'Authorization: Bearer ${RELATICLE_TOKEN}'\n```\n\nThe `.mcp.json` file then holds the placeholder, not the token. Without the variable, `claude mcp list` warned: `Missing environment variables: RELATICLE_TOKEN`. This still leaves the machine and its environment responsible for the secret.\n\n## \n\nSince v2.1.283, released September 25, 2026, auto mode is the starting mode for interactive terminal and VS Code sessions. That holds on every plan and provider. A separate classifier model reviews actions before they run, instead of asking you. `claude -p` runs still start in Manual mode, and so does anyone who switches back to it.\n\nIts [permission-mode documentation](https://code.claude.com/docs/en/permission-modes) says auto mode blocks \"Printing a live credential or token into the transcript or a file.\" It allows \"Reading .env and sending credentials to their matching API.\" The same page says, \"Auto mode reduces permission prompts but does not guarantee safety.\"\n\nIn our test, auto mode ran the same database command without a prompt and wrote no allow rule. That avoided storing the password. The password was still typed into a command line.\n\n## \n\nRelaticle's MCP server supports OAuth with dynamic client registration. Claude Code uses it. That makes OAuth the better route for Claude Code than the header command above:\n\n```\nclaude mcp add relaticle --transport http https://crm.example.com/mcp\nclaude mcp login relaticle\n```\n\nYou can also run `/mcp` inside a session. On Relaticle's consent screen, you pick one workspace. The list of what Claude Code may do follows your role there. Afterwards the entry in `~/.claude.json` held only the transport type and the URL.\n\nClaude Code's documentation says it stores OAuth tokens securely and refreshes them automatically. Removing the server in Claude Code deletes its stored tokens but does not revoke them at the issuer. Revoke the connector in Relaticle to end its access.\n\nRelaticle OAuth access tokens last 30 days. Refresh tokens last 90 days. Revoke the connector under Settings, Access Tokens, AI Connectors. After revocation, Claude Code showed `Needs authentication` in our test.\n\nThe [MCP guide's OAuth section](https://relaticle.com/developers/mcp#oauth-21-recommended-for-end-users) covers the connection flow. MCP writes apply immediately in Relaticle. Any confirmation comes from Claude Code's own permissions. Rela, the built-in AI assistant, asks before it writes, but that approval does not cover MCP writes.\n\n## \n\n1. Start a reporting workflow with a read-only personal access token.\n2. Keep bearer tokens out of project configuration and shell permission rules.\n3. Use `${RELATICLE_TOKEN}` when a personal token remains necessary.\n4. Check `git status` after adding project-scoped MCP configuration.\n5. Add `.claude/settings.local.json` and`.mcp.json` with literal tokens to the repository's own`.gitignore` .\n6. Read the rule a \"don't ask again\" option names before you pick it. `curl *` allows every curl.\n7. Open `.claude/settings.local.json` , delete any rule holding a password or token, and rotate that secret.\n8. Connect Claude Code to the CRM through OAuth.\n9. Revoke unused connectors under Settings, Access Tokens, AI Connectors.\n\nA permission prompt asks you to judge a command in the second you least want to. I would rather a CRM connection never put the token in front of that judgment at all.\n\n*Manuk Minasyan, founder of Relaticle*\n\n## \n\n[#mcp](https://relaticle.com/blog/tag/mcp)", "url": "https://wpnews.pro/news/claude-code-permissions-where-your-crm-token-ends-up", "canonical_source": "https://relaticle.com/blog/claude-code-permissions-where-your-crm-token-ends-up", "published_at": "2026-11-09 13:30:00+00:00", "updated_at": "2026-11-09 13:53:23.873559+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "ai-safety", "developer-tools"], "entities": ["Apiiro", "Claude Code", "Anthropic", "Boris Cherny", "Relaticle", "GitHub", "Sonnet 5.5", "Hacker News"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/claude-code-permissions-where-your-crm-token-ends-up", "markdown": "https://wpnews.pro/news/claude-code-permissions-where-your-crm-token-ends-up.md", "text": "https://wpnews.pro/news/claude-code-permissions-where-your-crm-token-ends-up.txt", "jsonld": "https://wpnews.pro/news/claude-code-permissions-where-your-crm-token-ends-up.jsonld"}}