@medusasec/sensitive-spans
v0.1.1
Published
Dependency-free browser-side primitives from the Medusa extension: sensitive-span detection with measured precision guards, actor attribution (human vs. agent), actor-aware policy, pseudonymization, and signed receipt chains.
Downloads
6,249
Maintainers
Readme
@medusasec/sensitive-spans
The browser-side primitives from the Medusa extension, as one dependency-free ESM package. Runs in browsers, Node 20+, Deno and Workers. Nothing phones home.
npm i @medusasec/sensitive-spansWhat's inside
| Module | What it gives you |
|---|---|
| detect(text, {policy, settings, extraSpans}) | Sensitive spans (secrets, PII, financial, health, insurance, code, prompt injection) from the deterministic layer — vendor key prefixes, checksummed identifiers (Luhn, IBAN mod-97, ABA), 30+ injection families — then the measured precision guards and a policy decision: {spans, action, requireJustification, disallowOverride, disallowApproval}. |
| classifyLocal, applyAllowlist, mergeSpans | The pieces behind detect, if you want to run your own model and merge. |
| decide, filterSpans, hasSecretSignal, isProsePii, … | The guard library: each guard is traceable to a quantified false-positive reduction on a 12k-row corpus of real prose. |
| detectSpansTier0 | The zero-shot Tier-0 engine (entropy scoring, base64 deobfuscation, dummy-value rejection). |
| attributeActor, scoreSignals | Who is driving the browser: human \| agent \| automation \| unknown from debugger attachment + an input fingerprint (pointer pressure, trail, unkeyed text insertion, injected-script frames). |
| decideAgentAction | Actor-aware policy: {default, rules:[{agent, sites, actions, action}]} → allow \| log \| approve \| deny. Humans are never gated. |
| assignPlaceholders, pseudonymizeText, rehydrateText | Consistent, reversible placeholders ([PII-1]) for detected values. |
| makeReceipt, verifyReceipts, makeSigner, makeVerifier | Hash-chained, ECDSA P-256 signed receipts with WebCrypto; verification works from any runtime with the public JWK. |
| actorHeaderValue, headerRule | The Sec-Agent-Actor attribution header and its per-tab declarativeNetRequest rule. |
| mergeTools, toolsFingerprint | WebMCP tool inventory helpers. |
Quick start
import { detect, decideAgentAction, attributeActor } from "@medusasec/sensitive-spans";
const r = detect("rotate AKIAIOSFODNN7EXAMPLE before Friday", {
policy: { category_actions: { secret: "block" }, disallow_override: ["secret"] },
});
// r.action === "block", r.spans[0].category === "secret"
const actor = attributeActor({ attached: true, candidates: [{ id: "fcoe…", known: "claude-in-chrome", label: "Claude in Chrome", kind: "agent", enabled: true, canDrive: true }] });
decideAgentAction({ default: "log", rules: [{ agent: "claude-in-chrome", sites: ["*.internal.example"], action: "approve" }] }, actor, "hr.internal.example");
// → { action: "approve", rule: 0, source: "rule" }The model
The extension also runs a 28.8 MB int8 BERT token classifier on-device. It is
not bundled here; pass its spans as extraSpans and detect merges them
before the guards run. A loader package is planned.
Publishing
The scope is @medusasec; create the medusasec organization on npmjs.com (or
rename the package to your user scope) before the first publish. Then:
npm login
cd packages/sensitive-spans
npm publishprepublishOnly rebuilds dist/ from the extension source and runs the tests,
and publishConfig.access is public, so no flags are needed.
Build
dist/ is assembled from ../../medusa-browser-extension/src by build.mjs
so the package can never drift from the extension. npm test builds and runs
the tests.
Apache-2.0.
