fix(llm-security): scanner robustness — ReDoS, MCP-stdout DoS, redirect loop, atomic writes (#24,#53,#31,#25,#51)
#24 the HTML-obfuscation injection patterns had overlapping unbounded runs plus a required closing quote, so a non-closing input backtracked O(N^2) (~28.7s at the 512KB cap); quantifiers bounded, pathological input now 4ms. #53 mcp-live-inspect buffered MCP-server stdout via readline with no cap, so a hostile stdio server could exhaust memory / throw an uncaught RangeError; replaced with manual line buffering capped at 4MB that rejects pending RPCs and destroys stdout. #31 vsix-fetch's same-host redirect follower had no depth cap (loop hang); added depth>=5 cap mirroring the sibling fetcher. #25/#51 mcp-description-cache and skill-registry wrote JSON via bare writeFileSync (non-atomic: concurrent load-modify-save loses updates, a torn read silently yields an empty registry); both now write a temp file then renameSync. Suite 1931/0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TcQyMTQfyrsAapaCMPxTtQ
This commit is contained in:
parent
f3aaf5479f
commit
207385fbbe
10 changed files with 251 additions and 19 deletions
|
|
@ -4,7 +4,7 @@
|
|||
// Zero external dependencies.
|
||||
|
||||
import { createHash } from 'node:crypto';
|
||||
import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync, statSync } from 'node:fs';
|
||||
import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync, statSync, renameSync } from 'node:fs';
|
||||
import { join, resolve, relative, dirname, basename, extname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
|
|
@ -259,7 +259,11 @@ export function saveRegistry(registry, pluginRoot) {
|
|||
registry.updated = new Date().toISOString();
|
||||
registry.entry_count = Object.keys(registry.entries).length;
|
||||
|
||||
writeFileSync(filePath, JSON.stringify(registry, null, 2) + '\n');
|
||||
// Atomic write (v7.8.3 #51): temp file + rename — a torn write would
|
||||
// parse-fail in loadRegistry and silently reset to an empty registry.
|
||||
const tmpPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
||||
writeFileSync(tmpPath, JSON.stringify(registry, null, 2) + '\n');
|
||||
renameSync(tmpPath, filePath);
|
||||
return filePath;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue