CLAUDE LABJP
PRICING — Anthropic has cancelled the September 1 increase for Claude Sonnet 5. The $2 input and $10 output per million tokens is now simply the standard price, so any forecast built on $3 and $15 needs redoingVERSION — v2.1.241, released August 23, is a fixes-and-reliability release. MCP v2 no longer reopens subscriptions/listen endlessly against servers that close long-held streams on a fixed timeoutLINUX — Idle sessions on Linux with sandboxing enabled no longer pin a CPU core at 100 percentSKILLS — Bundled skill aliases such as /checkup and /review no longer report Unknown command in -p mode or with plugins and MCP loaded when a same-named user or project skill shadows themARGS — Skill and command argument substitution no longer re-expands argument values as template markersWATERMARK — Claude products released from August 2 onward embed machine-readable marking in generated output. It answers EU AI Act transparency rules, but it is applied worldwide rather than only in EuropePRICING — Anthropic has cancelled the September 1 increase for Claude Sonnet 5. The $2 input and $10 output per million tokens is now simply the standard price, so any forecast built on $3 and $15 needs redoingVERSION — v2.1.241, released August 23, is a fixes-and-reliability release. MCP v2 no longer reopens subscriptions/listen endlessly against servers that close long-held streams on a fixed timeoutLINUX — Idle sessions on Linux with sandboxing enabled no longer pin a CPU core at 100 percentSKILLS — Bundled skill aliases such as /checkup and /review no longer report Unknown command in -p mode or with plugins and MCP loaded when a same-named user or project skill shadows themARGS — Skill and command argument substitution no longer re-expands argument values as template markersWATERMARK — Claude products released from August 2 onward embed machine-readable marking in generated output. It answers EU AI Act transparency rules, but it is applied worldwide rather than only in Europe
Articles/Cowork
Cowork/2026-08-24Intermediate

I counted the keys in my connected folder: filenames found 5 of the 18

A record of counting what lives inside a connected folder, once by filename and once by file contents. Filenames returned 24 hits of which only 5 were real, while a content scan returned 18 of which 13 left no trace in their names. Includes a scanner that never prints a secret, its real output, and the rules I adopted afterwards.

Cowork34connected foldersecret managementindie development20operations21

I was re-selecting a connected folder one morning. The dialog showed the working folder I use every day, and there was no reason to hesitate.

Then I stopped.

I could not actually say what was inside it. Four site repositories, operations documents, image assets, old backups. Add to a folder for a few years as an indie developer and this is simply what happens.

Before deciding how much to expose, I decided to count.

The short version: filenames miss about three quarters of it

Here is the result up front. The target was the same working folder I connect every day.

MethodHitsActually contained a keyMissed
Search by filename24513 files
Search by file contents1818

Searching for names containing token or secret produced 24 hits, but only 5 of them held an actual key string. The other 19 were things like article drafts about how token counting works. A check that is wrong four times out of five is a check people stop reading.

The content search produced 18 files, and 13 of those carry no hint at all in their names.

That is where "protect it by naming convention" stops working.

What was actually counted: 14,814 files out of 103,267

The first number I got was 103,267 files and 4.0 GB. That number is close to meaningless, because most of it is node_modules.

I excluded the following before scanning.

Excluded directoryWhy
node_modulesNot mine, and not somewhere keys live. Nearly 90% of the file count
.next / dist / buildBuild output. Reading the source is enough
.gitHistory needs a different hunt (keys already committed), which is a separate question
.wranglerDeploy tooling scratch space

After exclusions: 14,814 files and 2.1 GB, a little over a tenth of the original. Without that step the scan takes minutes every time and produces a result list nobody wants to read.

One note on skipping .git. A key committed to history survives deletion from the working tree, so that hunt still matters — but it answers a different question than "is it safe to expose this folder right now." Here I only looked at the working tree.

Of the 24 filename hits, 5 were real

All 19 false positives were article drafts. Their filenames contained token because they discussed token estimates and rate limits. Nothing more.

The 5 real ones broke down like this:

  • A note holding a personal access token in plain text — 1
  • Dated backups of that same note — 3
  • A note holding a webhook signing secret — 1

There is a practical cost hiding in that 19. A check that mostly cries wolf gets skimmed, then scheduled less often, then quietly dropped. I had run a name-based grep like this before and remembered it as "clean," which in hindsight probably means I stopped reading past the article filenames. Precision is not a cosmetic property of a security check; it decides whether the check survives contact with a busy week.

The line that stopped me was the three backups. You can rotate a token and still leave the old value alive under a slightly different filename. Backups quietly extend the lifetime of a key.

Stray .bak files cause trouble on the commit side too. I wrote up how a helper script's leftovers get swept in by git add -A in git add -A sweeps up your .bak backups.

The 18 content hits, and why 13 of them are invisible by name

Grouped by extension:

ExtensionCountWhat they were
.sh10Throwaway scripts written to set up billing configuration
.bak_* (dated)4Generational backups of documents and notes
.txt3Notes holding tokens and configuration values
.md1A troubleshooting log with a real key pasted into the repro steps

Shell scripts dominated. Register products and prices in bulk, create webhooks, replace descriptions across a catalog — each one ran once, did its job, and stayed. When I wrote them they were "things I run locally," and that assumption evaporates the moment the folder is handed to something else. Working as an indie developer, nobody reviews that assumption for you.

The single .md file was the one that stung. A record of a problem I had hit months earlier included the real key inside its reproduction steps. My assumption that documentation is not where keys live had become the hole in my own checking.

What those 13 invisible files have in common is simple: the person who wrote them did not think of them as secrets. They were not secret when they were named. They became secret later. Names cannot track that.

The scanner, in a form you can run today

It is written so that no key value is ever printed. The output is paths and counts only.

#!/usr/bin/env bash
# Count the exposure surface of a connected folder. Never prints key values.
set -uo pipefail
ROOT="${1:?usage: scan-exposure.sh <folder>}"
 
PRUNE=( -name node_modules -o -name .next -o -name .git
        -o -name .wrangler -o -name dist -o -name build )
NAME_PAT=( -iname "*token*" -o -iname "*secret*" -o -iname "*credential*"
           -o -iname "*.pem" -o -iname "*.key" -o -iname ".env*"
           -o -iname "id_rsa*" -o -iname "*api?key*" )
VALUE_RE='ghp_[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{20,}|sk-ant-[A-Za-z0-9-]{20,}'
VALUE_RE="$VALUE_RE"'|sk_live_[A-Za-z0-9]{20,}|whsec_[A-Za-z0-9]{20,}|AIza[A-Za-z0-9_-]{30,}'
 
all=$(find "$ROOT" -type f 2>/dev/null | wc -l)
kept=$(find "$ROOT" \( "${PRUNE[@]}" \) -prune -o -type f -print 2>/dev/null | wc -l)
byname=$(find "$ROOT" \( "${PRUNE[@]}" \) -prune -o -type f \( "${NAME_PAT[@]}" \) -print 2>/dev/null | wc -l)
 
tmp=$(mktemp)
find "$ROOT" \( "${PRUNE[@]}" \) -prune -o -type f -size -2M -print0 2>/dev/null \
  | xargs -0 grep -lIE "$VALUE_RE" 2>/dev/null > "$tmp"
 
printf 'files(all)        %s\n' "$all"
printf 'files(scanned)    %s\n' "$kept"
printf 'hits(by filename) %s\n' "$byname"
printf 'hits(by content)  %s\n' "$(wc -l < "$tmp")"
printf -- '--- by extension ---\n'
sed 's|.*/||; s|^[^.]*$|(no ext)|; s|.*\.|.|' "$tmp" | sort | uniq -c | sort -rn
rm -f "$tmp"

Real output from my machine:

files(all)        103267
files(scanned)    14814
hits(by filename) 24
hits(by content)  18
--- by extension ---
     10 .sh
      3 .txt
      1 .md
      1 .bak_20260822
      1 .bak_20260602b
      1 .bak_2026-07-28
      1 .bak_20260602
 
real	0m32.147s

Three notes on why it is written this way.

grep -l returns filenames only and never the matching line, so the scan result itself does not become a new leak path. -I skips binaries, which matters a lot in a folder full of image assets. -size -2M keeps large logs and build artifacts out of the comparison; a key note is never two megabytes.

The regex list only covers keys with fixed prefixes. Values without a recognizable prefix will not be caught this way. I use it knowing that limit, as a tool that reliably catches what it can catch.

Thirty-two seconds is light enough to run once a month without thinking about it.

What I changed afterwards

Three things went into my own routine:

  1. Key notes move outside the connected folder. When the unit of sharing is a whole folder, "no secrets live in this folder" has to be decided first, or the boundary shifts every time.
  2. No generational backups of key notes. Those three backups were keeping replaced values alive. One copy now, updated in place.
  3. Scan by content, not by name, once a month. A check with a 79% false positive rate was not worth continuing.

Order matters in the cleanup, and I got it wrong on the first pass. My instinct was to delete the files immediately, which felt satisfying and accomplished very little: the values had already been sitting in a shared folder, so the exposure had happened regardless of whether the file still existed. Rotating the credential is what actually ends it. Deleting first also destroys the evidence of which key was where, which is exactly what you need in order to rotate the right things. So the sequence I use now is rotate, then relocate, then delete — and only then re-run the scan to confirm the count went to zero.

Counting is only the entrance. The next step is making the files unreadable in the first place, and that belongs to configuration. The sandbox.credentials settings that stop credential files from being read at the OS level, along with how to verify they are working, are written up with the implementation in The sandbox can run your code without reading your credentials. Reading it after you have your own counts makes it much clearer which setting removes which files from the list.

The useful part of today was not the number 18. It was that 13 of them were invisible by name — the exact size of the gap between how well I thought I was managing this and how well I actually was.

If you have a connected folder, run the script once. A count of zero is a real basis for confidence. A count above zero is something you can act on today, while it is still cheap.

Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $15 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Cowork2026-03-20
Running 4 Sites with 600+ Articles on Autopilot Using Cowork — A Solo Developer's Real Automation Story
How I use Claude's Cowork mode to automatically generate and publish articles across 4 AI knowledge base sites. Covers scheduled task design, skill files, real failures, and lessons learned.
Cowork2026-07-11
Make Your Nightly MCP Connectors' Health Visible — A Lightweight Ledger for Solo Operators
You don't need Enterprise connector observability to see your MCP connectors' error rate and latency. Append one line per tool call, roll it up weekly, and let regressions ring a bell. A working health ledger for anyone running scheduled tasks solo.
Cowork2026-07-02
How Many Tasks Fire in the Same Minute — Flattening Cowork Scheduled-Task Collisions from Cron
When Cowork scheduled tasks bunch up at the same time and fight over shared resources, you can expand every cron expression into fire times, count collisions and true concurrency, and shave the peak with a greedy offset that never moves your premium slots. With working code and measured before/after numbers.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →