<?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>Forem: CloakLLM</title>
    <description>The latest articles on Forem by CloakLLM (@cloakllm).</description>
    <link>https://forem.com/cloakllm</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3800261%2Ffe790df0-1fbd-4ba2-ad69-2135ca9b3f78.png</url>
      <title>Forem: CloakLLM</title>
      <link>https://forem.com/cloakllm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/cloakllm"/>
    <language>en</language>
    <item>
      <title>What the Data Act Misses: The Last Mile Between Regulation and Adoption</title>
      <dc:creator>CloakLLM</dc:creator>
      <pubDate>Thu, 09 Apr 2026 14:43:23 +0000</pubDate>
      <link>https://forem.com/cloakllm/what-the-data-act-misses-the-last-mile-between-regulation-and-adoption-3982</link>
      <guid>https://forem.com/cloakllm/what-the-data-act-misses-the-last-mile-between-regulation-and-adoption-3982</guid>
      <description>&lt;p&gt;Every company using Large Language Models (LLMs) is sending data somewhere. Most of them don't have a clear answer for what happens to the personal information inside those API calls. That's not a future compliance problem, it's a right-now problem. And waiting for regulation to catch up isn't a strategy; it's a liability.&lt;/p&gt;

&lt;p&gt;I founded CloakLLM because I kept seeing the same scenario play out across industries. Companies were ready to adopt LLMs for high-impact use cases-customer support automation, complex document processing, internal knowledge search- but they hit a wall. There was no clear path to move from a "cool demo" to "production-ready" without exposing sensitive customer data to a third-party API.&lt;/p&gt;

&lt;p&gt;When that wall is hit, the project usually stalls. But "stalled" is a polite word for what actually happens.&lt;/p&gt;

&lt;p&gt;In reality, the project often goes underground. When official AI initiatives are blocked by compliance concerns, employees don't stop needing the technology. They open ChatGPT in a personal browser tab and paste customer data, proprietary code, or sensitive legal summaries into a consumer interface. They do this with zero logging, zero PII protection, and zero audit trail. The compliance concern hasn't been solved; it's just become invisible to the C-suite. This "Shadow AI" is one of the largest unmanaged risks in the enterprise today.&lt;/p&gt;

&lt;p&gt;The Vision vs. The Reality&lt;/p&gt;

&lt;p&gt;This gap exists everywhere, but in the EU, the tension is particularly high. The regulatory framework is actually ahead of most jurisdictions. The Data Act went live on September 12, 2025. The AI Act mandates automatic record-keeping (Article 12) and transparency (Article 13). GDPR remains the bedrock, requiring data minimization and the right to erasure.&lt;/p&gt;

&lt;p&gt;Europe got the vision right. I believe that a trust-based framework is a long-term competitive advantage. But there's a "last mile" problem: none of these high-level principles translates into tools that organizations can actually deploy today.&lt;/p&gt;

&lt;p&gt;There is no off-the-shelf solution. No middleware says, "This request contains PII from an EU data subject; here is how to handle it before it leaves your infrastructure." That's why I founded CloakLLM - to create a transparent, open-source layer that sits between the application and the model, ensuring that the "legal yes" is as easy to achieve as the "technical yes."&lt;/p&gt;

&lt;p&gt;Solving the Natural Language Problem&lt;/p&gt;

&lt;p&gt;Protecting data in an LLM call is fundamentally different from protecting a database. Personal information in natural language isn't a solved problem. Simple pattern matching catches structured data, IBANs, credit cards, and phone numbers, but misses the nuance of human speech.&lt;/p&gt;

&lt;p&gt;That's why CloakLLM uses a 3-pass detection pipeline:&lt;/p&gt;

&lt;p&gt;Pattern Matching: For high-speed, high-confidence structured data.&lt;/p&gt;

&lt;p&gt;Named Entity Recognition: To identify people, organizations, and locations in context.&lt;/p&gt;

&lt;p&gt;Local AI Reasoning: This is the critical layer. A local model reasons about what is actually sensitive. It can distinguish between "123 Main St" as a generic example and "the house next to the bakery" as a specific, identifiable address.&lt;/p&gt;

&lt;p&gt;All of this happens locally; the data never leaves the organization's infrastructure until it's already replaced with safe placeholder tokens. When inference happens on a cloud API, that's not a design preference; it's a requirement for GDPR compliance.&lt;/p&gt;

&lt;p&gt;The Three Critical Gaps&lt;/p&gt;

&lt;p&gt;From where I sit, three gaps are preventing the Data Act from becoming a catalyst for adoption:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The API-Layer Standard: The Data Act focuses heavily on IoT-generated data and portability. The AI Act focuses on risk classification. Neither addresses the primary data flow of the current AI boom: the API call. We need a standard for protecting the data in these requests and a recognized format for logging them. Without a standard, every legal department is forced to reinvent the wheel, leading to months of unnecessary friction.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Documentation-Agile Conflict: The AI Act's Annex IV demands comprehensive records of design decisions and data lineage. But for companies using Retrieval-Augmented Generation (RAG) - where the AI pulls from a live knowledge base to answer questions - "data lineage" is a moving target. Every time the knowledge base updates with new documents or fresh data, the system's context changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Annex IV assumes a static audit trail; RAG is inherently dynamic. If you change how the system processes or retrieves information, your compliance snapshot is technically obsolete. Compliance documentation needs to be generated automatically as part of the development process, not maintained manually after the fact. And every month spent on manual compliance work is a month your competitor ships without you.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Missing Implementation Layer: Regulators have published a flood of guidance. These are valuable for legal teams, but the people actually building AI products need practical tools and implementation blueprints. The gap between a regulatory PDF and a working product is where most innovation quietly dies.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Moving Toward "Compliance-as-Code"&lt;/p&gt;

&lt;p&gt;What would actually change the equation? Standardized, open-source reference implementations.&lt;/p&gt;

&lt;p&gt;If the EU were to fund standard open-source components, privacy detection layers, audit logging tools, and consent-tracking systems - in the same way it funds research, the impact would be massive. Standardization removes the excuse. When a compliance layer is one install away, "we couldn't figure out how to handle PII" stops being a valid reason to delay AI adoption.&lt;/p&gt;

&lt;p&gt;For companies outside the EU, the lesson is the same: adopting this infrastructure now isn't just about avoiding a future fine. It's about building the trust necessary to move AI out of the sandbox and into the core of your business.&lt;/p&gt;

&lt;p&gt;I'd like to hear from others navigating this. If you're leading AI adoption at your company, what's getting in the way? Is it the model capability, or is it the infrastructure of trust?&lt;/p&gt;

&lt;p&gt;The code is open-source: &lt;a href="https://cloakllm.dev/" rel="noopener noreferrer"&gt;cloakllm.dev&lt;/a&gt; | &lt;a href="https://github.com/cloakllm/CloakLLM" rel="noopener noreferrer"&gt;github.com/cloakllm/CloakLLM&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  EUAIAct #DataAct #opensource #privacy #LLM
&lt;/h1&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>privacy</category>
      <category>security</category>
    </item>
    <item>
      <title>Cryptographic Proof That Your LLM Never Saw Real Data</title>
      <dc:creator>CloakLLM</dc:creator>
      <pubDate>Thu, 19 Mar 2026 05:50:02 +0000</pubDate>
      <link>https://forem.com/cloakllm/cryptographic-proof-that-your-llm-never-saw-real-data-50fd</link>
      <guid>https://forem.com/cloakllm/cryptographic-proof-that-your-llm-never-saw-real-data-50fd</guid>
      <description>&lt;h1&gt;
  
  
  Cryptographic Proof That Your LLM Never Saw Real Data
&lt;/h1&gt;

&lt;p&gt;Every PII protection tool makes the same promise: "We sanitized it before sending." But promises aren't proof. When a regulator asks you to demonstrate that patient names never reached OpenAI's servers, "trust us" isn't an answer.&lt;/p&gt;

&lt;p&gt;We just shipped CloakLLM v0.3.2 with cryptographic attestation - Ed25519-signed certificates that mathematically prove sanitization happened. Here's how it works, why it matters, and how to use it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem: Trust Without Verification
&lt;/h2&gt;

&lt;p&gt;Most PII middleware operates on trust. You install it, it sanitizes prompts, and you believe it did its job. Your audit log says "sanitized 3 entities at 14:30:00." But that log is just text. Anyone with file access can edit it. Nothing ties the log entry to the actual data that was processed.&lt;/p&gt;

&lt;p&gt;This creates three gaps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gap 1: No proof of execution.&lt;/strong&gt; Your compliance team can show the tool is installed. They can't prove it was running when a specific prompt was sent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gap 2: No tamper evidence on individual operations.&lt;/strong&gt; Hash-chained audit logs prove the chain wasn't modified after the fact. But they don't prove &lt;em&gt;what&lt;/em&gt; was sanitized - only that &lt;em&gt;something&lt;/em&gt; was logged.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gap 3: No cross-system verification.&lt;/strong&gt; If a downstream execution layer wants to confirm that PII was handled before it processes an action, there's no machine-readable artifact to check.&lt;/p&gt;

&lt;p&gt;The EU AI Act (Article 12, enforcement begins August 2, 2026) requires audit logs that regulators can mathematically verify. Gap 2 is the one that will fail an audit.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Solution: Sanitization Certificates
&lt;/h2&gt;

&lt;p&gt;Starting in v0.3.2, every &lt;code&gt;sanitize()&lt;/code&gt; call can produce an Ed25519-signed certificate. The certificate contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Input hash&lt;/strong&gt; - SHA-256 of the original text (proves what was processed)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output hash&lt;/strong&gt; - SHA-256 of the sanitized text (proves what was produced)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Entity count&lt;/strong&gt; - how many PII entities were detected&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Categories&lt;/strong&gt; - breakdown by type (EMAIL: 2, PERSON: 1, SSN: 1)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detection passes&lt;/strong&gt; - which detection methods ran (regex, NER, LLM)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mode&lt;/strong&gt; - tokenize (reversible) or redact (irreversible)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timestamp&lt;/strong&gt; - ISO 8601&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key ID&lt;/strong&gt; - identifies which signing key produced the certificate&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nonce&lt;/strong&gt; - UUID4 preventing replay attacks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signature&lt;/strong&gt; - Ed25519 signature over the canonical JSON of all fields above&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The certificate is attached to the token map returned by &lt;code&gt;sanitize()&lt;/code&gt;. It's also hashed into the audit log entry, binding the certificate to the chain.&lt;/p&gt;




&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Generate a Signing Key
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cloakllm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DeploymentKeyPair&lt;/span&gt;

&lt;span class="n"&gt;keypair&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DeploymentKeyPair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./keys/signing_key.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This produces an Ed25519 keypair. The private key signs certificates. The public key verifies them. You generate it once per deployment and keep the private key secure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Configure the Shield
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cloakllm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Shield&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ShieldConfig&lt;/span&gt;

&lt;span class="n"&gt;shield&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Shield&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ShieldConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;attestation_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;keypair&lt;/span&gt;
&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or load from a file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;shield&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Shield&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ShieldConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;attestation_key_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./keys/signing_key.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or from an environment variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CLOAKLLM_SIGNING_KEY_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;./keys/signing_key.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Sanitize and Get the Certificate
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;sanitized&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;token_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shield&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sanitize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Email john@acme.com about Sarah Johnson&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s medical records&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;cert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;token_map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;certificate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The certificate now contains a signed attestation of what happened. You can serialize it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;cert_dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_dict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# {
#   "version": "1.0",
#   "timestamp": "2026-03-15T10:30:00Z",
#   "input_hash": "sha256:9f86d081...",
#   "output_hash": "sha256:a3f2b1c4...",
#   "entity_count": 3,
#   "categories": {"EMAIL": 1, "PERSON": 1, "MEDICAL": 1},
#   "detection_passes": ["regex", "ner"],
#   "mode": "tokenize",
#   "key_id": "ed25519:7b2a...",
#   "nonce": "a1b2c3d4-e5f6-...",
#   "signature": "base64:..."
# }
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Verify
&lt;/h3&gt;

&lt;p&gt;Anyone with the public key can verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;public_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;shield&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify_certificate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a single byte of the certificate has been modified, verification fails. The signature covers a canonical JSON serialization of all fields, so field reordering doesn't break verification.&lt;/p&gt;




&lt;h2&gt;
  
  
  Batch Attestation with Merkle Trees
&lt;/h2&gt;

&lt;p&gt;Single-text certificates are straightforward. But what about &lt;code&gt;sanitize_batch()&lt;/code&gt; with 50 texts? You don't want 50 separate certificates - that's expensive and hard to manage.&lt;/p&gt;

&lt;p&gt;CloakLLM uses Merkle trees for batch attestation. Instead of hashing each text individually into the certificate, we compute:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A &lt;strong&gt;Merkle root of input hashes&lt;/strong&gt; - one hash representing all original texts&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Merkle root of output hashes&lt;/strong&gt; - one hash representing all sanitized texts&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The batch certificate contains these two roots instead of individual hashes. One signature covers the entire batch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;texts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Email john@acme.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SSN 123-45-6789&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Call Sarah at 555-0100&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;sanitized_texts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;token_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shield&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sanitize_batch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;texts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;cert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;token_map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;certificate&lt;/span&gt;        &lt;span class="c1"&gt;# single certificate for entire batch
&lt;/span&gt;&lt;span class="n"&gt;merkle_tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;token_map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;merkle_tree&lt;/span&gt;  &lt;span class="c1"&gt;# Merkle tree with proofs
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To verify that a specific text was part of the batch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cloakllm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MerkleTree&lt;/span&gt;

&lt;span class="n"&gt;leaf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;texts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;proof&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;merkle_tree&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;proof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;MerkleTree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify_proof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;leaf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;proof&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;merkle_tree&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the same data structure used in blockchain systems and certificate transparency logs. It lets you prove the inclusion of a single item without revealing the others.&lt;/p&gt;




&lt;h2&gt;
  
  
  Cross-Language Verification
&lt;/h2&gt;

&lt;p&gt;Certificates are fully portable between Python and JavaScript. The canonical JSON serialization and Ed25519 signature format are identical in both SDKs.&lt;/p&gt;

&lt;p&gt;Sign in Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cloakllm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Shield&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ShieldConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DeploymentKeyPair&lt;/span&gt;

&lt;span class="n"&gt;keypair&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DeploymentKeyPair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;shield&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Shield&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ShieldConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attestation_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;sanitized&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;token_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shield&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sanitize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Email john@acme.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cert_dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;token_map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;certificate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_dict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;public_key_hex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;public_key_hex&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify in JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SanitizationCertificate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;DeploymentKeyPair&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cloakllm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SanitizationCertificate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromDict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;certDict&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;publicKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DeploymentKeyPair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromPublicKeyHex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;publicKeyHex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This matters for architectures where the sanitization layer and the verification layer run in different languages or services.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Ed25519?
&lt;/h2&gt;

&lt;p&gt;We chose Ed25519 over RSA or ECDSA for three reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic signatures.&lt;/strong&gt; Same input always produces the same signature. No nonce-related vulnerabilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Small keys and signatures.&lt;/strong&gt; 32-byte public key, 64-byte signature. Certificates stay compact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast.&lt;/strong&gt; Ed25519 verification is roughly 60x faster than RSA-2048 for single-signature verification.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The JavaScript SDK uses Node.js built-in &lt;code&gt;crypto&lt;/code&gt; module - zero additional dependencies. The Python SDK supports either &lt;code&gt;pynacl&lt;/code&gt; or &lt;code&gt;cryptography&lt;/code&gt; as an optional dependency.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;cloakllm[attestation]  &lt;span class="c"&gt;# installs pynacl&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What This Means for EU AI Act Compliance
&lt;/h2&gt;

&lt;p&gt;Article 12 of the EU AI Act requires that high-risk AI systems maintain logs enabling traceability of how the system operates. Enforcement begins August 2, 2026. Non-compliance can result in fines up to 7% of global annual revenue.&lt;/p&gt;

&lt;p&gt;CloakLLM's audit chain already provides hash-linked logs. Attestation certificates add a stronger guarantee: each sanitization operation is individually signed, and the signature binds the operation's inputs, outputs, and metadata into a single tamper-evident artifact.&lt;/p&gt;

&lt;p&gt;For an auditor, this means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Existence proof&lt;/strong&gt; - the certificate proves a sanitization operation occurred at a specific time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrity proof&lt;/strong&gt; - the signature proves the certificate hasn't been modified&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content proof&lt;/strong&gt; - the input/output hashes prove what was processed, without revealing the actual PII&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch proof&lt;/strong&gt; - Merkle proofs demonstrate individual text inclusion without exposing the full batch&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What This Means for Execution Governance
&lt;/h2&gt;

&lt;p&gt;There's an emerging architectural pattern in agentic AI systems: execution boundaries that decide whether a proposed action is allowed to proceed. These boundaries evaluate intent, authority, and system state before committing an action.&lt;/p&gt;

&lt;p&gt;Sanitization certificates add a data-layer signal to this decision. An execution boundary can now ask: "Was the input to this reasoning step provably sanitized?" and verify the answer cryptographically - without trusting the sanitization layer itself.&lt;/p&gt;

&lt;p&gt;This is the difference between a policy that says "PII must be removed" and an architecture that enforces it with mathematical proof.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;cloakllm[attestation]&lt;span class="o"&gt;==&lt;/span&gt;0.3.2
npm &lt;span class="nb"&gt;install &lt;/span&gt;cloakllm@0.3.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate a key, configure the shield, and every &lt;code&gt;sanitize()&lt;/code&gt; call produces a signed certificate. The certificate is attached to the token map, hashed into the audit log, and verifiable in any language.&lt;/p&gt;

&lt;p&gt;Full documentation: &lt;a href="https://cloakllm.dev" rel="noopener noreferrer"&gt;cloakllm.dev&lt;/a&gt;&lt;br&gt;
Source: &lt;a href="https://github.com/cloakllm/CloakLLM" rel="noopener noreferrer"&gt;github.com/cloakllm/CloakLLM&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;CloakLLM is open source (MIT). Built by Ziv Chen.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Every LLM Prompt You Send Is Plaintext. Here's How to Fix That Before the EU Makes You.</title>
      <dc:creator>CloakLLM</dc:creator>
      <pubDate>Mon, 02 Mar 2026 17:32:31 +0000</pubDate>
      <link>https://forem.com/cloakllm/every-llm-prompt-you-send-is-plaintext-heres-how-to-fix-that-before-the-eu-makes-you-27jh</link>
      <guid>https://forem.com/cloakllm/every-llm-prompt-you-send-is-plaintext-heres-how-to-fix-that-before-the-eu-makes-you-27jh</guid>
      <description>&lt;p&gt;Your LLM calls are unencrypted confessions.&lt;/p&gt;

&lt;p&gt;Every time you call &lt;code&gt;litellm.completion()&lt;/code&gt; or &lt;code&gt;openai.chat.completions.create()&lt;/code&gt;, the provider receives your prompt in full plaintext. Names, emails, SSNs, API keys, medical records - all of it sitting in someone else's logs.&lt;/p&gt;

&lt;p&gt;That's been a privacy risk for years. In 5 months, it becomes illegal.&lt;/p&gt;

&lt;h2&gt;
  
  
  August 2, 2026
&lt;/h2&gt;

&lt;p&gt;The EU AI Act enters enforcement. Article 12 mandates &lt;strong&gt;tamper-evident audit logs&lt;/strong&gt; for AI systems - not &lt;code&gt;console.log()&lt;/code&gt;, not a JSON file you append to. Logs that regulators can &lt;strong&gt;mathematically verify&lt;/strong&gt; haven't been altered.&lt;/p&gt;

&lt;p&gt;The penalty: up to &lt;strong&gt;7% of global annual revenue&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you use LLMs and handle EU data, you need:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;PII never reaches the provider (or you need explicit consent per entity)&lt;/li&gt;
&lt;li&gt;Every AI interaction logged in a verifiable audit trail&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Most teams have neither. I built CloakLLM to fix both.&lt;/p&gt;

&lt;h2&gt;
  
  
  What CloakLLM Does
&lt;/h2&gt;

&lt;p&gt;CloakLLM is open-source middleware that sits between your app and any LLM provider. Python, Node.js, and MCP for Claude Desktop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It does three things:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Detects PII&lt;/strong&gt; - three layers deep:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;spaCy NER&lt;/strong&gt; for names, orgs, locations (Python)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regex&lt;/strong&gt; for emails, SSNs, credit cards, API keys, IBANs, phones, IPs, JWTs (both SDKs)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local LLM via Ollama&lt;/strong&gt; (opt-in) - catches context-dependent PII that regex misses: addresses, medical terms, financial data, national IDs. Your data never leaves your machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cloaks it&lt;/strong&gt; with context-preserving tokens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your app:      "Email sarah.j@techcorp.io about Project Falcon"
Provider sees: "Email [EMAIL_0] about Project Falcon"
You receive:   Original email restored in the response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The LLM still understands the prompt. It just never sees real data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Logs everything&lt;/strong&gt; to a hash-chained audit trail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"seq"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sanitize"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"entity_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prompt_hash"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha256:9f86d0..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prev_hash"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha256:7c4d2e..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"entry_hash"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha256:b5e8f3..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each entry's SHA-256 hash includes the previous entry's hash. Tamper with one log entry, and every subsequent hash breaks. This is what Article 12 actually requires.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python - One Line with LiteLLM
&lt;/h2&gt;

&lt;p&gt;Works with 100+ providers (Anthropic, OpenAI, Azure, Bedrock, Ollama, etc.) via LiteLLM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cloakllm&lt;/span&gt;
&lt;span class="n"&gt;cloakllm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# Done.
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;litellm&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;litellm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic/claude-sonnet-4-20250514&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Help me email sarah.j@techcorp.io about the Q3 audit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Provider never saw the email. Response has it restored.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Node.js - OpenAI SDK
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cloakllm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cloakllm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;openai&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;cloakllm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Done.&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gpt-4o-mini&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Write a reminder for sarah.j@techcorp.io about the Q3 audit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// Provider never saw the email.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Node.js - Vercel AI SDK
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createCloakLLMMiddleware&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cloakllm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;generateText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wrapLanguageModel&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ai&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;openai&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ai-sdk/openai&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createCloakLLMMiddleware&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wrapLanguageModel&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gpt-4o&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;generateText&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Write a reminder for sarah.j@techcorp.io about the Q3 audit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// Streaming supported - handles tokens split across chunk boundaries&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  MCP Server - Claude Desktop
&lt;/h2&gt;

&lt;p&gt;CloakLLM also ships as an MCP server with three tools: &lt;code&gt;sanitize&lt;/code&gt;, &lt;code&gt;desanitize&lt;/code&gt;, and &lt;code&gt;analyze&lt;/code&gt;. Add it to your &lt;code&gt;claude_desktop_config.json&lt;/code&gt; and every Claude Desktop conversation gets PII cloaking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Or Use It Standalone
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Python
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cloakllm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Shield&lt;/span&gt;
&lt;span class="n"&gt;shield&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Shield&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;cloaked&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;token_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shield&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sanitize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Send to john@acme.com, SSN 123-45-6789&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# cloaked: "Send to [EMAIL_0], SSN [SSN_0]"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Node.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Shield&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cloakllm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shield&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Shield&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;cloaked&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tokenMap&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;shield&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sanitize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Send to john@acme.com, SSN 123-45-6789&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Works with any LLM client, any provider, any framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Local LLM Detection
&lt;/h2&gt;

&lt;p&gt;Regex catches structured PII. But "I live at 742 Evergreen Terrace" or "diagnosed with hypertension" - regex can't catch that.&lt;/p&gt;

&lt;p&gt;CloakLLM has an opt-in LLM detection layer that runs through local Ollama:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;shield&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Shield&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;ShieldConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;llm_detection&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;llm_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama3.2:3b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It detects addresses, medical terms, financial data, national IDs, biometrics, usernames, and passwords - all without your data leaving your machine.&lt;/p&gt;

&lt;p&gt;The LLM pass runs after regex, so already-detected entities are skipped. No double counting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design Decisions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Regex first, NER second, LLM third.&lt;/strong&gt; Structured data (emails, SSNs, credit cards) is caught by regex with near-zero latency. spaCy NER runs second for names and orgs. The LLM pass is opt-in and catches everything else. Fast path stays fast.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overlap detection.&lt;/strong&gt; If regex catches &lt;code&gt;john@acme.com&lt;/code&gt; and NER detects &lt;code&gt;acme.com&lt;/code&gt; as ORG, the overlap is caught and the duplicate is skipped.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;System prompt injection.&lt;/strong&gt; Without it, LLMs see &lt;code&gt;[PERSON_0]&lt;/code&gt; and ask "what's the real name?" CloakLLM injects a system message telling the model to treat tokens as real values. Only when tokens are present.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token injection protection.&lt;/strong&gt; If user input contains &lt;code&gt;[PERSON_0]&lt;/code&gt;, it gets escaped to fullwidth Unicode brackets before tokenization - preventing attackers from injecting fake tokens to extract other users' PII during desanitization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;try/finally cleanup.&lt;/strong&gt; Even if the LLM API throws, the token map (which contains PII mappings) is always cleaned up. No PII lingers in process memory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vercel streaming.&lt;/strong&gt; The Vercel AI SDK middleware buffers text-delta chunks and desanitizes on text-end, correctly handling tokens that span chunk boundaries like &lt;code&gt;[EM&lt;/code&gt; + &lt;code&gt;AIL_0]&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify Your Audit Chain
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cloakllm verify ./cloakllm_audit/
✅ Audit chain integrity verified - no tampering detected.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If someone edits a log entry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Entry #40 ✅ → #41 ✅ → #42 ❌ TAMPERED → #43 ❌ BROKEN → ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hand this to an auditor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Python&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;cloakllm                  &lt;span class="c"&gt;# standalone&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;cloakllm[litellm]         &lt;span class="c"&gt;# with LiteLLM middleware&lt;/span&gt;
python &lt;span class="nt"&gt;-m&lt;/span&gt; spacy download en_core_web_sm

&lt;span class="c"&gt;# Node.js&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;cloakllm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Numbers
&lt;/h2&gt;

&lt;p&gt;150 tests across Python (62), JS (79), and MCP (9). Security audited with 6 vulnerability classes found and fixed: backreference injection, fake token injection, ReDoS hardening, spaCy model validation, middleware memory cleanup, and custom pattern safety checks. All regression-tested.&lt;/p&gt;

&lt;p&gt;Zero runtime dependencies on the JS side. Python depends on spaCy.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;The roadmap includes LangChain.js integration, OpenTelemetry span emission, RFC 3161 trusted timestamping, sensitivity-based routing (PII → local model, clean → cloud), and an admin dashboard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The EU AI Act deadline is August 2, 2026. 5 months from today.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;→ &lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/cloakllm/CloakLLM" rel="noopener noreferrer"&gt;github.com/cloakllm/CloakLLM&lt;/a&gt;&lt;br&gt;
→ &lt;strong&gt;Python SDK:&lt;/strong&gt; &lt;a href="https://github.com/cloakllm/CloakLLM-PY" rel="noopener noreferrer"&gt;github.com/cloakllm/CloakLLM-PY&lt;/a&gt; | &lt;code&gt;pip install cloakllm&lt;/code&gt;&lt;br&gt;
→ &lt;strong&gt;Node.js SDK:&lt;/strong&gt; &lt;a href="https://github.com/cloakllm/CloakLLM-JS" rel="noopener noreferrer"&gt;github.com/cloakllm/CloakLLM-JS&lt;/a&gt; | &lt;code&gt;npm install cloakllm&lt;/code&gt;&lt;br&gt;
→ &lt;strong&gt;MCP Server:&lt;/strong&gt; &lt;a href="https://github.com/cloakllm/cloakllm-mcp" rel="noopener noreferrer"&gt;github.com/cloakllm/cloakllm-mcp&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>python</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
