<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Shanjeev Rajendran</title>
    <description>The latest articles on DEV Community by Shanjeev Rajendran (@shanjeev_rajendran).</description>
    <link>https://dev.to/shanjeev_rajendran</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4185670%2Fd1f0c86d-1f3b-428e-8abc-15870a8405df.jpg</url>
      <title>DEV Community: Shanjeev Rajendran</title>
      <link>https://dev.to/shanjeev_rajendran</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shanjeev_rajendran"/>
    <language>en</language>
    <item>
      <title>How I keep secrets and personal data out of Claude Code</title>
      <dc:creator>Shanjeev Rajendran</dc:creator>
      <pubDate>Thu, 15 Oct 2026 00:39:00 +0000</pubDate>
      <link>https://dev.to/shanjeev_rajendran/how-i-keep-secrets-and-personal-data-out-of-claude-code-61n</link>
      <guid>https://dev.to/shanjeev_rajendran/how-i-keep-secrets-and-personal-data-out-of-claude-code-61n</guid>
      <description>&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Claude Code reads whatever a task touches. Ask it to fix a failing job and it opens the &lt;code&gt;.env&lt;/code&gt;, tails the log, greps the support export. Everything it reads goes to the model as context.&lt;/p&gt;

&lt;p&gt;But my working folders hold API keys, database passwords, and support tickets with customers' names, emails and home addresses. I didn't want any of that leaving my machine just because Claude needed to look at a file that happened to contain it.&lt;/p&gt;

&lt;p&gt;Secret scanners help with keys that have a known shape. They don't help with a customer's name in a ticket, or an address in a log line. To a regex, those look like ordinary text.&lt;/p&gt;

&lt;p&gt;So I built Cloakroom: a Claude Code plugin that masks secrets and personal data before the model sees them, and puts the real values back when Claude writes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Claude sees
&lt;/h2&gt;

&lt;p&gt;Claude Code lets a plugin run hooks before and after every tool call. Cloakroom sits on those hooks. When Claude reads a file or runs a command, the output goes through Cloakroom first. It looks for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;secrets with a known shape (cloud keys, tokens, private keys, passwords in URLs and config lines)&lt;/li&gt;
&lt;li&gt;numbers with a checksum (cards, IBANs, SSNs)&lt;/li&gt;
&lt;li&gt;personal data in free text (names, emails, addresses, birth dates), found by a small model that runs locally&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each value it finds is swapped for a placeholder. Here's a support note and a config line, on disk and as Claude gets them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# on disk
Nadia Petrov called about a double charge. Reach her at nadia.petrov@gmail.com, 18 Larkspur Lane, Charlotte NC.
DATABASE_URL=postgres://admin:Hunter2x9@10.0.4.12/prod

# what Claude sees
PII_PERSON_1 called about a double charge. Reach her at PII_EMAIL_1, PII_ADDRESS_1.
DATABASE_URL=postgres://admin:PII_SECRET_1@10.0.4.12/prod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude can still do the job. It knows there's a person, an email and a password, and where each one sits. It just doesn't know the values. A value keeps the same placeholder for the whole session, so &lt;code&gt;PII_PERSON_1&lt;/code&gt; in one file is the same person in the next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scans and photos
&lt;/h2&gt;

&lt;p&gt;A lot of personal data lives in pictures: a scanned form, a photo of an ID. Cloakroom can't check pixels, so it reads them instead. A scanned PDF page or a photo that Claude opens goes through OCR on your own machine, and Claude gets the masked text instead of the image. The OCR models ship inside the package, so nothing is uploaded. A photo of a form that says &lt;code&gt;Patient: Nadia Petrov DOB 03/14/1986&lt;/code&gt; reaches Claude as &lt;code&gt;Patient: PII_PERSON_1 DOB PII_DATE_1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;OCR misreads digits, so in that text every long run of them is masked as an account number. Handwriting still reads poorly.&lt;/p&gt;

&lt;h2&gt;
  
  
  How restore works
&lt;/h2&gt;

&lt;p&gt;Masking alone breaks things. If Claude writes &lt;code&gt;Hi PII_PERSON_1,&lt;/code&gt; into a reply draft, that's useless to you.&lt;/p&gt;

&lt;p&gt;So the original values go into an encrypted vault for the session, with the key in your OS's secure store (Keychain on macOS, Credential Manager on Windows, Secret Service on Linux). When Claude writes a file or runs a command that contains a placeholder, the hook swaps the real value back in, locally, just before the tool runs. The draft on your disk says &lt;code&gt;Hi Nadia Petrov,&lt;/code&gt;. The model never saw the name.&lt;/p&gt;

&lt;p&gt;Prompts are different. Claude Code lets a hook block a prompt but not rewrite it, so if you paste a key or an email straight into the chat, Cloakroom stops that prompt and tells you what it found. Put the detail in a file and ask Claude to read it instead, or start the prompt with &lt;code&gt;cr!&lt;/code&gt; to send it as is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing false alarms
&lt;/h2&gt;

&lt;p&gt;A detector that masks too much gets switched off. Mine flagged &lt;code&gt;Order 4471&lt;/code&gt; as an account number, which is harmless and gets in the way.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cloakroom dashboard&lt;/code&gt; opens a local page listing every masked call. Label an alert as correct, a false alarm, or something it missed. A false alarm suggests a "never mask this" rule; a miss suggests an "always mask this" one. Approve the rule and that order number reaches Claude as plain text from then on. Rules that would unmask a key, password or card number always wait for your yes, and undo puts everything back.&lt;/p&gt;

&lt;p&gt;The detection model itself never changes. Your labels become rules in front of it, encrypted like the vault.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Regex isn't enough.&lt;/strong&gt; Keys are easy. Names, addresses and free-text personal data need a model. I use a small one that runs on your machine. The cost is a one-time download and some false alarms, which is why the labels and rules exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Restore is the hard part.&lt;/strong&gt; Detection gets the attention, but the real work was making write-back reliable: the same placeholder everywhere in a session, the right shape for each tool's input, and edge cases like Claude's Edit tool checking text against the file before any hook runs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fail closed.&lt;/strong&gt; If Cloakroom can't check something (the model still loading, the service down, OCR timing out), tool calls are held back rather than waved through. Prompts fall back to the fast rules, so you're never locked out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Encoded output counts.&lt;/strong&gt; A command like &lt;code&gt;base64 .env&lt;/code&gt; or &lt;code&gt;xxd&lt;/code&gt; turns a secret into something no pattern matches. Cloakroom decodes those dumps and checks them too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Know what it isn't.&lt;/strong&gt; Cloakroom stops accidental exposure: the key in a file Claude happened to open, the customer list in a log. It isn't a sandbox, and a model determined to leak data piece by piece is out of scope.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;It's open source, runs locally, needs no account, and works on macOS, Windows and Linux. Inside Claude Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/plugin marketplace add shanjeevrajendran/cloakroom
/plugin install cloakroom@cloakroom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It protects keys and card numbers within seconds, then downloads the local model in the background for names and addresses.&lt;/p&gt;

&lt;p&gt;I'd like to hear what it misses and what it over-masks: &lt;a href="https://github.com/shanjeevrajendran/cloakroom" rel="noopener noreferrer"&gt;https://github.com/shanjeevrajendran/cloakroom&lt;/a&gt;&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>privacy</category>
      <category>security</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
