Skip to content

Ayubjon/prompt-cloak

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

prompt-cloak

Reversibly mask secrets and PII before sending text to an LLM, then restore them in the response.

How prompt-cloak works

When you send text to a hosted model, anything sensitive in that text — emails, API keys, card numbers, private keys — leaves your machine. prompt-cloak swaps those values for stable placeholders before the request, keeps the mapping in a local vault, and swaps the real values back after the model replies. The model sees [EMAIL_1]; you keep jane@corp.io.

  • Reversible. cloak() → call the model → uncloak() restores everything.
  • Zero dependencies. Pure ESM JavaScript, runs anywhere Node 18+ runs.
  • Deterministic. The same value always maps to the same placeholder, so the model can reason about [EMAIL_1] and you can map its answer back.
  • Local-first. No network, no API keys, nothing phones home.

Install

npm install prompt-cloak
# or run the CLI without installing:
npx prompt-cloak --help

Library usage

import { cloak, uncloak } from 'prompt-cloak';

const { text, vault } = cloak('Email jane@corp.io, card 4111 1111 1111 1111');
// text  -> 'Email [EMAIL_1], card [CREDIT_CARD_1]'
// vault -> { '[EMAIL_1]': 'jane@corp.io', '[CREDIT_CARD_1]': '4111 1111 1111 1111' }

// ...send `text` to your LLM, get a reply that references the placeholders...

const restored = uncloak(modelReply, vault);

Round-trip is exact: uncloak(cloak(s).text, cloak(s).vault) === s.

See examples/llm-roundtrip.js for a full flow.

Options

cloak(text, {
  only:   ['email', 'creditCard'], // apply only these detectors
  except: ['phone'],               // apply all detectors except these
});

CLI usage

# Mask a file and save the vault for later
prompt-cloak mask notes.txt --vault notes.vault.json > masked.txt

# Restore from the masked text + vault
prompt-cloak unmask masked.txt --vault notes.vault.json

# One-shot JSON (text + vault together), reading stdin
echo "ping me at a@b.com" | prompt-cloak mask --json

# List what it can detect
prompt-cloak detectors

What it detects

Type Example
email jane@corp.io
creditCard 4111 1111 1111 1111 (Luhn-checked)
ipv4 10.0.0.5
macAddress 3D:F2:C9:A6:B3:4F
jwt eyJhbGci...
awsAccessKey AKIAIOSFODNN7EXAMPLE
githubToken ghp_...
apiKey sk-..., sk-ant-...
ssn 123-45-6789
phone +1 415-555-0132
privateKey -----BEGIN RSA PRIVATE KEY----- ...

Overlapping matches are resolved by detector priority (e.g. a 16-digit card is never carved up by the phone-number rule), and Luhn validation keeps random 16-digit IDs from being mistaken for cards.

API

Export Description
cloak(text, options?) Returns { text, vault }.
uncloak(text, vault) Returns the text with placeholders restored.
detectors The array of built-in detector definitions.
findMatches(text, detectors) Low-level: raw matches before overlap resolution.
resolveOverlaps(matches) Low-level: pick non-overlapping matches by priority.
isLuhnValid(value) The Luhn checksum used by the card detector.

Caveats

prompt-cloak uses pattern matching, not magic. It catches well-structured secrets and common PII formats, but it cannot recognize a person's name in free prose or a secret that looks like ordinary text. Treat it as a strong first layer of defense, not a guarantee. Review the masked output for anything sensitive the patterns missed before sending it onward.

Develop

npm test   # runs node --test

License

MIT © 2026 Ayubjon

Support

If this project is useful to you, you can support its development with a crypto tip — thank you!

USDT — Ethereum (ERC-20):

0xad39bdf2df0b8dd6991150fcea0a156150ed19b8

View / verify on Etherscan

Send only on the Ethereum (ERC-20) network.

About

Reversibly mask secrets & PII before sending text to an LLM, then restore them in the response. Zero-dependency Node CLI + library.

Topics

Resources

License

Stars

2 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors