Skip to main content

Documentation Index

Fetch the complete documentation index at: https://glide-9da73dea.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Two-pass secret scanner. The first pass matches known-format secrets against curated regexes; the second catches high-entropy opaque blobs that didn’t match any pattern. Used in the Glide Trust Console event ingestion pipeline to redact ReasoningStepEvent.excerpt before persistence, and as a CI gate on every PR via scripts/scan-secrets.mjs.

Install

npm install @glideco/secrets-scan
npmjs.com/package/@glideco/secrets-scan

What it catches

KindDetection methodExample pattern
jwtdenylisteyJ… three-part structure
pem-blockdenylist-----BEGIN … PRIVATE KEY-----
aws-access-keydenylistAKIA[A-Z0-9]{16}
aws-secret-keydenylist + contextcontextual prefix required (aws_secret_access_key=)
stripe-keydenylistsk_live_, pk_test_, rk_live_ + 20+ chars
github-patdenylistghp_, gho_, ghu_, ghs_, ghr_ + 30+ chars
slack-tokendenylistxox[abprs]-
gcp-keydenylistAIza[0-9A-Za-z_-]{35}
anthropic-keydenylistsk-ant- + 20+ chars
openai-keydenylistsk- + 20+ chars (after anthropic-key check)
oauth-codedenylistaccess_token=, refresh_token= + value
evm-private-keydenylist + contextcontextual prefix + 0x[a-f0-9]{64}
solana-private-keydenylist + contextcontextual prefix + base58 86–90 chars
bearerdenylistBearer + 20–128 chars
high-entropyentropy≥ 4.5 bits/char × ≥ 30 chars, not already redacted
Anthropic keys are matched before OpenAI keys in the denylist order because both share the sk- prefix — earlier rules win when ranges overlap.

Basic usage

import { scan } from '@glideco/secrets-scan';

const result = scan(
  'key=AKIAIOSFODNN7EXAMPLE token=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
);

console.log(result.redactions);
// [
//   { kind: 'aws-access-key', match: 'AKIAIOSFODNN7EXAMPLE', start: 4, end: 24, reason: 'denylist' },
//   { kind: 'github-pat', match: 'ghp_xxxx...', start: 32, end: 69, reason: 'denylist' },
// ]

console.log(result.redacted);
// 'key=[REDACTED:aws-access-key] token=[REDACTED:github-pat]'

Tuning the entropy pass

import { scan } from '@glideco/secrets-scan';

// Turn off entropy for inputs that are naturally high-entropy
// (e.g. base64-encoded binary payloads, transaction hashes).
const result = scan(txHashHeavyLogLine, { disableEntropy: true });

// Tighten entropy threshold (default 4.5 bits/char, default min length 30).
const strict = scan(inputText, {
  entropyBitsPerChar: 4.8,
  entropyMinLength: 40,
});

Custom redaction marker

import { scan } from '@glideco/secrets-scan';

const result = scan(input, {
  marker: (kind) => `<REDACTED_${kind.toUpperCase()}>`,
});
// → 'prefix <REDACTED_AWS-ACCESS-KEY> suffix'

Concurrent safety

Each scan() call clones every denylist regex so concurrent invocations cannot race on the shared lastIndex state of a stateful global RegExp. The Trust Console event ingestion path runs scan() in parallel under load — sharing lastIndex would make the second concurrent scan’s first-match index non-deterministic, silently letting secrets through.

Two-pass design

Pass 1 — denylist. 14 patterns, each with its own cloned RegExp instance. Shape-only kinds (EVM private key, Solana private key, AWS secret key, Bearer token) require a contextual word on the same line — “private”, “secret”, “key”, “seed”, “Bearer” — so the scanner doesn’t redact every transaction hash that happens to be a 64-hex string. Pass 2 — entropy. Shannon entropy (bits/character) on whitespace-tokenized fragments not already covered by a denylist redaction range. Default threshold is 4.5 bits/char over at least 30 characters — high enough to catch typical API key formats, low enough to avoid false-positives on English prose.
import { shannonEntropyBitsPerChar } from '@glideco/secrets-scan';

// Inspect the entropy score of a specific string.
const score = shannonEntropyBitsPerChar('sk-ant-api03-abcdef1234567890');
// → ~4.8 (above the 4.5 default threshold)

CI gate

The Cathedral CI pipeline runs node scripts/scan-secrets.mjs on every PR. The script calls scan() on all staged file contents and exits non-zero on any redaction. Use disableEntropy: true on directories that legitimately contain long base64 blobs (e.g. test/fixtures/).

Reading list