UNPKG

@felixgeelhaar/cclint

Version:

Catch CLAUDE.md drift before Claude misbehaves. Lints CLAUDE.md, skills, subagents, and hooks for Claude Code projects.

63 lines 2.97 kB
import type { Rule } from '../domain/Rule.js'; import { ContextFile } from '../domain/ContextFile.js'; import { Violation } from '../domain/Violation.js'; /** * SecretDetectionRule — flags credentials pasted into CLAUDE.md. * * @remarks * Committing a live API key into a context file is one of the most damaging * authoring mistakes: CLAUDE.md is routinely shared, versioned, and fed to * models, so a leaked key propagates widely. This rule detects the common * provider key shapes (OpenAI, Anthropic, GitHub, AWS, Google, Slack), PEM * private-key blocks, and a high-entropy heuristic for * `KEY=`/`TOKEN=`/`SECRET=`/`PASSWORD=` assignments. * * Findings are ERROR severity. Messages name the kind of secret and mask the * value (first four characters + `…`) so the linter never re-echoes the * credential it is warning about. * * Scope: Markdown files only ({@link appliesTo}). Both prose and fenced code * blocks are scanned — a pasted key is equally dangerous in either. */ export declare class SecretDetectionRule implements Rule { readonly id = "secret-detection"; readonly description = "Detects likely API keys, tokens, and private keys committed to CLAUDE.md"; /** * Ordered so more specific prefixes win before generic ones (Anthropic * `sk-ant-` and OpenAI `sk-proj-` are matched before the classic OpenAI * `sk-` shape). Hyphens in the specific prefixes already prevent the classic * pattern from matching them, but the ordering keeps the intent explicit. */ private static readonly PATTERNS; /** Substrings that mark a value as an obvious placeholder, not a secret. */ private static readonly PLACEHOLDER_TOKENS; /** * Env-style assignment keys that indicate a secret value is being set. The * identifier is required to be upper-snake-case (e.g. `API_TOKEN`, * `SECRET_KEY`) so ordinary prose like "here is a token: …" is not mistaken * for an assignment. */ private static readonly ASSIGNMENT_KEY; private static readonly MIN_ENTROPY_LENGTH; private static readonly MIN_DISTINCT_CHARS; private static readonly MIN_ENTROPY_BITS; appliesTo(file: ContextFile): boolean; lint(file: ContextFile): Violation[]; /** Match the known credential shapes on a single line. */ private collectPatternMatches; /** * Heuristic pass: a `KEY=`/`TOKEN=`/`SECRET=`/`PASSWORD=` assignment whose * value is long, high-entropy, and mixed is very likely a real secret even * when it carries no recognizable provider prefix. */ private collectEntropyMatches; private violation; /** Show only the first four characters, then an ellipsis. */ private static mask; private static looksLikePlaceholder; private static matchesKnownPattern; private static isHighEntropySecret; private static distinctChars; private static shannonEntropy; } //# sourceMappingURL=SecretDetectionRule.d.ts.map