#006Observing

Claude Code silently committed my Contentful Management Token to git history through an MCP config file.

GitGuardian caught what Claude Code didn't. Here's exactly how an MCP config file caused it and what I do differently now.

I got an email at 3:16 PM from GitGuardian.

Subject: [nikakarliuchenko/fieldnotes-ai] Contentful Content Management API Key exposed on GitHub

My first reaction was that it was a scam. The repo was still private. I had run a security audit with Claude Code before going public specifically to catch things like this. We scanned for exposed tokens. Nothing came up.

It was not a scam.


What actually happened

The token was in .claude/mcp.json, a config file Claude Code creates automatically when you set up an MCP server inside a project directory.

In my case that file contained my Contentful Management API token, a CFPAT key with full read/write access to my content space. Not a read-only Delivery key. The real one.

That file lived inside the project folder. It never made it into .gitignore. At some point during normal development it got committed silently. No warning. No prompt. No flag that a file with credentials was being tracked.

The token sat in git history across multiple commits and branches. Not in the current file tree. In the history. The kind of place you don't look unless you know to look.


Why the security audit missed it

This is the part that matters.

Before making the repo public I asked Claude Code to audit it for exposed secrets. We went through the codebase. Nothing flagged.

Claude Code created the .claude/mcp.json file. Claude Code introduced the credential into the project. And then Claude Code scanned the repo and didn't find it.

I don't think this was negligence on my part. I think it's a gap that most developers using AI coding tools won't think about until it happens to them. Claude Code scanned what it thought of as the codebase, the application files. It didn't flag its own config file as a security surface.

GitGuardian scans everything. Every commit. Every branch. Every file that was ever tracked, even deleted ones. That's why it caught what Claude Code missed.


The cleanup

Once I confirmed the token was real and exposed, the steps were straightforward.

Revoke it in Contentful immediately. This is the only thing that actually matters for security. Everything else is hygiene.

Then purge it from git history using BFG Repo Cleaner. This took three passes because BFG won't touch the HEAD commit. You have to manually remove the file from the current branch first, then run BFG on a fresh clone. About 45 minutes of back and forth.

To confirm it's fully gone:

git log --all -p | grep "CFPAT-"

Empty output means clean. That's what I got.

The new token lives in ~/.claude/ at the home directory level, outside any project folder, where it will never get committed.


What I do differently now

Two things.

First, .claude/ goes into .gitignore at project creation. Not after the first commit. Before.

.claude/

.env*

!.env.example

Second, before making any repo public:

git log --all -p | grep -E "CFPAT|CTFL|sk-|ghp_|token|secret|password|api_key" -i

This searches every commit ever made including deleted files across all branches. It's the same thing GitGuardian does. It takes ten seconds. There is no reason not to run it.


The bigger pattern

AI coding tools expand the surface area of your project in ways that aren't always visible. MCP configs, cache files, tool-specific directories get created as side effects of using the tools, not as intentional choices you made. And they can contain credentials.

The mental model most developers have for "what's in my repo" doesn't include the scaffolding left behind by their tooling. That's the gap GitGuardian caught in my favor. In a worse scenario someone else would have caught it first.

Claude Code is good at a lot of things. Auditing its own footprint in your repo is not one of them. Use a separate tool for that job.

GitGuardian is free for public repos. I have no affiliation. I'm just glad it exists.