fix(#2198): remove dead scan exports, correct injection-scan docs
scanEntropyAnomalies + shannonEntropy were dead exports with zero production callers — the live hooks (gsd-prompt-guard.js, gsd-read-injection-scanner.js) inline their own pattern subsets for hook independence and never called these functions. Changes: - Remove scanEntropyAnomalies + shannonEntropy from src/security.cts - Remove scanEntropyAnomalies test block from tests/security.test.cjs - Correct REQ-SCAN-INJ-02/-03 in FEATURES.md (EN/zh-CN/ja-JP) to describe what actually runs live (injection patterns, invisible Unicode) vs CI-only (base64-decode, codebase scan) - Correct docs/security/baseline.md §2.4 to clarify live hooks inline patterns, not import from security.cts - Add regression test asserting the corrected contract - scanForInjection retained: it serves as the CI codebase-scanner engine
This commit is contained in:
@@ -477,40 +477,9 @@ export function validatePromptStructure(text: unknown, fileType: string): { vali
|
||||
return { valid: violations.length === 0, violations };
|
||||
}
|
||||
|
||||
// ─── Layer 4: Paragraph-Level Entropy Anomaly Detection ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
function shannonEntropy(text: string): number {
|
||||
if (!text || text.length === 0) return 0;
|
||||
const freq: Record<string, number> = {};
|
||||
for (const ch of text) {
|
||||
freq[ch] = (freq[ch] || 0) + 1;
|
||||
}
|
||||
const len = text.length;
|
||||
let entropy = 0;
|
||||
for (const count of Object.values(freq)) {
|
||||
const p = count / len;
|
||||
entropy -= p * Math.log2(p);
|
||||
}
|
||||
return entropy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan text for paragraphs with anomalously high Shannon entropy.
|
||||
*/
|
||||
export function scanEntropyAnomalies(text: unknown): { clean: boolean; findings: string[] } {
|
||||
if (!text || typeof text !== 'string') {
|
||||
return { clean: true, findings: [] };
|
||||
}
|
||||
const findings: string[] = [];
|
||||
const paragraphs = text.split(/\n\n+/);
|
||||
for (const para of paragraphs) {
|
||||
if (para.length <= 50) continue;
|
||||
const entropy = shannonEntropy(para);
|
||||
if (entropy > 5.5) {
|
||||
findings.push(
|
||||
`High-entropy paragraph detected (${entropy.toFixed(2)} bits/char) — possible encoded payload`
|
||||
);
|
||||
}
|
||||
}
|
||||
return { clean: findings.length === 0, findings };
|
||||
}
|
||||
// NOTE (#2198): scanEntropyAnomalies + shannonEntropy were removed as dead exports.
|
||||
// They had zero production callers — the live hooks (gsd-prompt-guard.js,
|
||||
// gsd-read-injection-scanner.js) inline their own pattern subsets for hook
|
||||
// independence and never called these functions. scanForInjection is retained
|
||||
// below: it serves as the CI codebase-scanner engine
|
||||
// (tests/prompt-injection-scan.security.test.cjs), not as a live hook.
|
||||
|
||||
Reference in New Issue
Block a user