← All tools

namespace-guard

Popularity 65 Updated Development & Build

Cross-script confusable detection, slug safety, and LLM Denial of Spend defence. Zero dependencies.

npmauto-collected

Installation

npm
npm install -g namespace-guard

Install with npm.

namespace-guard

The world's first library that detects confusable characters across non-Latin scripts. Slug claimability, Unicode anti-spoofing, and LLM Denial of Spend defence in one zero-dependency package.

  • Live demo: https://paultendo.github.io/namespace-guard/
  • Blog post: https://paultendo.github.io/posts/namespace-guard-launch/

Cross-script confusable detection

Existing confusable standards (TR39, IDNA) map non-Latin characters to Latin equivalents. They have zero coverage for confusable pairs between two non-Latin scripts.

namespace-guard ships 3,525 cross-script pairs from confusable-vision (measured across 245 system fonts using vector-outline raycasting — RaySpace). This catches attacks that no other library detects:

import { areConfusable, detectCrossScriptRisk } from "namespace-guard";
import { CONFUSABLE_WEIGHTS } from "namespace-guard/confusable-weights";

// Hangul ᅵ and Han 丨 are visually identical (ray distance 0.004, Arial Unicode MS)
areConfusable("\u1175", "\u4E28", { weights: CONFUSABLE_WEIGHTS }); // true

// Greek Τ and Han 丅 are near-identical (multiple fonts)
areConfusable("\u03A4", "\u4E05", { weights: CONFUSABLE_WEIGHTS }); // true

// Cyrillic І and Greek Ι are identical outlines (62 fonts)
areConfusable("\u0406", "\u0399", { weights: CONFUSABLE_WEIGHTS }); // true

areConfusable("\u1175", "\u4E28"); // false

// Analyze an identifier for cross-script risk const risk = detectCrossScriptRisk("\u1175\u4E28", { weights: CONFUSABLEWEIGHTS }); // { riskLevel: "high", scripts: ["han", "hangul"], crossScriptPairs: [...] }


4,174 total confusable pairs scored by visual measurement (3,111 TR39-confirmed, 1,063 novel). Each pair carries a `danger` score (0–1) representing geometric similarity across fonts; the shipped dataset uses a 0.5 floor. For higher precision, filter at `danger > 0.7` (574 pairs). Cross-script data licensed CC-BY-4.0.

## Installation

npm install namespace-guard


## Quick Start (60 seconds)

import { createNamespaceGuardWithProfile } from "namespace-guard"; import { createPrismaAdapter } from "namespace-guard/adapters/prisma"; import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

const guard = createNamespaceGuardWithProfile( "consumer-handle", { reserved: ["admin", "api", "settings", "dashboard", "login", "signup"], sources: [ { name: "user", column: "handleCanonical", scopeKey: "id" }, { name: "organization", column: "slugCanonical", scopeKey: "id" }, ], }, createPrismaAdapter(prisma) );

await guard.assertClaimable("acme-corp");


For race-safe writes, use `claim()`:

const result = await guard.claim(input.handle, async (canonical) = { return prisma.user.create({ data: { handle: input.handle, handleCanonical: canonical, }, }); });