Claude Code Permissions: Where CRM Tokens End Up - Relaticle         

Claude Code permissions: where your CRM token ends up
=====================================================

Claude Code permissions can save a secret in plain text. We tested where a CRM token lands, and why OAuth keeps it out of your config files.

 Manuk Minasyan · November 9, 2026 · 7 min read

 ![Claude Code permissions: where your CRM token ends up](https://relaticle.com/storage/ink/01M707289GAN3VEKBCWTPM5R5V.png) 

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.

[](#what-apiiro-found "Permalink")What Apiiro found
---------------------------------------------------

Apiiro 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.

The 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.

Claude 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.

Boris 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.

[](#what-we-tested "Permalink")What we tested
---------------------------------------------

We 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.

| Scenario | What Claude Code saved | Where |
|---|---|---|
| MCP read approval | `mcp__crm__list-companies-tool` | `.claude/settings.local.json` |
| Token read from `.env`, used in curl | Nothing (no "don't ask again" option offered) | Nothing written |
| Token pasted into the chat, then inlined in curl | `Bash(curl *)` | `.claude/settings.local.json` |
| Database password in a command | `Bash(PGPASSWORD=Fake-Pw-4417-crm psql *)` | `.claude/settings.local.json` |
| Auto mode database password command | No rule | No `.claude/settings.local.json` write |

An 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."

A 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.

The 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.

[](#your-claude-code-mcp-config-can-hold-the-token "Permalink")Your Claude Code MCP config can hold the token
-------------------------------------------------------------------------------------------------------------

Our [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:

```
claude mcp add relaticle --transport http https://crm.example.com/mcp --header "Authorization: Bearer YOUR_TOKEN"

```

Default local scope stored our token in plain text in `~/.claude.json`, outside the repository. Project scope changed the exposure:

```
claude mcp add relaticle --scope project --transport http https://crm.example.com/mcp --header "Authorization: Bearer YOUR_TOKEN"

```

That 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.

Use an environment-variable reference if a personal token remains necessary:

```
claude mcp add relaticle --scope project --transport http https://crm.example.com/mcp --header 'Authorization: Bearer ${RELATICLE_TOKEN}'

```

The `.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.

[](#auto-mode-changes-the-picture "Permalink")Auto mode changes the picture
---------------------------------------------------------------------------

Since 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.

Its [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."

In 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.

[](#connect-the-crm-with-oauth-instead "Permalink")Connect the CRM with OAuth instead
-------------------------------------------------------------------------------------

Relaticle'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:

```
claude mcp add relaticle --transport http https://crm.example.com/mcp
claude mcp login relaticle

```

You 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.

Claude 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.

Relaticle 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.

![The AI Connectors list in Relaticle settings, showing Claude Code (relaticle) connected to the Acme Sales workspace with one active token and a revoke control](https://relaticle.com/storage/ink/01M70728SZ6DBEC0C7W6Q42QZV.png)

The [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.

[](#a-short-checklist "Permalink")A short checklist
---------------------------------------------------

1. Start a reporting workflow with a read-only personal access token.
2. Keep bearer tokens out of project configuration and shell permission rules.
3. Use `${RELATICLE_TOKEN}` when a personal token remains necessary.
4. Check `git status` after adding project-scoped MCP configuration.
5. Add `.claude/settings.local.json` and `.mcp.json` with literal tokens to the repository's own `.gitignore`.
6. Read the rule a "don't ask again" option names before you pick it. `curl *` allows every curl.
7. Open `.claude/settings.local.json`, delete any rule holding a password or token, and rotate that secret.
8. Connect Claude Code to the CRM through OAuth.
9. Revoke unused connectors under Settings, Access Tokens, AI Connectors.

> A 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.
> 
> *Manuk Minasyan, founder of Relaticle*

[](#related-reading "Permalink")Related reading
-----------------------------------------------

- [Set CRM permissions before connecting an agent](https://relaticle.com/blog/crm-ai-permissions-before-connecting-an-agent)
- [Run a sales pipeline session with Claude Code](https://relaticle.com/blog/let-claude-code-run-your-sales-pipeline)
- [Connect Claude to your CRM with MCP](https://relaticle.com/blog/how-to-connect-claude-to-your-crm-with-mcp)
- [Secure a self-hosted CRM through backups and upgrades](https://relaticle.com/blog/backups-upgrades-and-security-for-a-self-hosted-crm)

 Tagged [ #mcp ](https://relaticle.com/blog/tag/mcp) 

 On this page

 Keep reading

 Related posts. 
----------------

- [  Nov 6, 2026  Guides 

    ###  CRM implementation plan for a small team 

    A CRM implementation plan for small teams, with a copyable cutover checklist, a completed example, and clear rules for late changes and recovery.

     ![](https://relaticle.com/storage/ink/01M38HWYT62PSAG65D9EFWYAXA.png) 

     ](https://relaticle.com/blog/small-team-crm-rollout-plan)
- [  Nov 3, 2026  Guides 

    ###  CRM data cleansing: a checklist before migration 

    Use this CRM data cleansing checklist to review duplicates, keep the right values, assign owners, and preserve relationships before migration.

     ![](https://relaticle.com/storage/ink/01M38HCR6VHYECX10S1TNTZN3P.png) 

     ](https://relaticle.com/blog/crm-data-cleanup-before-migration)
- [  Oct 30, 2026  Guides 

    ###  How to design CRM custom fields your team will use 

    Design CRM custom fields with a field dictionary, clear empty values, and worked examples you can test across forms, imports, and APIs.

     ![](https://relaticle.com/storage/ink/01M34D9JFP41HRBX4Z79ZZRBT7.png) 

     ](https://relaticle.com/blog/design-crm-custom-fields-your-team-will-use)
