progmune-runtime 2.1.6 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -468
- package/dist/ablation-study.js +144 -0
- package/dist/ablation-study.test.js +18 -0
- package/dist/action-runtime.js +3 -1
- package/dist/active-learning.js +211 -0
- package/dist/analytics.js +139 -0
- package/dist/asset-factory.js +309 -0
- package/dist/asset-growth.js +244 -0
- package/dist/asset-promotion.js +382 -0
- package/dist/asset-quality.js +550 -0
- package/dist/audit/business-translator.js +285 -0
- package/dist/audit/cli.js +66 -0
- package/dist/audit/formatters/html.js +379 -0
- package/dist/audit/formatters/json.js +11 -0
- package/dist/audit/formatters/markdown.js +192 -0
- package/dist/audit/formatters/terminal.js +189 -0
- package/dist/audit/index.js +25 -0
- package/dist/audit/report-builder.js +318 -0
- package/dist/audit/types.js +8 -0
- package/dist/audit.js +3 -3
- package/dist/auto-benchmark-generator.js +137 -0
- package/dist/auto-benchmark-generator.test.js +45 -0
- package/dist/auto-protocol-synthesizer.js +362 -0
- package/dist/auto-protocol-synthesizer.test.js +82 -0
- package/dist/autonomous-patch.js +175 -0
- package/dist/autonomous-patch.test.js +128 -0
- package/dist/badge/badge-server.js +98 -0
- package/dist/behavior-miner.js +442 -0
- package/dist/belief-layer.js +475 -0
- package/dist/benchmark-count.js +5 -0
- package/dist/benchmark-generator.js +211 -0
- package/dist/benchmark-harness.js +201 -0
- package/dist/benchmark-pass-rate.js +7 -0
- package/dist/benchmark-report.js +8 -3
- package/dist/benchmark-save.js +14 -1
- package/dist/bootstrap-validation.js +197 -0
- package/dist/bootstrap-validation.test.js +51 -0
- package/dist/branch-ledger.js +1 -1
- package/dist/capability-gap.js +130 -0
- package/dist/certify-html.js +351 -0
- package/dist/certify.js +326 -0
- package/dist/check.js +4 -4
- package/dist/compliance-miner.js +447 -0
- package/dist/continuous-benchmark.js +194 -0
- package/dist/continuous-benchmark.test.js +116 -0
- package/dist/corpus-stats.js +173 -0
- package/dist/counterfactual-engine.js +288 -0
- package/dist/coverage-dashboard.js +109 -0
- package/dist/coverage-system.test.js +205 -0
- package/dist/cross-repo-precision.js +352 -0
- package/dist/cve-benchmark.js +180 -0
- package/dist/cve-benchmark.test.js +28 -0
- package/dist/cve-collector.js +73 -0
- package/dist/data-quality.js +141 -0
- package/dist/decision-engine.js +388 -0
- package/dist/derive-metadata.js +250 -0
- package/dist/difficulty-active.test.js +198 -0
- package/dist/difficulty-map.js +244 -0
- package/dist/discovery-analytics.js +125 -0
- package/dist/discovery-model.js +149 -0
- package/dist/discovery-optimize.test.js +199 -0
- package/dist/discovery-trace.js +276 -0
- package/dist/discovery-trace.test.js +97 -0
- package/dist/emitter.js +83 -1
- package/dist/enterprise-dashboard.js +405 -0
- package/dist/eval-hardening.js +297 -0
- package/dist/eval-hardening.test.js +85 -0
- package/dist/evaluation-campaign.js +359 -0
- package/dist/evaluation-campaign.test.js +181 -0
- package/dist/evidence-growth.js +143 -0
- package/dist/evidence-repository.js +209 -0
- package/dist/evidence-system.js +441 -0
- package/dist/execute.js +15 -7
- package/dist/experimental/software-physics.js +291 -0
- package/dist/experimental/state-inference.js +516 -0
- package/dist/experimental/unsupervised-physics.js +230 -0
- package/dist/extract-ir-python.js +54 -7
- package/dist/extract-ir.js +376 -12
- package/dist/failure-collector.js +2 -2
- package/dist/failure-corpus.js +322 -9
- package/dist/feedback.js +16 -5
- package/dist/feedback.test.js +49 -0
- package/dist/file-lock.js +1 -1
- package/dist/flywheel-batch.js +292 -0
- package/dist/frameworks/express-cli.js +237 -0
- package/dist/frameworks/express-detector.js +445 -0
- package/dist/frameworks/express-detector.test.js +206 -0
- package/dist/frameworks/index.js +30 -0
- package/dist/frameworks/nestjs-detector.js +302 -0
- package/dist/frameworks/trpc-detector.js +161 -0
- package/dist/frameworks/version-awareness.js +179 -0
- package/dist/function-synonyms.js +164 -0
- package/dist/function-synonyms.test.js +68 -0
- package/dist/generalization.test.js +352 -0
- package/dist/goal-annotator.js +113 -0
- package/dist/goal-planner.js +563 -0
- package/dist/gold-cve.js +164 -0
- package/dist/gold-cve.test.js +104 -0
- package/dist/gold-quality.js +206 -0
- package/dist/gold-tiers.js +241 -0
- package/dist/governance-dashboard.js +327 -0
- package/dist/graph-viz.js +240 -0
- package/dist/guided-frontier.js +195 -0
- package/dist/hierarchical-planner.js +148 -0
- package/dist/identifier-parser.js +260 -0
- package/dist/immune-metrics.js +93 -0
- package/dist/immune-receiver.js +158 -0
- package/dist/immune-reporter.js +1 -1
- package/dist/improvement-orchestrator.js +206 -0
- package/dist/inject-p0-vocabulary.js +300 -0
- package/dist/intent-parser.js +218 -0
- package/dist/invariant-algebra.js +476 -0
- package/dist/invariant-calculus.js +533 -0
- package/dist/ir-utils.js +70 -0
- package/dist/ir-utils.test.js +50 -0
- package/dist/knowledge-api.js +312 -0
- package/dist/knowledge-evolution.js +452 -0
- package/dist/knowledge-explorer.js +506 -0
- package/dist/knowledge-flywheel.js +274 -0
- package/dist/knowledge-governance.js +338 -0
- package/dist/knowledge-governance.test.js +150 -0
- package/dist/knowledge-graph.js +181 -0
- package/dist/knowledge-guided-synth.js +246 -0
- package/dist/knowledge-loop.test.js +77 -0
- package/dist/knowledge-object.js +316 -0
- package/dist/knowledge-package.js +98 -0
- package/dist/kpi-dashboard.js +561 -0
- package/dist/l3-cross-function.js +280 -0
- package/dist/learning-ranker.js +148 -0
- package/dist/learning-ranker.test.js +291 -0
- package/dist/ledger/accountability.js +322 -0
- package/dist/ledger/chain-builder.js +185 -0
- package/dist/ledger/cli.js +222 -0
- package/dist/ledger/index.js +13 -0
- package/dist/ledger/signatures.js +193 -0
- package/dist/ledger/types.js +9 -0
- package/dist/llm.js +74 -3
- package/dist/load-benchmarks.js +8 -3
- package/dist/logger.js +66 -0
- package/dist/logger.test.js +37 -0
- package/dist/logistic-reward.js +339 -0
- package/dist/logistic-reward.test.js +180 -0
- package/dist/macro-graph.js +193 -0
- package/dist/macro-repair.js +183 -0
- package/dist/mcp-server.mjs +1202 -483
- package/dist/memory-layer.js +42 -5
- package/dist/multi-repo-precision.js +422 -0
- package/dist/name-free-protocol.js +425 -0
- package/dist/name-free-protocol.test.js +170 -0
- package/dist/name-scrambling.js +138 -0
- package/dist/name-scrambling.test.js +16 -0
- package/dist/p3-observability.test.js +281 -0
- package/dist/p5-orchestrator.test.js +225 -0
- package/dist/pairwise-preference.js +294 -0
- package/dist/pairwise-preference.test.js +140 -0
- package/dist/planner-constraints.js +104 -0
- package/dist/planner-prompts.js +155 -0
- package/dist/planner-telemetry.js +415 -0
- package/dist/planner-trace.js +214 -0
- package/dist/planner.js +162 -167
- package/dist/plsb/artifact.js +116 -0
- package/dist/plsb/cli.js +71 -0
- package/dist/plsb/index.js +19 -0
- package/dist/plsb/leaderboard.js +249 -0
- package/dist/plsb/report-md.js +156 -0
- package/dist/plsb/schema.js +179 -0
- package/dist/plsb-benchmark.js +284 -0
- package/dist/plsb-benchmark.test.js +119 -0
- package/dist/policy/cli.js +134 -0
- package/dist/policy/engine.js +333 -0
- package/dist/policy/index.js +12 -0
- package/dist/policy/types.js +59 -0
- package/dist/policy-miner.js +505 -0
- package/dist/precision-analyze.js +229 -0
- package/dist/precision-benchmark.js +147 -0
- package/dist/precision-label-c.js +134 -0
- package/dist/precision-label.js +193 -0
- package/dist/precision-report-c.js +149 -0
- package/dist/precision-report.js +246 -0
- package/dist/progmune-status.js +108 -0
- package/dist/proof-engine.js +479 -0
- package/dist/proof-provenance.js +315 -0
- package/dist/protocol-coverage.js +294 -0
- package/dist/protocol-detector.js +1189 -0
- package/dist/protocol-embedding-expanded.js +297 -0
- package/dist/protocol-embedding-expanded.test.js +97 -0
- package/dist/protocol-embedding.js +195 -0
- package/dist/protocol-embedding.test.js +82 -0
- package/dist/protocol-extractor-v2.js +354 -0
- package/dist/protocol-extractor-v2.test.js +140 -0
- package/dist/protocol-extractor.js +310 -0
- package/dist/protocol-extractor.test.js +113 -0
- package/dist/protocol-foundation.js +322 -0
- package/dist/protocol-foundation.test.js +163 -0
- package/dist/protocol-frontier.js +243 -0
- package/dist/protocol-frontier.test.js +92 -0
- package/dist/protocol-gap-analyzer.js +228 -0
- package/dist/protocol-gap-analyzer.test.js +49 -0
- package/dist/protocol-invariants.js +276 -0
- package/dist/protocol-invariants.test.js +111 -0
- package/dist/protocol-knowledge.js +464 -0
- package/dist/protocol-miner.js +343 -0
- package/dist/protocol-mining.js +207 -0
- package/dist/protocol-mining.test.js +37 -0
- package/dist/protocol-registry.js +1 -1
- package/dist/protocol-security-benchmark.js +222 -0
- package/dist/protocol-vulnerability.js +257 -0
- package/dist/protocol-vulnerability.test.js +60 -0
- package/dist/python-benchmark.js +120 -0
- package/dist/python-emitter.js +163 -45
- package/dist/python-protocol-extractor.js +187 -0
- package/dist/python-protocol-extractor.test.js +116 -0
- package/dist/realworld-benchmark.js +646 -0
- package/dist/realworld-benchmark.test.js +36 -0
- package/dist/repair-arch.test.js +411 -0
- package/dist/repair-evolution.test.js +454 -0
- package/dist/repair-executor.js +719 -0
- package/dist/repair-proposal.js +4 -4
- package/dist/repair-ranker.js +141 -0
- package/dist/repair-strategies.js +419 -0
- package/dist/repair-taxonomy.js +234 -0
- package/dist/repair-types.js +12 -0
- package/dist/repo-evaluator.js +250 -0
- package/dist/repo-evaluator.test.js +128 -0
- package/dist/resource-abstraction.js +242 -0
- package/dist/resource-detector.js +211 -0
- package/dist/result.test.js +43 -0
- package/dist/reward-system.js +411 -0
- package/dist/reward-system.test.js +175 -0
- package/dist/risk-model.js +215 -0
- package/dist/rule-miner.js +234 -7
- package/dist/rule-specificity.js +254 -0
- package/dist/runtime-types.js +27 -0
- package/dist/scaffold.js +208 -0
- package/dist/scale-collector.test.js +101 -0
- package/dist/scale-trajectory-collector.js +128 -0
- package/dist/sdk.js +250 -0
- package/dist/search-planner.js +4 -41
- package/dist/semantic-snapshot.js +1 -1
- package/dist/semantic-topology.js +121 -0
- package/dist/semantic-trace.js +310 -317
- package/dist/sequence-extractor.js +343 -0
- package/dist/skill-library.js +245 -0
- package/dist/skill-planner.test.js +189 -0
- package/dist/software-physics.js +291 -0
- package/dist/software-physics.test.js +81 -0
- package/dist/ssg-precision.js +478 -0
- package/dist/ssg-validator.js +71 -21
- package/dist/state-inference-doubleblind.test.js +160 -0
- package/dist/state-inference.js +516 -0
- package/dist/state-inference.test.js +115 -0
- package/dist/state-machine-fingerprint.js +345 -0
- package/dist/state-machine-fingerprint.test.js +120 -0
- package/dist/state-miner.js +386 -0
- package/dist/state-name-inference.js +213 -0
- package/dist/state-name-inference.test.js +69 -0
- package/dist/strategy-planner.js +262 -96
- package/dist/strategy-planner.test.js +135 -0
- package/dist/telemetry-analytics.test.js +402 -0
- package/dist/terminal-format.js +68 -0
- package/dist/terminal-format.test.js +83 -0
- package/dist/topology-factory.js +196 -0
- package/dist/topology-representation.js +242 -0
- package/dist/topology-representation.test.js +27 -0
- package/dist/trajectory-augmentation.js +254 -0
- package/dist/trajectory-augmentation.test.js +63 -0
- package/dist/trajectory-corpus.js +440 -0
- package/dist/trajectory-corpus.test.js +32 -0
- package/dist/trajectory-feedback.test.js +116 -0
- package/dist/transition-synthesizer.js +286 -0
- package/dist/transition-synthesizer.test.js +123 -0
- package/dist/trust/api-semantic-mapper.js +809 -0
- package/dist/trust/call-graph-propagator.js +225 -0
- package/dist/trust/cli.js +122 -0
- package/dist/trust/compliance-scorer.js +283 -0
- package/dist/trust/confidence-calculator.js +261 -0
- package/dist/trust/engine.js +1145 -0
- package/dist/trust/explainability.js +85 -0
- package/dist/trust/formatters/ci.js +42 -0
- package/dist/trust/formatters/json.js +11 -0
- package/dist/trust/formatters/terminal.js +152 -0
- package/dist/trust/index.js +39 -0
- package/dist/trust/phase1-verify.js +171 -0
- package/dist/trust/protocol-domain-validator.js +697 -0
- package/dist/trust/score-calculator.js +282 -0
- package/dist/trust/ssg-bridge.js +641 -0
- package/dist/trust/ssg-bridge.test.js +269 -0
- package/dist/trust/types.js +67 -0
- package/dist/trust/violation-trace.js +335 -0
- package/dist/trust-api.js +179 -0
- package/dist/trust-calibration.js +279 -0
- package/dist/unknown-protocol-discovery.js +339 -0
- package/dist/unknown-protocol-discovery.test.js +102 -0
- package/dist/unsupervised-physics.js +230 -0
- package/dist/unsupervised-physics.test.js +95 -0
- package/dist/utils.test.js +37 -0
- package/dist/validator.js +187 -10
- package/dist/verification-intelligence.js +475 -0
- package/dist/verify-api.js +432 -0
- package/dist/vi-impact-report.js +293 -0
- package/dist/wl-fingerprint.js +162 -0
- package/dist/wl-fingerprint.test.js +130 -0
- package/dist/zeroshot-strategy.js +139 -0
- package/docs/Progmune_/346/212/225/350/265/204/344/272/272/347/231/275/347/232/256/344/271/246_v2.0.html +576 -0
- package/docs/Progmune_/351/241/271/347/233/256/345/205/250/350/247/243.html +710 -0
- package/package.json +74 -7
- package/protocols.json +1956 -50
- package/.dockerignore +0 -14
- package/.mcp.json +0 -11
- package/.progmune_allowlist +0 -50
- package/.test_report/test_report.md +0 -87
- package/Dockerfile +0 -9
- package/FAQ.md +0 -167
- package/WHITEPAPER.md +0 -540
- package/demo-project/auth.ts +0 -55
- package/demo-project/tsconfig.json +0 -8
- package/dist/acl-breakdown.js +0 -13
- package/dist/all-sessions.js +0 -11
- package/dist/antibody-stats.js +0 -11
- package/dist/branch-tree-count.js +0 -14
- package/dist/common-fixpath.js +0 -12
- package/dist/constraint-types.js +0 -12
- package/dist/exec-metrics.js +0 -11
- package/dist/failure-report.js +0 -11
- package/dist/fast-path-hits.js +0 -13
- package/dist/fingerprint-list.js +0 -15
- package/dist/gen-history-log.js +0 -13
- package/dist/heatmap-data.js +0 -11
- package/dist/recent-session.js +0 -12
- package/dist/svl-distribution.js +0 -11
- package/dist/terminal-status.js +0 -11
- package/dist/token-savings.js +0 -11
- package/dist/total-repairs.js +0 -12
- package/dist/unresolved-count.js +0 -12
- package/dist/valid-fingerprints.js +0 -13
- package/dist/verify-ledgers.js +0 -11
- package/docs/whitepaper-style.css +0 -77
- package/docs/whitepaper-v2.1.md +0 -609
- package/docs/whitepaper-v2.2.md +0 -1064
- package/docs/whitepaper-v2.2.pdf +0 -0
- package/fly.toml +0 -31
- package/public/dashboard.html +0 -119
- package/server/hub.js +0 -116
- package/test/replay-golden/sess_1780063202050_mgeld.json +0 -9
- package/test/replay-golden/sess_1780064032560_gocld.json +0 -354
- package/test/replay-golden/sess_1780064413331_s2709.json +0 -606
- package/test/replay-golden/sess_1780064792710_y3avo.json +0 -614
- package/test/replay-golden.ts +0 -84
- package/test_benchmark.js +0 -165
- package/test_comprehensive.mjs +0 -638
- package/test_concurrency.js +0 -129
- package/test_ir_robustness.js +0 -85
- package/test_semantic_contracts.js +0 -269
- package/test_ssg_stress.js +0 -156
- package/test_svl3.js +0 -58
- package/tsconfig.json +0 -17
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Risk Model — Pattern × Severity × Policy
|
|
4
|
+
*
|
|
5
|
+
* Upgrades detection from boolean (valid/invalid) to structured risk assessment.
|
|
6
|
+
*
|
|
7
|
+
* Architecture:
|
|
8
|
+
* Protocol → Concept → DetectionPattern → RiskObject → Policy → Decision
|
|
9
|
+
*
|
|
10
|
+
* Completeness becomes a knowledge-layer metric. Risk drives governance.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.DETECTION_PATTERNS = void 0;
|
|
14
|
+
exports.assessRisk = assessRisk;
|
|
15
|
+
// ═══════════════════════════════════════════════════════════════
|
|
16
|
+
// Detection Patterns (evidence-backed, weighted by severity)
|
|
17
|
+
// ═══════════════════════════════════════════════════════════════
|
|
18
|
+
exports.DETECTION_PATTERNS = [
|
|
19
|
+
// ── TLS Patterns ──
|
|
20
|
+
{
|
|
21
|
+
id: "TLS-MISSING-FINISHED",
|
|
22
|
+
name: "Missing Finished",
|
|
23
|
+
description: "TLS handshake started but Finished message not sent — handshake incomplete. Attacker may intercept before authentication completes.",
|
|
24
|
+
protocolName: "TLS Handshake",
|
|
25
|
+
conceptName: "Finished",
|
|
26
|
+
severity: "Critical",
|
|
27
|
+
confidence: 91,
|
|
28
|
+
evidenceSequences: 135,
|
|
29
|
+
detect: (calls) => {
|
|
30
|
+
const hasInit = calls.some(c => /\b(\w*ssl\w*init|\w*SSL\w*new|\w*tls\w*init)\b/i.test(c));
|
|
31
|
+
const hasConnect = calls.some(c => /\b(\w*ssl\w*connect|\w*ssl\w*handshake|\w*tls\w*connect)\b/i.test(c));
|
|
32
|
+
const hasFree = calls.some(c => /\b(\w*ssl\w*free|\w*SSL\w*cleanup|\w*SSL_CTX_free)\b/i.test(c));
|
|
33
|
+
return (hasInit || hasConnect) && !hasFree;
|
|
34
|
+
},
|
|
35
|
+
detail: "TLS handshake initiated but no Finished/free step detected. Connection may remain open or unverified.",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: "TLS-NO-INIT",
|
|
39
|
+
name: "TLS Without Init",
|
|
40
|
+
description: "TLS connect or read without prior initialization — possible use of uninitialized SSL context.",
|
|
41
|
+
protocolName: "TLS Handshake",
|
|
42
|
+
conceptName: "ClientHello",
|
|
43
|
+
severity: "High",
|
|
44
|
+
confidence: 85,
|
|
45
|
+
evidenceSequences: 135,
|
|
46
|
+
detect: (calls) => {
|
|
47
|
+
const hasInit = calls.some(c => /\b(\w*ssl\w*init|\w*SSL\w*new|\w*tls\w*init)\b/i.test(c));
|
|
48
|
+
const hasConnect = calls.some(c => /\b(\w*ssl\w*connect|\w*ssl\w*handshake)\b/i.test(c));
|
|
49
|
+
return hasConnect && !hasInit;
|
|
50
|
+
},
|
|
51
|
+
detail: "SSL connect/handshake called without prior context initialization. Missing SSL_CTX_new or equivalent.",
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: "TLS-DOUBLE-FREE",
|
|
55
|
+
name: "TLS Double Free",
|
|
56
|
+
description: "SSL free called on same object twice, or free without matching init. Normal cleanup (SSL_free + SSL_CTX_free for SSL_new + SSL_CTX_new) is safe.",
|
|
57
|
+
protocolName: "TLS Handshake",
|
|
58
|
+
conceptName: "Finished",
|
|
59
|
+
severity: "Critical",
|
|
60
|
+
confidence: 88,
|
|
61
|
+
evidenceSequences: 135,
|
|
62
|
+
detect: (calls) => {
|
|
63
|
+
// Count distinct SSL object types freed (not just total free calls)
|
|
64
|
+
const sslFreeCount = calls.filter(c => /\bSSL_free\b/i.test(c)).length;
|
|
65
|
+
const ctxFreeCount = calls.filter(c => /\bSSL_CTX_free\b/i.test(c)).length;
|
|
66
|
+
const sslNewCount = calls.filter(c => /\bSSL_new\b/i.test(c)).length;
|
|
67
|
+
const ctxNewCount = calls.filter(c => /\bSSL_CTX_new\b/i.test(c)).length;
|
|
68
|
+
// Violation: more frees than news for the SAME object type
|
|
69
|
+
const sslDoubleFree = sslFreeCount > sslNewCount;
|
|
70
|
+
const ctxDoubleFree = ctxFreeCount > ctxNewCount;
|
|
71
|
+
return (sslDoubleFree || ctxDoubleFree) && (sslFreeCount + ctxFreeCount >= 2);
|
|
72
|
+
},
|
|
73
|
+
detail: "SSL_free or SSL_CTX_free called more times than their matching init. Normal cleanup (1 SSL_free + 1 SSL_CTX_free for 1 SSL_new + 1 SSL_CTX_new) is safe.",
|
|
74
|
+
},
|
|
75
|
+
// ── SSH Patterns ──
|
|
76
|
+
{
|
|
77
|
+
id: "SSH-NO-AUTH",
|
|
78
|
+
name: "SSH Without Auth",
|
|
79
|
+
description: "SSH connection established but no authentication step — possible unauthorized access.",
|
|
80
|
+
protocolName: "SSH Connection",
|
|
81
|
+
conceptName: "Authentication",
|
|
82
|
+
severity: "Critical",
|
|
83
|
+
confidence: 78,
|
|
84
|
+
evidenceSequences: 135,
|
|
85
|
+
detect: (calls) => {
|
|
86
|
+
const hasInit = calls.some(c => /\b(\w*ssh\w*init|ssh\w*setup)\b/i.test(c));
|
|
87
|
+
const hasAuth = calls.some(c => /\b(\w*ssh\w*auth|\w*ssh\w*login)\b/i.test(c));
|
|
88
|
+
return hasInit && !hasAuth;
|
|
89
|
+
},
|
|
90
|
+
detail: "SSH session initialized but no authentication step. Connection may be unauthenticated.",
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
id: "SSH-NO-CLEANUP",
|
|
94
|
+
name: "SSH Missing Cleanup",
|
|
95
|
+
description: "SSH session started but never properly closed — potential resource leak or session hijacking.",
|
|
96
|
+
protocolName: "SSH Connection",
|
|
97
|
+
conceptName: "Channel",
|
|
98
|
+
severity: "High",
|
|
99
|
+
confidence: 78,
|
|
100
|
+
evidenceSequences: 135,
|
|
101
|
+
detect: (calls) => {
|
|
102
|
+
const hasInit = calls.some(c => /\b(\w*ssh\w*init)\b/i.test(c));
|
|
103
|
+
const hasDone = calls.some(c => /\b(\w*ssh\w*done|\w*ssh\w*close|\w*ssh\w*free|\w*ssh\w*disconnect)\b/i.test(c));
|
|
104
|
+
return hasInit && !hasDone;
|
|
105
|
+
},
|
|
106
|
+
detail: "SSH session initialized but never closed. Resource leak or session fixation risk.",
|
|
107
|
+
},
|
|
108
|
+
// ── HTTP Patterns ──
|
|
109
|
+
{
|
|
110
|
+
id: "HTTP-NO-RESPONSE",
|
|
111
|
+
name: "HTTP Without Response",
|
|
112
|
+
description: "HTTP request sent but no response processed — possible incomplete request handling.",
|
|
113
|
+
protocolName: "HTTP Request",
|
|
114
|
+
conceptName: "Response",
|
|
115
|
+
severity: "Medium",
|
|
116
|
+
confidence: 80,
|
|
117
|
+
evidenceSequences: 150,
|
|
118
|
+
detect: (calls) => {
|
|
119
|
+
const hasInit = calls.some(c => /\b(\w*http\w*init|\w*http\w*handler)\b/i.test(c));
|
|
120
|
+
const hasSend = calls.some(c => /\b(\w*http\w*send|\w*http\w*process|ap_pass_brigade)\b/i.test(c));
|
|
121
|
+
return (hasInit || hasSend) && !calls.some(c => /\b(\w*http\w*cleanup|\w*http\w*finalize)\b/i.test(c));
|
|
122
|
+
},
|
|
123
|
+
detail: "HTTP request initiated but no cleanup/finalize step. Connection may hang.",
|
|
124
|
+
},
|
|
125
|
+
// ── Resource Patterns ──
|
|
126
|
+
{
|
|
127
|
+
id: "RES-ACQUIRE-NO-RELEASE",
|
|
128
|
+
name: "Resource Acquire Without Release",
|
|
129
|
+
description: "Resource acquired (malloc, open, SSL_new) but never released — definite resource leak.",
|
|
130
|
+
protocolName: "Resource Lifecycle",
|
|
131
|
+
severity: "Critical",
|
|
132
|
+
confidence: 98,
|
|
133
|
+
evidenceSequences: 250,
|
|
134
|
+
detect: (calls) => {
|
|
135
|
+
const acquireRe = /\b(malloc|calloc|SSL_CTX_new|SSL_new|BIO_new|open|fopen|socket)\b/i;
|
|
136
|
+
const releaseRe = /\b(free|SSL_CTX_free|SSL_free|BIO_free|close|fclose)\b/i;
|
|
137
|
+
const hasAcquire = calls.some(c => acquireRe.test(c) && !/\b(create|alloc|new|init)\w*\b/i.test(c));
|
|
138
|
+
const hasRelease = calls.some(c => releaseRe.test(c));
|
|
139
|
+
return hasAcquire && !hasRelease;
|
|
140
|
+
},
|
|
141
|
+
detail: "Resource acquired but no matching release call. Definite resource leak.",
|
|
142
|
+
},
|
|
143
|
+
];
|
|
144
|
+
// ═══════════════════════════════════════════════════════════════
|
|
145
|
+
// Risk Assessment Engine
|
|
146
|
+
// ═══════════════════════════════════════════════════════════════
|
|
147
|
+
function assessRisk(calls, protocolName) {
|
|
148
|
+
const patterns = exports.DETECTION_PATTERNS.filter(p => {
|
|
149
|
+
if (protocolName && p.protocolName !== protocolName)
|
|
150
|
+
return false;
|
|
151
|
+
return p.detect(calls);
|
|
152
|
+
});
|
|
153
|
+
if (patterns.length === 0) {
|
|
154
|
+
return {
|
|
155
|
+
riskLevel: "Low",
|
|
156
|
+
patterns: [],
|
|
157
|
+
knowledgeUnit: { id: "", name: protocolName || "Unknown", version: "", rfc: undefined },
|
|
158
|
+
recommendation: "Allow",
|
|
159
|
+
summary: "No known risk patterns detected.",
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
// Highest severity pattern determines risk level
|
|
163
|
+
const severityOrder = ["Critical", "High", "Medium", "Low"];
|
|
164
|
+
const maxSeverity = patterns.reduce((max, p) => {
|
|
165
|
+
const i1 = severityOrder.indexOf(p.severity);
|
|
166
|
+
const i2 = severityOrder.indexOf(max);
|
|
167
|
+
return i1 < i2 ? p.severity : max;
|
|
168
|
+
}, "Low");
|
|
169
|
+
// Recommendation based on highest severity
|
|
170
|
+
let recommendation;
|
|
171
|
+
if (maxSeverity === "Critical")
|
|
172
|
+
recommendation = "Block";
|
|
173
|
+
else if (maxSeverity === "High")
|
|
174
|
+
recommendation = "Warn";
|
|
175
|
+
else
|
|
176
|
+
recommendation = "Allow";
|
|
177
|
+
// Look up Knowledge Unit
|
|
178
|
+
let unitId = "", unitVersion = "", unitRfc;
|
|
179
|
+
try {
|
|
180
|
+
const { buildKnowledgeBase } = require("./protocol-knowledge");
|
|
181
|
+
const kb = buildKnowledgeBase();
|
|
182
|
+
const unit = kb.units.find((u) => u.name === patterns[0].protocolName);
|
|
183
|
+
if (unit) {
|
|
184
|
+
unitId = unit.id;
|
|
185
|
+
unitVersion = unit.currentVersion;
|
|
186
|
+
unitRfc = unit.rfcReference;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
catch { /* KB unavailable */ }
|
|
190
|
+
return {
|
|
191
|
+
riskLevel: maxSeverity,
|
|
192
|
+
patterns: patterns.map(p => ({
|
|
193
|
+
patternId: p.id,
|
|
194
|
+
patternName: p.name,
|
|
195
|
+
severity: p.severity,
|
|
196
|
+
confidence: p.confidence,
|
|
197
|
+
concept: p.conceptName,
|
|
198
|
+
detail: p.detail || p.description,
|
|
199
|
+
})),
|
|
200
|
+
knowledgeUnit: { id: unitId, name: patterns[0].protocolName, version: unitVersion, rfc: unitRfc },
|
|
201
|
+
recommendation,
|
|
202
|
+
summary: patterns.length === 1
|
|
203
|
+
? `${patterns[0].name}: ${patterns[0].detail || patterns[0].description}`
|
|
204
|
+
: `${patterns.length} risk patterns detected. Highest: ${patterns[0].name} (${maxSeverity}).`,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
// ═══════════════════════════════════════════════════════════════
|
|
208
|
+
// CLI
|
|
209
|
+
// ═══════════════════════════════════════════════════════════════
|
|
210
|
+
if (require.main === module) {
|
|
211
|
+
const args = process.argv.slice(2);
|
|
212
|
+
const calls = args.length > 0 ? args : ["SSL_CTX_new", "SSL_connect"];
|
|
213
|
+
const risk = assessRisk(calls);
|
|
214
|
+
console.log(JSON.stringify(risk, null, 2));
|
|
215
|
+
}
|
package/dist/rule-miner.js
CHANGED
|
@@ -1,10 +1,237 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Rule Miner — generates actionable protocol rules from failure patterns.
|
|
4
|
+
*
|
|
5
|
+
* Upgrades the passive diagnostic to an active rule generator:
|
|
6
|
+
* 1. Analyses the failure corpus for recurring SVL-4 violations
|
|
7
|
+
* 2. Generates FunctionProtocol entries from fix paths
|
|
8
|
+
* 3. Can merge rules into protocols.json (dry-run by default)
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
2
43
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.mineRules = mineRules;
|
|
45
|
+
exports.toProtocolEntries = toProtocolEntries;
|
|
46
|
+
exports.applyMinedRules = applyMinedRules;
|
|
47
|
+
exports.mineAntibodiesV2 = mineAntibodiesV2;
|
|
48
|
+
const fs = __importStar(require("fs"));
|
|
49
|
+
const path = __importStar(require("path"));
|
|
3
50
|
const failure_corpus_1 = require("./failure-corpus");
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Mine protocol rules from failure patterns.
|
|
53
|
+
*
|
|
54
|
+
* Analyses SVL-4 protocol violations to infer state transitions
|
|
55
|
+
* that should be encoded as permanent protocol rules.
|
|
56
|
+
*/
|
|
57
|
+
function mineRules() {
|
|
58
|
+
const genome = (0, failure_corpus_1.getFailureGenome)();
|
|
59
|
+
const patterns = (0, failure_corpus_1.getTopFailurePatterns)(10);
|
|
60
|
+
const mined = [];
|
|
61
|
+
// Strategy 1: Convert common fix paths into protocol rules
|
|
62
|
+
const ssgFixes = genome.commonFixPaths.filter(f => f.violation === "SVL-4");
|
|
63
|
+
for (const fix of ssgFixes) {
|
|
64
|
+
if (fix.fixPath.length < 2)
|
|
65
|
+
continue;
|
|
66
|
+
for (let i = 0; i < fix.fixPath.length - 1; i++) {
|
|
67
|
+
const currentFn = fix.fixPath[i];
|
|
68
|
+
const nextFn = fix.fixPath[i + 1];
|
|
69
|
+
mined.push({
|
|
70
|
+
function: currentFn,
|
|
71
|
+
pre_states: [],
|
|
72
|
+
post_states: [`READY_FOR_${nextFn.toUpperCase()}`],
|
|
73
|
+
namespace: "_global",
|
|
74
|
+
reason: `Fix path ${fix.fixPath.join(" → ")} observed ${fix.count} times`,
|
|
75
|
+
confidence: fix.count,
|
|
76
|
+
});
|
|
77
|
+
mined.push({
|
|
78
|
+
function: nextFn,
|
|
79
|
+
pre_states: [`READY_FOR_${nextFn.toUpperCase()}`],
|
|
80
|
+
post_states: ["COMPLETED"],
|
|
81
|
+
namespace: "_global",
|
|
82
|
+
reason: `Fix path continuation: ${currentFn} → ${nextFn}`,
|
|
83
|
+
confidence: fix.count,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Strategy 2: Pattern-based rules from top violations
|
|
88
|
+
const PATTERN_RULES = {
|
|
89
|
+
symbol_existence: { pre: [], post: ["IR_VALIDATED"], desc: "只使用 IR 中已导出的函数,禁止编造函数名" },
|
|
90
|
+
type_mismatch: { pre: [], post: ["TYPE_CHECKED"], desc: "检查参数类型与 IR 签名一致后再调用" },
|
|
91
|
+
dataflow: { pre: [], post: ["DATAFLOW_VALID"], desc: "变量必须先声明再使用,避免循环引用" },
|
|
92
|
+
protocol: { pre: ["INIT"], post: ["PROTOCOL_COMPLIANT"], desc: "严格遵循 SSG 协议状态顺序调用函数" },
|
|
93
|
+
missing_import: { pre: [], post: ["IMPORT_RESOLVED"], desc: "只从已导出的模块导入符号" },
|
|
94
|
+
params_undefined: { pre: [], post: ["PARAMS_SAFE"], desc: "调用 .map/.filter 前检查对象是否为数组,使用 (obj || [])" },
|
|
95
|
+
};
|
|
96
|
+
for (const p of patterns) {
|
|
97
|
+
// Extract constraint type from pattern (e.g. "SVL-1:symbol_existence" → "symbol_existence")
|
|
98
|
+
const constraintMatch = p.pattern.match(/SVL-\d:(.+)/);
|
|
99
|
+
if (!constraintMatch)
|
|
100
|
+
continue;
|
|
101
|
+
const constraintType = constraintMatch[1];
|
|
102
|
+
const rule = PATTERN_RULES[constraintType];
|
|
103
|
+
if (rule) {
|
|
104
|
+
mined.push({
|
|
105
|
+
function: constraintType,
|
|
106
|
+
pre_states: rule.pre,
|
|
107
|
+
post_states: rule.post,
|
|
108
|
+
namespace: "mined",
|
|
109
|
+
reason: `Pattern "${constraintType}" occurred ${p.count} times → ${rule.desc}`,
|
|
110
|
+
confidence: p.count,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
// Generic fallback for unknown patterns
|
|
115
|
+
mined.push({
|
|
116
|
+
function: constraintType,
|
|
117
|
+
pre_states: ["INIT"],
|
|
118
|
+
post_states: ["VALIDATED"],
|
|
119
|
+
namespace: "mined",
|
|
120
|
+
reason: `Unknown pattern "${constraintType}" occurred ${p.count} times`,
|
|
121
|
+
confidence: p.count,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// Deduplicate by function name (keep highest confidence)
|
|
126
|
+
const seen = new Map();
|
|
127
|
+
for (const rule of mined) {
|
|
128
|
+
const key = `${rule.function}:${rule.namespace}`;
|
|
129
|
+
if (!seen.has(key) || seen.get(key).confidence < rule.confidence) {
|
|
130
|
+
seen.set(key, rule);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return [...seen.values()].sort((a, b) => b.confidence - a.confidence);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Convert mined rules to FunctionProtocol format compatible with protocols.json.
|
|
137
|
+
*/
|
|
138
|
+
function toProtocolEntries(rules) {
|
|
139
|
+
const entries = {};
|
|
140
|
+
for (const r of rules) {
|
|
141
|
+
entries[r.function] = {
|
|
142
|
+
pre_states: r.pre_states,
|
|
143
|
+
post_states: r.post_states,
|
|
144
|
+
...(r.invalidate && r.invalidate.length > 0 ? { invalidate: r.invalidate } : {}),
|
|
145
|
+
...(r.namespace !== "_global" ? { namespace: r.namespace } : {}),
|
|
146
|
+
_mined: { reason: r.reason, confidence: r.confidence },
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
return entries;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Merge mined rules into protocols.json.
|
|
153
|
+
* Dry-run by default — set apply=true to write.
|
|
154
|
+
*/
|
|
155
|
+
function applyMinedRules(apply = false) {
|
|
156
|
+
const mined = mineRules();
|
|
157
|
+
const protocolsPath = path.resolve(__dirname, "..", "protocols.json");
|
|
158
|
+
let existing = {};
|
|
159
|
+
if (fs.existsSync(protocolsPath)) {
|
|
160
|
+
existing = JSON.parse(fs.readFileSync(protocolsPath, "utf-8"));
|
|
161
|
+
}
|
|
162
|
+
const newEntries = toProtocolEntries(mined);
|
|
163
|
+
let merged = 0;
|
|
164
|
+
let skipped = 0;
|
|
165
|
+
for (const [fn, rule] of Object.entries(newEntries)) {
|
|
166
|
+
if (existing[fn]) {
|
|
167
|
+
skipped++;
|
|
168
|
+
continue; // Don't overwrite existing rules
|
|
169
|
+
}
|
|
170
|
+
existing[fn] = rule;
|
|
171
|
+
merged++;
|
|
172
|
+
}
|
|
173
|
+
if (apply && merged > 0) {
|
|
174
|
+
// Backup original
|
|
175
|
+
const backup = protocolsPath + ".bak";
|
|
176
|
+
if (fs.existsSync(protocolsPath)) {
|
|
177
|
+
fs.copyFileSync(protocolsPath, backup);
|
|
178
|
+
}
|
|
179
|
+
fs.writeFileSync(protocolsPath, JSON.stringify(existing, null, 2));
|
|
180
|
+
console.error(`[规则挖掘] 已将 ${merged} 条规则写入 ${protocolsPath}(备份: ${backup})`);
|
|
181
|
+
}
|
|
182
|
+
return { rules: mined, merged, skipped, dryRun: !apply };
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Mine antibody candidates from Schema v2 failure records.
|
|
186
|
+
* Returns patterns that recurred >= minCount times.
|
|
187
|
+
*/
|
|
188
|
+
function mineAntibodiesV2(minCount = 3) {
|
|
189
|
+
const all = (0, failure_corpus_1.loadTrajectories)().filter(t => t.result === "violation");
|
|
190
|
+
if (all.length === 0)
|
|
191
|
+
return [];
|
|
192
|
+
const groups = {};
|
|
193
|
+
for (const t of all) {
|
|
194
|
+
const key = `${t.violation?.type || "other"}|${t.protocol}`;
|
|
195
|
+
if (!groups[key])
|
|
196
|
+
groups[key] = [];
|
|
197
|
+
groups[key].push(t);
|
|
198
|
+
}
|
|
199
|
+
const candidates = [];
|
|
200
|
+
for (const [key, records] of Object.entries(groups)) {
|
|
201
|
+
if (records.length < minCount)
|
|
202
|
+
continue;
|
|
203
|
+
const [violationType, protocol] = key.split("|");
|
|
204
|
+
const avgDepth = Math.round(records.reduce((s, t) => s + t.context.nestingDepth, 0) / records.length);
|
|
205
|
+
const fixPaths = [...new Set(records.flatMap(t => t.violation?.fixPath || []))];
|
|
206
|
+
const avgSuccess = records.length > 0
|
|
207
|
+
? records.reduce((s, t) => s + t.successRate, 0) / records.length
|
|
208
|
+
: 0;
|
|
209
|
+
const timestamps = records.map(f => f.timestamp).sort();
|
|
210
|
+
candidates.push({
|
|
211
|
+
id: `ab2_${violationType}_${protocol}_${Date.now()}`,
|
|
212
|
+
violationType: violationType,
|
|
213
|
+
protocol,
|
|
214
|
+
contextPattern: { nestingDepth: avgDepth },
|
|
215
|
+
fixPath: fixPaths.slice(0, 5),
|
|
216
|
+
promoteToStatic: ["resource_leak", "protocol_violation", "illegal_state_transition"].includes(violationType),
|
|
217
|
+
occurrenceCount: records.length,
|
|
218
|
+
avgSuccessRate: avgSuccess,
|
|
219
|
+
firstSeen: timestamps[0] || "N/A",
|
|
220
|
+
lastSeen: timestamps[timestamps.length - 1] || "N/A",
|
|
221
|
+
minedAt: new Date().toISOString(),
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
return candidates.sort((a, b) => b.occurrenceCount - a.occurrenceCount);
|
|
225
|
+
}
|
|
226
|
+
/** CLI entry point: print mined rules without applying. */
|
|
227
|
+
if (require.main === module) {
|
|
228
|
+
const result = applyMinedRules(false);
|
|
229
|
+
console.log(`\n挖掘到 ${result.rules.length} 条候选规则(dry-run):`);
|
|
230
|
+
for (const r of result.rules) {
|
|
231
|
+
console.log(` ${r.function}: [${r.pre_states.join(",")}] → [${r.post_states.join(",")}] (置信度: ${r.confidence})`);
|
|
232
|
+
console.log(` 原因: ${r.reason}`);
|
|
233
|
+
}
|
|
234
|
+
if (result.rules.length > 0) {
|
|
235
|
+
console.log(`\n应用规则: node -e "require('./dist/rule-miner').applyMinedRules(true)"`);
|
|
236
|
+
}
|
|
237
|
+
}
|