* chore(ingest): pin web-tree-sitter@0.25.10 + tree-sitter-wasms@0.1.13; add multilang-ingest design docs * feat(ingest): multi-language grammar registry (web-tree-sitter, 8 langs, fail-open); 100% cov * feat(ingest): language-aware param-name splitter (py/go/ts/java/c); 100% cov * feat(ingest): tree-sitter CodeBlock extractor with wall-clock parse budget + fail-open * feat(ingest): cross-lang sinks + multilang config + wire tree-sitter into ingestRepository (sync) * feat(ingest): repoint white-box production callers to multilang config + prod regression test * server-init-wiring: load multi-language grammars once at bootstrap initGrammars() runs after LLM init, before app.listen. Internally fail-open (never rejects): on failure the grammar registry stays empty and ingest falls back to the Python regex parser. * adversarial-tests: hostile-input hardening for untrusted target source Malformed per-language source, wrong-language content, binary/non-UTF8, empty, unicode identifiers, 20k-func large file (wall-clock budget), deeply nested input, and a symlink-loop crawl — all must fail-open, never throw or spin. Drives parseFileMultiLang + ingestRepository/crawl. * readme-status + docs: flip white-box status to multi-language ingest README source-code rows now state web-tree-sitter multi-language ingest (fail-open to Python regex). whitebox.ts scope caveat + no-source error message updated off the stale Python-only wording. * coverage-setup: enforce 100% coverage gate on the three new ingest files vitest.config.ts adds a coverage-only block (v8, perFile thresholds=100) scoped to ts-grammars.ts, param-split.ts, ts-parse.ts. Test discovery and env stay on defaults. Edited files gate on new-branch coverage via the regression suites; the server.ts initGrammars bootstrap line is the documented smoke-covered carve-out. * review: fix WASM heap leak, language-scoped fail-open, sink recall/precision Adversarial security + strict code review (two independent subagents) returned one blocking bug and several correctness findings; remediated: BLOCKING #1 — native WASM memory leak: web-tree-sitter Tree/Parser objects were never .delete()'d. Both reviewers reproduced a process-global wedge: after ~7 large parses the shared WASM heap exhausts, every subsequent parse aborts (caught by fail-open), and non-Python ingest silently returns [] forever. Fix: free the tree in a finally; delete the parser in resetParser. Regression test parses ~8MB through the real shared parser 12x. regex, which mis-parses brace/class syntax into corrupt blocks (wrong line spans, lost methods). Now non-.py fail-open returns [] (honest absence); the Python regex only ever runs on .py. Isolated ts-parse-fallback test. http(s).request, axios(config), C exec-family); negative lookbehind stops bare system(/popen(/fetch( from matching Python receivers (os.system etc. still matched, corpus rankings unchanged). Recall+precision tests added. operator sees non-Python degradation. (one-line call-graph edges, no decorators, C++ member methods). * review round 2: fix sink-regex regressions, real timeout test, deterministic leak guard Third review round (correctness + security re-attack + test-quality) against the round-1 fixes surfaced issues in the fixes themselves; remediated: - Sink-regex regressions I introduced: (1) my fetch lookbehind dropped window.fetch/this.fetch (top JS SSRF idiom) — reverted to \bfetch\(; (2) bare .Get/.Post/.Do flagged db.Get/cache.Get/queue.Do as SSRF — receiver-qualified to [Cc]lient. Recall+precision tests cover both; regex is ReDoS-free (timed). - Placebo leak test: the 12x function-dense loop did NOT wedge the parser on machines with heap headroom (proven: passed with tree.delete removed). Replaced with a deterministic vi.spyOn(Tree.prototype,'delete') assertion, verified RED without the fix. - Real (non-mocked) parse-timeout test: parseFileMultiLang gains an injectable budgetMs; a 0ms budget drives the real progressCallback cancellation to []. - runWhiteboxAnalysis swap now has coverage (spy on orchestrator.run) so the 2nd production caller can't silently revert to the Python-only config. - Un-vacuoused weak tests: unicode now asserts the extracted block; nested/ wrong-language wrapped in invariants() + timing bounds. - CI now runs npm run test:coverage (the 100% gate was defined but unenforced). - Security: documented maxFileBytes as the control bounding a single parse's peak WASM memory below the 2GB heap-abort ceiling. - Stale 'fail-open to Python regex' docs fixed (ts-parse, whitebox, server, adversarial); circular-import note added; temp-dir cleanup; honest coverage wording in spec + config. * docs(ingest): align fallback-contract text with the shipped language-scoped fail-open Review feedback (#75, @jmagly): the design docs + one ts-grammars comment still described the pre-implementation 'fall back to the Python regex' model for non-Python files. The shipped contract is language-scoped: .py uses parseFile; any non-.py file with a missing/unsupported/failed grammar or a parse timeout returns [] (never the Python regex, which would mis-parse brace/class syntax into corrupt blocks). Updated every stale reference in multilang-ingest-spec.md, multilang-ingest-plan.md, and ts-grammars.ts so the docs match the security boundary. Docs/comment only — no code change. * fix(test): make the ReDoS wall-clock guard robust under coverage instrumentation Review feedback (#75, @jmagly): the CI step this PR adds (npm run test:coverage = vitest run --coverage) runs the full suite under V8 coverage, and that overhead pushes the pathological-brace DoS timing guard in local-agent-tool-calling.test.ts:69 over its <300ms bound (320 < 300 fails on CI). Raise the bound to 1000ms — still 2x below the ~2100ms quadratic-ReDoS regression it guards against, so it fails hard if the regression returns, but no longer false-fails under coverage/slow CI. Chose the reviewer's option (a) (robust bound) over scoping test:coverage, so the gate stays a simple full-suite run and no test-file enumeration can rot. Verified: npm run test:coverage is green and the 3 new files stay at 100%. * fix(ingest): cover pointer-returning C functions --------- Co-authored-by: Joseph Magly <1159087+jmagly@users.noreply.github.com>
151 lines
5.9 KiB
JSON
Executable File
151 lines
5.9 KiB
JSON
Executable File
{
|
|
"name": "t3mp3st",
|
|
"version": "1.0.0",
|
|
"description": "Tactical Execution Multi-agent Platform for Elite Security Testing",
|
|
"main": "dist/index.js",
|
|
"types": "dist/index.d.ts",
|
|
"type": "module",
|
|
"scripts": {
|
|
"build": "tsc",
|
|
"start": "node dist/cli.js",
|
|
"dev": "tsx src/cli.ts",
|
|
"setup": "tsx src/setup.ts",
|
|
"setup:api": "bash scripts/setup-api.sh",
|
|
"doctor": "node scripts/doctor.mjs",
|
|
"verify-claims": "node scripts/verify-claims.mjs",
|
|
"disclose": "node scripts/disclosure-gen.mjs",
|
|
"test:disclose": "node scripts/test-disclosure-gen.mjs",
|
|
"verify-finding": "node scripts/verify-finding.mjs",
|
|
"test:verify": "node scripts/test-verify-finding.mjs",
|
|
"test:fallback": "node scripts/test-model-fallback.mjs",
|
|
"server": "tsx src/server.ts",
|
|
"server:prod": "node dist/server.js",
|
|
"field:drill": "node scripts/field-drill.mjs",
|
|
"exploit:smoke": "node scripts/exploit-chain-smoke.mjs",
|
|
"arsenal:smoke": "node scripts/arsenal-smoke.mjs",
|
|
"arsenal:doctor": "node scripts/arsenal-doctor.mjs",
|
|
"prompt:audit": "node scripts/prompt-audit.mjs",
|
|
"cve:bench": "node scripts/cve-hunt-bench.mjs",
|
|
"cve:bench:live": "node scripts/cve-hunt-bench.mjs --live",
|
|
"cve:bench:adversarial": "node scripts/cve-hunt-bench.mjs --adversarial",
|
|
"cloud:bench": "node scripts/cloud-misconfig-bench.mjs",
|
|
"cloud:bench:live": "node scripts/cloud-misconfig-bench.mjs --live",
|
|
"mobile:bench": "node scripts/mobile-static-bench.mjs",
|
|
"binary:bench": "node scripts/binary-vuln-bench.mjs",
|
|
"keys": "bash scripts/keys.sh",
|
|
"keys:list": "bash scripts/keys.sh list",
|
|
"obsidivm": "node scripts/obsidivm-bridge.mjs",
|
|
"obsidivm:spec": "node scripts/obsidivm-bridge.mjs spec",
|
|
"obsidivm:bench": "node scripts/obsidivm-bench.mjs",
|
|
"obsidivm:bench:stub": "node scripts/obsidivm-bench.mjs --hunter stub",
|
|
"obsidivm:bench:live": "node scripts/obsidivm-bench.mjs --hunter live",
|
|
"obsidivm:bench:t3mp3st": "node scripts/obsidivm-bench.mjs --hunter t3mp3st",
|
|
"obsidivm:agent": "node scripts/obsidivm-agent.mjs",
|
|
"obsidivm:evolve": "node scripts/obsidivm-evolve.mjs",
|
|
"obsidivm:evolve:reset": "node scripts/obsidivm-evolve.mjs --reset",
|
|
"obsidivm:replay": "node scripts/obsidivm-replay.mjs",
|
|
"obsidivm:ablate": "node scripts/obsidivm-ablate.mjs",
|
|
"cybench": "node scripts/cybench-bench.mjs",
|
|
"cybench:live": "node scripts/cybench-bench.mjs --hunter live",
|
|
"test:flag-grading": "node scripts/test-flag-grading.mjs",
|
|
"test:cybench-ci": "node scripts/test-cybench-ci.mjs",
|
|
"tools:check": "bash scripts/check-tools-image.sh",
|
|
"tools:build": "bash tools/build.sh",
|
|
"install:tools": "bash scripts/install-tools.sh",
|
|
"mcp": "tsx src/mcp-server.ts",
|
|
"mcp:prod": "node dist/mcp-server.js",
|
|
"test": "vitest run src && node scripts/test-ops-preflight.mjs",
|
|
"test:coverage": "vitest run --coverage",
|
|
"test:watch": "vitest src",
|
|
"lint": "eslint src/**/*.ts",
|
|
"typecheck": "tsc --noEmit",
|
|
"test:playbooks": "node scripts/test-playbook-routing.mjs",
|
|
"decompose": "node scripts/decompose.mjs",
|
|
"test:decompose": "node scripts/decompose.mjs --self-test",
|
|
"probe:frontier": "node scripts/refusal-frontier.mjs",
|
|
"test:frontier": "node scripts/refusal-frontier.mjs --self-test",
|
|
"cli-hunt": "node scripts/cli-hunt.mjs",
|
|
"test:cli-hunt": "node scripts/cli-hunt.mjs --self-test",
|
|
"swarm": "node scripts/cli-swarm.mjs",
|
|
"test:swarm": "node scripts/cli-swarm.mjs --self-test",
|
|
"test:no-fitting": "node scripts/test-no-fitting.mjs",
|
|
"test:autodetect": "node scripts/test-autodetect.mjs",
|
|
"test:arsenal-tools": "node scripts/test-arsenal-tools.mjs",
|
|
"lessons": "node scripts/lessons.mjs",
|
|
"test:lessons": "node scripts/lessons.mjs --self-test",
|
|
"test:no-self-fitting": "node scripts/test-no-self-fitting.mjs",
|
|
"test:no-phantom-tools": "vitest run src/__tests__/no-phantom-tools.test.ts",
|
|
"test:spine-live": "vitest run src/__tests__/spine-live.test.ts",
|
|
"smoke": "node scripts/smoke.mjs",
|
|
"smoke:live": "node scripts/smoke.mjs --live",
|
|
"capability": "node scripts/capability-smoke.mjs",
|
|
"gauntlet": "node scripts/capability-smoke.mjs --gauntlet",
|
|
"test:gate": "npm run build --silent && node scripts/test-gate.mjs",
|
|
"ops:preflight": "node scripts/ops-preflight.mjs",
|
|
"test:ops-preflight": "node scripts/test-ops-preflight.mjs",
|
|
"update": "node scripts/update.mjs",
|
|
"update:dry": "node scripts/update.mjs --dry-run",
|
|
"update:hard": "node scripts/update.mjs --hard",
|
|
"test:update": "node scripts/test-update.mjs"
|
|
},
|
|
"bin": {
|
|
"tempest": "./dist/cli.js",
|
|
"t3mp3st": "./dist/cli.js"
|
|
},
|
|
"keywords": [
|
|
"penetration-testing",
|
|
"security",
|
|
"red-team",
|
|
"multi-agent",
|
|
"ai",
|
|
"llm"
|
|
],
|
|
"author": "t3mp3st contributors",
|
|
"license": "AGPL-3.0-or-later",
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "git+https://github.com/elder-plinius/t3mp3st.git"
|
|
},
|
|
"dependencies": {
|
|
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
"boxen": "^7.1.1",
|
|
"chalk": "^5.3.0",
|
|
"cli-table3": "^0.6.3",
|
|
"commander": "^12.1.0",
|
|
"conf": "^12.0.0",
|
|
"cors": "^2.8.5",
|
|
"dotenv": "^16.4.5",
|
|
"eventemitter3": "^5.0.1",
|
|
"express": "^4.18.2",
|
|
"figlet": "^1.7.0",
|
|
"gradient-string": "^2.0.2",
|
|
"inquirer": "^9.2.15",
|
|
"ora": "^8.0.1",
|
|
"tree-sitter-wasms": "0.1.13",
|
|
"tsx": "^4.7.0",
|
|
"web-tree-sitter": "0.25.10"
|
|
},
|
|
"devDependencies": {
|
|
"@eslint/js": "^9.39.2",
|
|
"@types/cors": "^2.8.17",
|
|
"@types/express": "^4.17.21",
|
|
"@types/figlet": "^1.5.8",
|
|
"@types/gradient-string": "^1.1.5",
|
|
"@types/inquirer": "^9.0.7",
|
|
"@types/node": "^20.11.0",
|
|
"@vitest/coverage-v8": "4.1.9",
|
|
"eslint": "^9.39.2",
|
|
"typescript": "^5.3.3",
|
|
"typescript-eslint": "^8.51.0",
|
|
"vitest": "^4.1.9"
|
|
},
|
|
"engines": {
|
|
"node": ">=18.0.0"
|
|
},
|
|
"overrides": {
|
|
"qs": "^6.15.2",
|
|
"hono": "^4.12.25",
|
|
"js-yaml": "^4.2.0"
|
|
}
|
|
}
|