agentic-qe 3.6.11 → 3.6.12
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/.claude/helpers/learning-service.mjs +2 -0
- package/.claude/helpers/statusline-v3.cjs +2 -0
- package/.claude/skills/skills-manifest.json +1 -1
- package/package.json +1 -1
- package/scripts/migrate-v2-to-v3-memory.js +2 -0
- package/scripts/sync-claude-flow.cjs +1 -0
- package/v3/CHANGELOG.md +14 -0
- package/v3/dist/adapters/claude-flow/trajectory-bridge.js +2 -2
- package/v3/dist/adapters/claude-flow/trajectory-bridge.js.map +1 -1
- package/v3/dist/benchmarks/performance-benchmarks.js +1 -1
- package/v3/dist/cli/bundle.js +198 -91
- package/v3/dist/cli/commands/learning-helpers.d.ts.map +1 -1
- package/v3/dist/cli/commands/learning-helpers.js +3 -4
- package/v3/dist/cli/commands/learning-helpers.js.map +1 -1
- package/v3/dist/cli/commands/learning.d.ts.map +1 -1
- package/v3/dist/cli/commands/learning.js +5 -8
- package/v3/dist/cli/commands/learning.js.map +1 -1
- package/v3/dist/cli/commands/migrate.js +2 -2
- package/v3/dist/coordination/constants.d.ts +1 -1
- package/v3/dist/coordination/constants.js +1 -1
- package/v3/dist/coordination/task-executor.d.ts.map +1 -1
- package/v3/dist/coordination/task-executor.js +322 -74
- package/v3/dist/coordination/task-executor.js.map +1 -1
- package/v3/dist/domains/code-intelligence/coordinator-hypergraph.js +2 -2
- package/v3/dist/domains/code-intelligence/coordinator-hypergraph.js.map +1 -1
- package/v3/dist/domains/code-intelligence/coordinator.js +2 -2
- package/v3/dist/domains/code-intelligence/coordinator.js.map +1 -1
- package/v3/dist/domains/coverage-analysis/coordinator.js +1 -1
- package/v3/dist/domains/coverage-analysis/services/coverage-analyzer.js +1 -1
- package/v3/dist/domains/coverage-analysis/services/coverage-embedder.d.ts +1 -1
- package/v3/dist/domains/coverage-analysis/services/coverage-embedder.js +1 -1
- package/v3/dist/domains/coverage-analysis/services/gap-detector.js +1 -1
- package/v3/dist/domains/coverage-analysis/services/ghost-coverage-analyzer.js +1 -1
- package/v3/dist/domains/coverage-analysis/services/hnsw-index.d.ts +2 -2
- package/v3/dist/domains/coverage-analysis/services/hnsw-index.js +3 -3
- package/v3/dist/domains/coverage-analysis/services/sublinear-analyzer.d.ts +1 -1
- package/v3/dist/domains/coverage-analysis/services/sublinear-analyzer.js +1 -1
- package/v3/dist/init/fleet-integration.d.ts.map +1 -1
- package/v3/dist/init/fleet-integration.js +3 -4
- package/v3/dist/init/fleet-integration.js.map +1 -1
- package/v3/dist/init/init-wizard-migration.d.ts.map +1 -1
- package/v3/dist/init/init-wizard-migration.js +3 -7
- package/v3/dist/init/init-wizard-migration.js.map +1 -1
- package/v3/dist/init/init-wizard-steps.d.ts.map +1 -1
- package/v3/dist/init/init-wizard-steps.js +3 -4
- package/v3/dist/init/init-wizard-steps.js.map +1 -1
- package/v3/dist/init/migration/data-migrator.d.ts.map +1 -1
- package/v3/dist/init/migration/data-migrator.js +6 -10
- package/v3/dist/init/migration/data-migrator.js.map +1 -1
- package/v3/dist/init/migration/detector.d.ts.map +1 -1
- package/v3/dist/init/migration/detector.js +2 -4
- package/v3/dist/init/migration/detector.js.map +1 -1
- package/v3/dist/init/phases/01-detection.d.ts.map +1 -1
- package/v3/dist/init/phases/01-detection.js +2 -4
- package/v3/dist/init/phases/01-detection.js.map +1 -1
- package/v3/dist/init/phases/06-code-intelligence.d.ts.map +1 -1
- package/v3/dist/init/phases/06-code-intelligence.js +4 -6
- package/v3/dist/init/phases/06-code-intelligence.js.map +1 -1
- package/v3/dist/init/phases/07-hooks.d.ts +11 -0
- package/v3/dist/init/phases/07-hooks.d.ts.map +1 -1
- package/v3/dist/init/phases/07-hooks.js +91 -1
- package/v3/dist/init/phases/07-hooks.js.map +1 -1
- package/v3/dist/init/phases/12-verification.d.ts.map +1 -1
- package/v3/dist/init/phases/12-verification.js +2 -4
- package/v3/dist/init/phases/12-verification.js.map +1 -1
- package/v3/dist/integrations/embeddings/cache/EmbeddingCache.d.ts.map +1 -1
- package/v3/dist/integrations/embeddings/cache/EmbeddingCache.js +2 -2
- package/v3/dist/integrations/embeddings/cache/EmbeddingCache.js.map +1 -1
- package/v3/dist/kernel/constants.d.ts +1 -1
- package/v3/dist/kernel/constants.js +1 -1
- package/v3/dist/kernel/unified-memory-hnsw.d.ts.map +1 -1
- package/v3/dist/kernel/unified-memory-hnsw.js +25 -6
- package/v3/dist/kernel/unified-memory-hnsw.js.map +1 -1
- package/v3/dist/kernel/unified-memory-migration.d.ts.map +1 -1
- package/v3/dist/kernel/unified-memory-migration.js +3 -3
- package/v3/dist/kernel/unified-memory-migration.js.map +1 -1
- package/v3/dist/learning/metrics-tracker.d.ts.map +1 -1
- package/v3/dist/learning/metrics-tracker.js +2 -2
- package/v3/dist/learning/metrics-tracker.js.map +1 -1
- package/v3/dist/learning/sqlite-persistence.d.ts.map +1 -1
- package/v3/dist/learning/sqlite-persistence.js +3 -6
- package/v3/dist/learning/sqlite-persistence.js.map +1 -1
- package/v3/dist/learning/v2-to-v3-migration.d.ts.map +1 -1
- package/v3/dist/learning/v2-to-v3-migration.js +4 -5
- package/v3/dist/learning/v2-to-v3-migration.js.map +1 -1
- package/v3/dist/mcp/bundle.js +733 -162
- package/v3/dist/mcp/tools/security-compliance/scan.d.ts +3 -1
- package/v3/dist/mcp/tools/security-compliance/scan.d.ts.map +1 -1
- package/v3/dist/mcp/tools/security-compliance/scan.js +417 -72
- package/v3/dist/mcp/tools/security-compliance/scan.js.map +1 -1
- package/v3/dist/planning/plan-executor.d.ts.map +1 -1
- package/v3/dist/planning/plan-executor.js +2 -2
- package/v3/dist/planning/plan-executor.js.map +1 -1
- package/v3/dist/shared/safe-db.d.ts +32 -0
- package/v3/dist/shared/safe-db.d.ts.map +1 -0
- package/v3/dist/shared/safe-db.js +41 -0
- package/v3/dist/shared/safe-db.js.map +1 -0
- package/v3/dist/sync/claude-flow-bridge.js +5 -5
- package/v3/dist/sync/claude-flow-bridge.js.map +1 -1
- package/v3/dist/sync/embeddings/sync-embedding-generator.js +3 -3
- package/v3/dist/sync/embeddings/sync-embedding-generator.js.map +1 -1
- package/v3/dist/sync/readers/sqlite-reader.d.ts.map +1 -1
- package/v3/dist/sync/readers/sqlite-reader.js +2 -2
- package/v3/dist/sync/readers/sqlite-reader.js.map +1 -1
- package/v3/package.json +1 -1
package/v3/dist/mcp/bundle.js
CHANGED
|
@@ -4421,7 +4421,7 @@ var init_constants = __esm({
|
|
|
4421
4421
|
/**
|
|
4422
4422
|
* Vector dimension for coverage analysis embeddings.
|
|
4423
4423
|
*/
|
|
4424
|
-
COVERAGE_VECTOR_DIMENSION:
|
|
4424
|
+
COVERAGE_VECTOR_DIMENSION: 768
|
|
4425
4425
|
};
|
|
4426
4426
|
AGENT_CONSTANTS = {
|
|
4427
4427
|
/**
|
|
@@ -4643,6 +4643,12 @@ var init_gnn = __esm({
|
|
|
4643
4643
|
});
|
|
4644
4644
|
|
|
4645
4645
|
// src/kernel/unified-memory-hnsw.ts
|
|
4646
|
+
var unified_memory_hnsw_exports = {};
|
|
4647
|
+
__export(unified_memory_hnsw_exports, {
|
|
4648
|
+
BinaryHeap: () => BinaryHeap,
|
|
4649
|
+
InMemoryHNSWIndex: () => InMemoryHNSWIndex,
|
|
4650
|
+
RuvectorFlatIndex: () => RuvectorFlatIndex
|
|
4651
|
+
});
|
|
4646
4652
|
function computeNorm(v62) {
|
|
4647
4653
|
let sum = 0;
|
|
4648
4654
|
for (let i58 = 0; i58 < v62.length; i58++) sum += v62[i58] * v62[i58];
|
|
@@ -5036,7 +5042,10 @@ var init_unified_memory_hnsw = __esm({
|
|
|
5036
5042
|
search(query, k68) {
|
|
5037
5043
|
if (this.ids.length === 0) return [];
|
|
5038
5044
|
const actualK = Math.min(k68, this.ids.length);
|
|
5039
|
-
|
|
5045
|
+
const storedDim = this.vectors.length > 0 ? this.vectors[0].length : 0;
|
|
5046
|
+
const queryDim = query.length;
|
|
5047
|
+
const dimensionsMatch = storedDim === queryDim;
|
|
5048
|
+
if (ruvectorDifferentiableSearch && this.vectors.length > 0 && dimensionsMatch) {
|
|
5040
5049
|
const queryF322 = new Float32Array(query);
|
|
5041
5050
|
const queryNorm2 = computeNorm(queryF322);
|
|
5042
5051
|
const result = ruvectorDifferentiableSearch(
|
|
@@ -5054,10 +5063,20 @@ var init_unified_memory_hnsw = __esm({
|
|
|
5054
5063
|
const queryNorm = computeNorm(queryF32);
|
|
5055
5064
|
const scored = [];
|
|
5056
5065
|
for (let i58 = 0; i58 < this.ids.length; i58++) {
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5066
|
+
const vec = this.vectors[i58];
|
|
5067
|
+
if (vec.length !== queryF32.length) {
|
|
5068
|
+
if (i58 === 0) {
|
|
5069
|
+
console.warn(
|
|
5070
|
+
`[RuvectorFlatIndex] Dimension mismatch: query=${queryF32.length}, stored=${vec.length}. Skipping ${this.ids.length} mismatched vectors. Re-index with correct dimensions.`
|
|
5071
|
+
);
|
|
5072
|
+
}
|
|
5073
|
+
continue;
|
|
5074
|
+
} else {
|
|
5075
|
+
scored.push({
|
|
5076
|
+
id: this.ids[i58],
|
|
5077
|
+
score: fastCosine(queryF32, vec, queryNorm, this.norms[i58])
|
|
5078
|
+
});
|
|
5079
|
+
}
|
|
5061
5080
|
}
|
|
5062
5081
|
scored.sort((a37, b68) => b68.score - a37.score);
|
|
5063
5082
|
return scored.slice(0, actualK);
|
|
@@ -11337,7 +11356,7 @@ function createHNSWIndex(memory, config) {
|
|
|
11337
11356
|
return new HNSWIndex(memory, config);
|
|
11338
11357
|
}
|
|
11339
11358
|
async function benchmarkHNSW(index, vectorCount = 1e4, searchCount = 1e3) {
|
|
11340
|
-
const dimensions =
|
|
11359
|
+
const dimensions = 768;
|
|
11341
11360
|
const startInsert = performance.now();
|
|
11342
11361
|
for (let i58 = 0; i58 < vectorCount; i58++) {
|
|
11343
11362
|
const vector = Array.from({ length: dimensions }, () => Math.random());
|
|
@@ -11366,7 +11385,7 @@ var init_hnsw_index = __esm({
|
|
|
11366
11385
|
QEGNNEmbeddingIndexClass = null;
|
|
11367
11386
|
ruvectorLoaded = false;
|
|
11368
11387
|
DEFAULT_HNSW_CONFIG = {
|
|
11369
|
-
dimensions:
|
|
11388
|
+
dimensions: 768,
|
|
11370
11389
|
M: 16,
|
|
11371
11390
|
efConstruction: 200,
|
|
11372
11391
|
efSearch: 100,
|
|
@@ -11618,7 +11637,7 @@ var init_hnsw_index = __esm({
|
|
|
11618
11637
|
/**
|
|
11619
11638
|
* Validate and auto-resize vectors to match HNSW configured dimensions.
|
|
11620
11639
|
* Fix #279: Prevents Rust WASM panic when RealEmbeddings (768-dim) are
|
|
11621
|
-
* passed to a
|
|
11640
|
+
* passed to a mismatched-dim HNSW index.
|
|
11622
11641
|
*/
|
|
11623
11642
|
validateVector(vector) {
|
|
11624
11643
|
if (vector.length !== this.config.dimensions) {
|
|
@@ -11721,6 +11740,33 @@ var init_hnsw_index = __esm({
|
|
|
11721
11740
|
}
|
|
11722
11741
|
});
|
|
11723
11742
|
|
|
11743
|
+
// src/shared/safe-db.ts
|
|
11744
|
+
var safe_db_exports = {};
|
|
11745
|
+
__export(safe_db_exports, {
|
|
11746
|
+
openDatabase: () => openDatabase
|
|
11747
|
+
});
|
|
11748
|
+
function openDatabase(dbPath, opts) {
|
|
11749
|
+
const readonly = opts?.readonly ?? false;
|
|
11750
|
+
const fileMustExist = opts?.fileMustExist ?? false;
|
|
11751
|
+
const busyTimeout = opts?.busyTimeout ?? 5e3;
|
|
11752
|
+
const walMode = opts?.walMode ?? !readonly;
|
|
11753
|
+
const db = new better_sqlite3_default(dbPath, {
|
|
11754
|
+
readonly,
|
|
11755
|
+
fileMustExist
|
|
11756
|
+
});
|
|
11757
|
+
db.pragma(`busy_timeout = ${busyTimeout}`);
|
|
11758
|
+
if (walMode) {
|
|
11759
|
+
db.pragma("journal_mode = WAL");
|
|
11760
|
+
}
|
|
11761
|
+
return db;
|
|
11762
|
+
}
|
|
11763
|
+
var init_safe_db = __esm({
|
|
11764
|
+
"src/shared/safe-db.ts"() {
|
|
11765
|
+
"use strict";
|
|
11766
|
+
init_better_sqlite3();
|
|
11767
|
+
}
|
|
11768
|
+
});
|
|
11769
|
+
|
|
11724
11770
|
// src/integrations/vibium/types.ts
|
|
11725
11771
|
var init_types2 = __esm({
|
|
11726
11772
|
"src/integrations/vibium/types.ts"() {
|
|
@@ -16333,7 +16379,7 @@ var DEFAULT_SQLITE_CONFIG, SQLitePatternStore;
|
|
|
16333
16379
|
var init_sqlite_persistence = __esm({
|
|
16334
16380
|
"src/learning/sqlite-persistence.ts"() {
|
|
16335
16381
|
"use strict";
|
|
16336
|
-
|
|
16382
|
+
init_safe_db();
|
|
16337
16383
|
init_esm_node();
|
|
16338
16384
|
init_safe_json();
|
|
16339
16385
|
init_error_utils();
|
|
@@ -16377,10 +16423,7 @@ var init_sqlite_persistence = __esm({
|
|
|
16377
16423
|
if (!fs21.existsSync(dir)) {
|
|
16378
16424
|
fs21.mkdirSync(dir, { recursive: true });
|
|
16379
16425
|
}
|
|
16380
|
-
this.db =
|
|
16381
|
-
if (this.config.walMode) {
|
|
16382
|
-
this.db.pragma("journal_mode = WAL");
|
|
16383
|
-
}
|
|
16426
|
+
this.db = openDatabase(this.config.dbPath);
|
|
16384
16427
|
this.db.pragma(`mmap_size = ${this.config.mmapSize}`);
|
|
16385
16428
|
this.db.pragma(`cache_size = ${this.config.cacheSize}`);
|
|
16386
16429
|
if (this.config.foreignKeys) {
|
|
@@ -21712,13 +21755,13 @@ var init_trajectory_bridge = __esm({
|
|
|
21712
21755
|
const { existsSync: existsSync18, mkdirSync: mkdirSync6 } = await import("fs");
|
|
21713
21756
|
const { createRequire: createRequire11 } = await import("module");
|
|
21714
21757
|
const require3 = createRequire11(import.meta.url);
|
|
21715
|
-
const
|
|
21758
|
+
const { openDatabase: openDatabase2 } = require3("../../shared/safe-db.js");
|
|
21716
21759
|
const dbPath = join26(this.options.projectRoot, ".agentic-qe", "trajectories.db");
|
|
21717
21760
|
const dir = join26(this.options.projectRoot, ".agentic-qe");
|
|
21718
21761
|
if (!existsSync18(dir)) {
|
|
21719
21762
|
mkdirSync6(dir, { recursive: true });
|
|
21720
21763
|
}
|
|
21721
|
-
const db =
|
|
21764
|
+
const db = openDatabase2(dbPath);
|
|
21722
21765
|
db.exec(`
|
|
21723
21766
|
CREATE TABLE IF NOT EXISTS trajectories (
|
|
21724
21767
|
id TEXT PRIMARY KEY,
|
|
@@ -65134,7 +65177,7 @@ var DEFAULT_CONFIG18 = {
|
|
|
65134
65177
|
};
|
|
65135
65178
|
var CoverageAnalyzerService = class _CoverageAnalyzerService {
|
|
65136
65179
|
static DEFAULT_THRESHOLD = 80;
|
|
65137
|
-
static VECTOR_DIMENSION =
|
|
65180
|
+
static VECTOR_DIMENSION = 768;
|
|
65138
65181
|
memory;
|
|
65139
65182
|
config;
|
|
65140
65183
|
llmRouter;
|
|
@@ -65668,7 +65711,7 @@ var DEFAULT_CONFIG19 = {
|
|
|
65668
65711
|
};
|
|
65669
65712
|
var GapDetectorService = class _GapDetectorService {
|
|
65670
65713
|
static DEFAULT_MIN_COVERAGE = 80;
|
|
65671
|
-
static VECTOR_DIMENSION =
|
|
65714
|
+
static VECTOR_DIMENSION = 768;
|
|
65672
65715
|
memory;
|
|
65673
65716
|
config;
|
|
65674
65717
|
llmRouter;
|
|
@@ -66666,7 +66709,7 @@ init_hnsw_index();
|
|
|
66666
66709
|
|
|
66667
66710
|
// src/domains/coverage-analysis/services/coverage-embedder.ts
|
|
66668
66711
|
var DEFAULT_EMBEDDER_CONFIG = {
|
|
66669
|
-
dimensions:
|
|
66712
|
+
dimensions: 768,
|
|
66670
66713
|
includePathFeatures: true,
|
|
66671
66714
|
includeTemporalFeatures: true,
|
|
66672
66715
|
normalization: "l2"
|
|
@@ -67098,7 +67141,7 @@ var ALL_CATEGORIES = [
|
|
|
67098
67141
|
"missing-security-check"
|
|
67099
67142
|
];
|
|
67100
67143
|
var DEFAULT_CONFIG20 = {
|
|
67101
|
-
dimensions:
|
|
67144
|
+
dimensions: 768,
|
|
67102
67145
|
minConfidence: 0.3,
|
|
67103
67146
|
maxGaps: 50,
|
|
67104
67147
|
riskWeight: 0.6,
|
|
@@ -68807,7 +68850,7 @@ var CoverageAnalysisCoordinator = class extends BaseDomainCoordinator {
|
|
|
68807
68850
|
return forecast;
|
|
68808
68851
|
}
|
|
68809
68852
|
createGapEmbedding(gap) {
|
|
68810
|
-
const VECTOR_DIMENSION =
|
|
68853
|
+
const VECTOR_DIMENSION = 768;
|
|
68811
68854
|
const embedding = new Array(VECTOR_DIMENSION).fill(0);
|
|
68812
68855
|
embedding[0] = gap.riskScore;
|
|
68813
68856
|
embedding[1] = Math.min(1, gap.lines.length / 100);
|
|
@@ -88568,7 +88611,7 @@ var CodeIntelligenceCoordinator = class extends BaseDomainCoordinator {
|
|
|
88568
88611
|
*/
|
|
88569
88612
|
async initializeHypergraph() {
|
|
88570
88613
|
try {
|
|
88571
|
-
const
|
|
88614
|
+
const { openDatabase: openDatabase2 } = await Promise.resolve().then(() => (init_safe_db(), safe_db_exports));
|
|
88572
88615
|
const fs21 = await import("fs");
|
|
88573
88616
|
const path23 = await import("path");
|
|
88574
88617
|
const { findProjectRoot: findProjectRoot2 } = await Promise.resolve().then(() => (init_unified_memory(), unified_memory_exports));
|
|
@@ -88578,7 +88621,7 @@ var CodeIntelligenceCoordinator = class extends BaseDomainCoordinator {
|
|
|
88578
88621
|
if (!fs21.existsSync(dir)) {
|
|
88579
88622
|
fs21.mkdirSync(dir, { recursive: true });
|
|
88580
88623
|
}
|
|
88581
|
-
this.hypergraphDb =
|
|
88624
|
+
this.hypergraphDb = openDatabase2(dbPath);
|
|
88582
88625
|
this.hypergraph = await createHypergraphEngine({
|
|
88583
88626
|
db: this.hypergraphDb,
|
|
88584
88627
|
maxTraversalDepth: 10,
|
|
@@ -132789,10 +132832,16 @@ function detectTransformType(task) {
|
|
|
132789
132832
|
}
|
|
132790
132833
|
async function loadCoverageData(targetPath) {
|
|
132791
132834
|
const coverageLocations = [
|
|
132835
|
+
// JavaScript/TypeScript (Istanbul/nyc/vitest)
|
|
132792
132836
|
path16.join(targetPath, "coverage", "coverage-final.json"),
|
|
132793
132837
|
path16.join(targetPath, "coverage", "lcov.info"),
|
|
132794
132838
|
path16.join(targetPath, ".nyc_output", "coverage-final.json"),
|
|
132795
|
-
path16.join(targetPath, "coverage-final.json")
|
|
132839
|
+
path16.join(targetPath, "coverage-final.json"),
|
|
132840
|
+
// Python (pytest-cov, coverage.py)
|
|
132841
|
+
path16.join(targetPath, "coverage.xml"),
|
|
132842
|
+
path16.join(targetPath, "htmlcov", "status.json"),
|
|
132843
|
+
// Cobertura (generic)
|
|
132844
|
+
path16.join(targetPath, "cobertura-coverage.xml")
|
|
132796
132845
|
];
|
|
132797
132846
|
for (const coveragePath of coverageLocations) {
|
|
132798
132847
|
try {
|
|
@@ -132801,6 +132850,8 @@ async function loadCoverageData(targetPath) {
|
|
|
132801
132850
|
return parseCoverageJson(content);
|
|
132802
132851
|
} else if (coveragePath.endsWith(".info")) {
|
|
132803
132852
|
return parseLcovInfo(content);
|
|
132853
|
+
} else if (coveragePath.endsWith(".xml")) {
|
|
132854
|
+
return parseCoberturaXml(content);
|
|
132804
132855
|
}
|
|
132805
132856
|
} catch {
|
|
132806
132857
|
}
|
|
@@ -132952,6 +133003,111 @@ function parseLcovInfo(content) {
|
|
|
132952
133003
|
}
|
|
132953
133004
|
};
|
|
132954
133005
|
}
|
|
133006
|
+
function parseCoberturaXml(content) {
|
|
133007
|
+
const files = [];
|
|
133008
|
+
function attr(element, name) {
|
|
133009
|
+
const match = element.match(new RegExp(`${name}=["']([^"']*)["']`));
|
|
133010
|
+
return match ? match[1] : null;
|
|
133011
|
+
}
|
|
133012
|
+
const classRegex = /<class\s[^>]*?>/g;
|
|
133013
|
+
let classMatch;
|
|
133014
|
+
while ((classMatch = classRegex.exec(content)) !== null) {
|
|
133015
|
+
const classTag = classMatch[0];
|
|
133016
|
+
const filename = attr(classTag, "filename");
|
|
133017
|
+
if (!filename) continue;
|
|
133018
|
+
const lineRate = parseFloat(attr(classTag, "line-rate") || "NaN");
|
|
133019
|
+
const branchRate = parseFloat(attr(classTag, "branch-rate") || "NaN");
|
|
133020
|
+
const classStart = classMatch.index;
|
|
133021
|
+
const classEnd = content.indexOf("</class>", classStart);
|
|
133022
|
+
const classContent = classEnd > classStart ? content.slice(classStart, classEnd) : "";
|
|
133023
|
+
let linesTotal = 0, linesCovered = 0;
|
|
133024
|
+
let branchesTotal = 0, branchesCovered = 0;
|
|
133025
|
+
let functionsTotal = 0, functionsCovered = 0;
|
|
133026
|
+
const uncoveredLines = [];
|
|
133027
|
+
const uncoveredBranches = [];
|
|
133028
|
+
const lineRegex = /<line\s([^>]*?)\/>/g;
|
|
133029
|
+
let lineMatch;
|
|
133030
|
+
while ((lineMatch = lineRegex.exec(classContent)) !== null) {
|
|
133031
|
+
const lineTag = lineMatch[1];
|
|
133032
|
+
const lineNum = parseInt(attr(lineTag, "number") || "0", 10);
|
|
133033
|
+
const hits = parseInt(attr(lineTag, "hits") || "0", 10);
|
|
133034
|
+
const isBranch = attr(lineTag, "branch") === "true";
|
|
133035
|
+
const condCoverage = attr(lineTag, "condition-coverage");
|
|
133036
|
+
linesTotal++;
|
|
133037
|
+
if (hits > 0) {
|
|
133038
|
+
linesCovered++;
|
|
133039
|
+
} else {
|
|
133040
|
+
uncoveredLines.push(lineNum);
|
|
133041
|
+
}
|
|
133042
|
+
if (isBranch) {
|
|
133043
|
+
branchesTotal++;
|
|
133044
|
+
const condPct = condCoverage ? parseInt(condCoverage, 10) : hits > 0 ? 100 : 0;
|
|
133045
|
+
if (condPct === 100) {
|
|
133046
|
+
branchesCovered++;
|
|
133047
|
+
} else {
|
|
133048
|
+
uncoveredBranches.push(lineNum);
|
|
133049
|
+
}
|
|
133050
|
+
}
|
|
133051
|
+
}
|
|
133052
|
+
const methodRegex = /<method\s([^>]*?)>/g;
|
|
133053
|
+
let methodMatch;
|
|
133054
|
+
while ((methodMatch = methodRegex.exec(classContent)) !== null) {
|
|
133055
|
+
functionsTotal++;
|
|
133056
|
+
const methodStart = methodMatch.index;
|
|
133057
|
+
const methodEnd = classContent.indexOf("</method>", methodStart);
|
|
133058
|
+
if (methodEnd > methodStart) {
|
|
133059
|
+
const methodContent = classContent.slice(methodStart, methodEnd);
|
|
133060
|
+
const methodLineRegex = /<line\s([^>]*?)\/>/g;
|
|
133061
|
+
let hasHits = false;
|
|
133062
|
+
let mLineMatch;
|
|
133063
|
+
while ((mLineMatch = methodLineRegex.exec(methodContent)) !== null) {
|
|
133064
|
+
if (parseInt(attr(mLineMatch[1], "hits") || "0", 10) > 0) {
|
|
133065
|
+
hasHits = true;
|
|
133066
|
+
break;
|
|
133067
|
+
}
|
|
133068
|
+
}
|
|
133069
|
+
if (hasHits) functionsCovered++;
|
|
133070
|
+
}
|
|
133071
|
+
}
|
|
133072
|
+
if (linesTotal === 0 && !isNaN(lineRate)) {
|
|
133073
|
+
linesTotal = 1;
|
|
133074
|
+
linesCovered = lineRate >= 0.5 ? 1 : 0;
|
|
133075
|
+
}
|
|
133076
|
+
files.push({
|
|
133077
|
+
path: filename,
|
|
133078
|
+
lines: { covered: linesCovered, total: linesTotal },
|
|
133079
|
+
branches: { covered: branchesCovered, total: branchesTotal },
|
|
133080
|
+
functions: { covered: functionsCovered, total: functionsTotal },
|
|
133081
|
+
statements: { covered: linesCovered, total: linesTotal },
|
|
133082
|
+
uncoveredLines,
|
|
133083
|
+
uncoveredBranches
|
|
133084
|
+
});
|
|
133085
|
+
}
|
|
133086
|
+
let totalLines = 0, totalCoveredLines = 0;
|
|
133087
|
+
let totalBranches = 0, totalCoveredBranches = 0;
|
|
133088
|
+
let totalFunctions = 0, totalCoveredFunctions = 0;
|
|
133089
|
+
for (const file of files) {
|
|
133090
|
+
totalLines += file.lines.total;
|
|
133091
|
+
totalCoveredLines += file.lines.covered;
|
|
133092
|
+
totalBranches += file.branches.total;
|
|
133093
|
+
totalCoveredBranches += file.branches.covered;
|
|
133094
|
+
totalFunctions += file.functions.total;
|
|
133095
|
+
totalCoveredFunctions += file.functions.covered;
|
|
133096
|
+
}
|
|
133097
|
+
const coverageTag = content.match(/<coverage\s[^>]*?>/);
|
|
133098
|
+
const summaryLineRate = coverageTag ? parseFloat(attr(coverageTag[0], "line-rate") || "NaN") * 100 : NaN;
|
|
133099
|
+
const summaryBranchRate = coverageTag ? parseFloat(attr(coverageTag[0], "branch-rate") || "NaN") * 100 : NaN;
|
|
133100
|
+
return {
|
|
133101
|
+
files,
|
|
133102
|
+
summary: {
|
|
133103
|
+
line: !isNaN(summaryLineRate) ? summaryLineRate : totalLines > 0 ? totalCoveredLines / totalLines * 100 : 0,
|
|
133104
|
+
branch: !isNaN(summaryBranchRate) ? summaryBranchRate : totalBranches > 0 ? totalCoveredBranches / totalBranches * 100 : 0,
|
|
133105
|
+
function: totalFunctions > 0 ? totalCoveredFunctions / totalFunctions * 100 : 0,
|
|
133106
|
+
statement: totalLines > 0 ? totalCoveredLines / totalLines * 100 : 0,
|
|
133107
|
+
files: files.length
|
|
133108
|
+
}
|
|
133109
|
+
};
|
|
133110
|
+
}
|
|
132955
133111
|
async function discoverSourceFiles(targetPath, options = {}) {
|
|
132956
133112
|
const files = [];
|
|
132957
133113
|
const { includeTests = true, languages } = options;
|
|
@@ -133342,12 +133498,14 @@ var DomainTaskExecutor = class {
|
|
|
133342
133498
|
const lines = content.split("\n");
|
|
133343
133499
|
const relPath = filePath.startsWith(targetPath) ? filePath.slice(targetPath.length).replace(/^\//, "") : filePath;
|
|
133344
133500
|
const secretPatterns = [
|
|
133345
|
-
{ regex:
|
|
133346
|
-
{ regex:
|
|
133501
|
+
{ regex: /\w*(?:secret|password|passwd|api_key|apikey|private_key|jwt_secret)\w*\s*[=:]\s*['"][^'"]{4,}['"]/gi, title: "Hardcoded secret", severity: "critical" },
|
|
133502
|
+
{ regex: /\w*(?:token|auth_token|access_key|secret_key)\w*\s*[=:]\s*['"][^'"]{8,}['"]/gi, title: "Hardcoded credential", severity: "critical" },
|
|
133503
|
+
{ regex: /(?:AWS_SECRET|GITHUB_TOKEN|SLACK_TOKEN|OPENAI_API_KEY)\s*[=:]\s*['"][^'"]+['"]/gi, title: "Hardcoded cloud credential", severity: "critical" }
|
|
133347
133504
|
];
|
|
133348
133505
|
for (const pattern of secretPatterns) {
|
|
133349
133506
|
for (let i58 = 0; i58 < lines.length; i58++) {
|
|
133350
|
-
|
|
133507
|
+
const matches = [...lines[i58].matchAll(pattern.regex)];
|
|
133508
|
+
for (const _m of matches) {
|
|
133351
133509
|
crossLangVulns.push({
|
|
133352
133510
|
title: pattern.title,
|
|
133353
133511
|
severity: pattern.severity,
|
|
@@ -133356,7 +133514,6 @@ var DomainTaskExecutor = class {
|
|
|
133356
133514
|
category: "sensitive-data"
|
|
133357
133515
|
});
|
|
133358
133516
|
}
|
|
133359
|
-
pattern.regex.lastIndex = 0;
|
|
133360
133517
|
}
|
|
133361
133518
|
}
|
|
133362
133519
|
const sqlPatterns = /(?:execute|query|cursor\.execute)\s*\(\s*(?:f['"]|['"].*%s|['"].*\+\s*\w)/gi;
|
|
@@ -133372,14 +133529,29 @@ var DomainTaskExecutor = class {
|
|
|
133372
133529
|
}
|
|
133373
133530
|
sqlPatterns.lastIndex = 0;
|
|
133374
133531
|
}
|
|
133375
|
-
|
|
133376
|
-
|
|
133377
|
-
|
|
133378
|
-
|
|
133379
|
-
|
|
133380
|
-
|
|
133381
|
-
|
|
133382
|
-
|
|
133532
|
+
const corsPatterns = [
|
|
133533
|
+
/allow_origins\s*=\s*\[?\s*['"]?\*['"]?\s*\]?/i,
|
|
133534
|
+
// Python FastAPI/Flask
|
|
133535
|
+
/cors\(\s*\{[^}]*origin:\s*['"]?\*['"]?/i,
|
|
133536
|
+
// Express.js cors()
|
|
133537
|
+
/Access-Control-Allow-Origin['":\s]+\*/i,
|
|
133538
|
+
// Raw header / Nginx / .htaccess
|
|
133539
|
+
/@CrossOrigin\(\s*origins?\s*=\s*["']\*["']/i,
|
|
133540
|
+
// Spring Boot
|
|
133541
|
+
/\.Header\(\)\.Set\(["']Access-Control-Allow-Origin["'],\s*["']\*["']/i
|
|
133542
|
+
// Go
|
|
133543
|
+
];
|
|
133544
|
+
for (const corsPattern of corsPatterns) {
|
|
133545
|
+
if (corsPattern.test(content)) {
|
|
133546
|
+
crossLangVulns.push({
|
|
133547
|
+
title: "CORS wildcard origin",
|
|
133548
|
+
severity: "high",
|
|
133549
|
+
location: { file: relPath, line: lines.findIndex((l75) => corsPattern.test(l75)) + 1 },
|
|
133550
|
+
description: "CORS configured with wildcard (*) origin \u2014 restrict to specific domains",
|
|
133551
|
+
category: "security-misconfiguration"
|
|
133552
|
+
});
|
|
133553
|
+
break;
|
|
133554
|
+
}
|
|
133383
133555
|
}
|
|
133384
133556
|
if (/(?:DEBUG|debug)\s*[=:]\s*(?:True|true|1)/i.test(content)) {
|
|
133385
133557
|
crossLangVulns.push({
|
|
@@ -133634,19 +133806,58 @@ var DomainTaskExecutor = class {
|
|
|
133634
133806
|
});
|
|
133635
133807
|
this.taskHandlers.set("execute-tests", async (task) => {
|
|
133636
133808
|
const payload = task.payload;
|
|
133637
|
-
|
|
133638
|
-
|
|
133639
|
-
|
|
133640
|
-
|
|
133641
|
-
|
|
133642
|
-
|
|
133643
|
-
|
|
133644
|
-
|
|
133645
|
-
|
|
133646
|
-
|
|
133647
|
-
|
|
133648
|
-
|
|
133649
|
-
|
|
133809
|
+
try {
|
|
133810
|
+
const { execSync: execSync6 } = await import("child_process");
|
|
133811
|
+
const testFiles = payload.testFiles || [];
|
|
133812
|
+
if (testFiles.length === 0) {
|
|
133813
|
+
return ok({
|
|
133814
|
+
total: 0,
|
|
133815
|
+
passed: 0,
|
|
133816
|
+
failed: 0,
|
|
133817
|
+
skipped: 0,
|
|
133818
|
+
duration: 0,
|
|
133819
|
+
coverage: 0,
|
|
133820
|
+
failedTests: [],
|
|
133821
|
+
warning: "No test files specified. Provide testFiles array with paths to test files."
|
|
133822
|
+
});
|
|
133823
|
+
}
|
|
133824
|
+
const cwd = process.cwd();
|
|
133825
|
+
let output;
|
|
133826
|
+
try {
|
|
133827
|
+
output = execSync6(
|
|
133828
|
+
`npx vitest run ${testFiles.join(" ")} --reporter=json 2>/dev/null || npx jest ${testFiles.join(" ")} --json 2>/dev/null`,
|
|
133829
|
+
{ cwd, timeout: 12e4, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
133830
|
+
);
|
|
133831
|
+
} catch (execError) {
|
|
133832
|
+
output = execError.stdout || "";
|
|
133833
|
+
}
|
|
133834
|
+
try {
|
|
133835
|
+
const jsonStart = output.indexOf("{");
|
|
133836
|
+
if (jsonStart >= 0) {
|
|
133837
|
+
const json = JSON.parse(output.slice(jsonStart));
|
|
133838
|
+
if (json.testResults) {
|
|
133839
|
+
const total = json.numTotalTests || 0;
|
|
133840
|
+
const passed = json.numPassedTests || 0;
|
|
133841
|
+
const failed = json.numFailedTests || 0;
|
|
133842
|
+
return ok({ total, passed, failed, skipped: total - passed - failed, duration: 0, coverage: 0, failedTests: [] });
|
|
133843
|
+
}
|
|
133844
|
+
}
|
|
133845
|
+
} catch {
|
|
133846
|
+
}
|
|
133847
|
+
return ok({
|
|
133848
|
+
total: testFiles.length,
|
|
133849
|
+
passed: 0,
|
|
133850
|
+
failed: 0,
|
|
133851
|
+
skipped: 0,
|
|
133852
|
+
duration: 0,
|
|
133853
|
+
coverage: 0,
|
|
133854
|
+
failedTests: [],
|
|
133855
|
+
warning: "Could not parse test runner output. Check that vitest or jest is installed.",
|
|
133856
|
+
rawOutput: output.slice(0, 500)
|
|
133857
|
+
});
|
|
133858
|
+
} catch (error) {
|
|
133859
|
+
return err(toError(error));
|
|
133860
|
+
}
|
|
133650
133861
|
});
|
|
133651
133862
|
this.taskHandlers.set("predict-defects", async (task) => {
|
|
133652
133863
|
const payload = task.payload;
|
|
@@ -133750,68 +133961,116 @@ var DomainTaskExecutor = class {
|
|
|
133750
133961
|
});
|
|
133751
133962
|
this.taskHandlers.set("validate-requirements", async (task) => {
|
|
133752
133963
|
const payload = task.payload;
|
|
133753
|
-
|
|
133754
|
-
|
|
133755
|
-
|
|
133756
|
-
|
|
133757
|
-
|
|
133758
|
-
|
|
133759
|
-
|
|
133760
|
-
|
|
133761
|
-
|
|
133762
|
-
|
|
133763
|
-
|
|
133964
|
+
try {
|
|
133965
|
+
const targetPath = payload.requirementsPath || process.cwd();
|
|
133966
|
+
const reqFiles = await discoverSourceFiles(targetPath, {
|
|
133967
|
+
includeTests: false,
|
|
133968
|
+
languages: []
|
|
133969
|
+
});
|
|
133970
|
+
const reqPatterns = [".md", ".feature", ".gherkin", ".txt", ".rst"];
|
|
133971
|
+
const requirementFiles = [];
|
|
133972
|
+
for (const f74 of reqFiles) {
|
|
133973
|
+
if (reqPatterns.some((ext) => f74.endsWith(ext))) {
|
|
133974
|
+
requirementFiles.push(f74);
|
|
133975
|
+
}
|
|
133976
|
+
}
|
|
133977
|
+
return ok({
|
|
133978
|
+
requirementsAnalyzed: requirementFiles.length,
|
|
133979
|
+
testable: 0,
|
|
133980
|
+
ambiguous: 0,
|
|
133981
|
+
untestable: 0,
|
|
133982
|
+
coverage: 0,
|
|
133983
|
+
bddScenarios: [],
|
|
133984
|
+
warning: requirementFiles.length === 0 ? "No requirement files (.md, .feature, .gherkin) found. Provide requirementsPath or add requirement docs." : "Requirements validation requires LLM analysis. File inventory returned \u2014 use task_orchestrate for deep analysis.",
|
|
133985
|
+
files: requirementFiles.map((f74) => f74.startsWith(targetPath) ? f74.slice(targetPath.length + 1) : f74).slice(0, 20)
|
|
133986
|
+
});
|
|
133987
|
+
} catch (error) {
|
|
133988
|
+
return err(toError(error));
|
|
133989
|
+
}
|
|
133764
133990
|
});
|
|
133765
133991
|
this.taskHandlers.set("validate-contracts", async (task) => {
|
|
133766
133992
|
const payload = task.payload;
|
|
133767
|
-
|
|
133768
|
-
|
|
133769
|
-
|
|
133770
|
-
|
|
133771
|
-
|
|
133772
|
-
|
|
133773
|
-
|
|
133774
|
-
|
|
133775
|
-
|
|
133993
|
+
try {
|
|
133994
|
+
if (!payload.contractPath) {
|
|
133995
|
+
return ok({
|
|
133996
|
+
contractPath: "",
|
|
133997
|
+
valid: false,
|
|
133998
|
+
breakingChanges: [],
|
|
133999
|
+
warnings: [],
|
|
134000
|
+
coverage: 0,
|
|
134001
|
+
error: "contractPath is required. Provide a path to an OpenAPI spec, JSON Schema, or Protocol Buffer file."
|
|
134002
|
+
});
|
|
134003
|
+
}
|
|
134004
|
+
try {
|
|
134005
|
+
const content = await fs15.readFile(payload.contractPath, "utf-8");
|
|
134006
|
+
const isJson = payload.contractPath.endsWith(".json");
|
|
134007
|
+
const isYaml = payload.contractPath.endsWith(".yaml") || payload.contractPath.endsWith(".yml");
|
|
134008
|
+
if (isJson) {
|
|
134009
|
+
JSON.parse(content);
|
|
134010
|
+
}
|
|
134011
|
+
return ok({
|
|
134012
|
+
contractPath: payload.contractPath,
|
|
134013
|
+
valid: true,
|
|
134014
|
+
format: isJson ? "json" : isYaml ? "yaml" : "unknown",
|
|
134015
|
+
breakingChanges: [],
|
|
134016
|
+
warnings: [],
|
|
134017
|
+
linesAnalyzed: content.split("\n").length,
|
|
134018
|
+
note: "Structural validation passed. For semantic contract testing, use consumer-driven contract tests."
|
|
134019
|
+
});
|
|
134020
|
+
} catch (readErr) {
|
|
134021
|
+
return ok({
|
|
134022
|
+
contractPath: payload.contractPath,
|
|
134023
|
+
valid: false,
|
|
134024
|
+
breakingChanges: [],
|
|
134025
|
+
warnings: [],
|
|
134026
|
+
error: `Could not read or parse contract file: ${toErrorMessage(readErr)}`
|
|
134027
|
+
});
|
|
134028
|
+
}
|
|
134029
|
+
} catch (error) {
|
|
134030
|
+
return err(toError(error));
|
|
134031
|
+
}
|
|
133776
134032
|
});
|
|
133777
134033
|
this.taskHandlers.set("test-accessibility", async (task) => {
|
|
133778
134034
|
const payload = task.payload;
|
|
133779
134035
|
return ok({
|
|
133780
|
-
url: payload.url,
|
|
134036
|
+
url: payload.url || "",
|
|
133781
134037
|
standard: payload.standard || "wcag21-aa",
|
|
133782
|
-
passed:
|
|
134038
|
+
passed: false,
|
|
133783
134039
|
violations: [],
|
|
133784
|
-
warnings: [
|
|
133785
|
-
|
|
133786
|
-
|
|
133787
|
-
score: 94
|
|
134040
|
+
warnings: [],
|
|
134041
|
+
score: 0,
|
|
134042
|
+
note: "Accessibility testing requires a browser environment (Puppeteer/Playwright). Use tools like axe-core, pa11y, or Lighthouse CLI for WCAG compliance testing. Example: npx pa11y " + (payload.url || "<url>")
|
|
133788
134043
|
});
|
|
133789
134044
|
});
|
|
133790
134045
|
this.taskHandlers.set("run-chaos", async (task) => {
|
|
133791
134046
|
const payload = task.payload;
|
|
133792
134047
|
return ok({
|
|
133793
|
-
faultType: payload.faultType,
|
|
133794
|
-
target: payload.target,
|
|
133795
|
-
dryRun: payload.dryRun,
|
|
133796
|
-
duration: payload.duration,
|
|
133797
|
-
systemBehavior:
|
|
133798
|
-
resilience:
|
|
133799
|
-
|
|
133800
|
-
recoveryTime: 2500,
|
|
133801
|
-
dataLoss: false
|
|
133802
|
-
}
|
|
134048
|
+
faultType: payload.faultType || "unknown",
|
|
134049
|
+
target: payload.target || "unknown",
|
|
134050
|
+
dryRun: payload.dryRun ?? true,
|
|
134051
|
+
duration: payload.duration || 0,
|
|
134052
|
+
systemBehavior: "not-executed",
|
|
134053
|
+
resilience: null,
|
|
134054
|
+
note: "Chaos engineering requires infrastructure-level fault injection. Use tools like Chaos Monkey, Litmus, or toxiproxy for real resilience testing. For Node.js apps, consider: nock (HTTP faults), testcontainers (dependency failures)."
|
|
133803
134055
|
});
|
|
133804
134056
|
});
|
|
133805
134057
|
this.taskHandlers.set("optimize-learning", async (_task) => {
|
|
133806
|
-
|
|
133807
|
-
|
|
133808
|
-
|
|
133809
|
-
|
|
133810
|
-
|
|
133811
|
-
|
|
133812
|
-
"
|
|
133813
|
-
|
|
133814
|
-
}
|
|
134058
|
+
try {
|
|
134059
|
+
const memUsage = await Promise.resolve().then(() => (init_unified_memory_hnsw(), unified_memory_hnsw_exports));
|
|
134060
|
+
return ok({
|
|
134061
|
+
patternsLearned: 0,
|
|
134062
|
+
modelsUpdated: 0,
|
|
134063
|
+
memoryConsolidated: false,
|
|
134064
|
+
note: 'Learning optimization runs during the dream cycle (SessionEnd hook). Use "npx agentic-qe hooks session-end --save-state" to trigger pattern consolidation.'
|
|
134065
|
+
});
|
|
134066
|
+
} catch {
|
|
134067
|
+
return ok({
|
|
134068
|
+
patternsLearned: 0,
|
|
134069
|
+
modelsUpdated: 0,
|
|
134070
|
+
memoryConsolidated: false,
|
|
134071
|
+
note: 'Learning system not initialized. Run "aqe init --auto" first.'
|
|
134072
|
+
});
|
|
134073
|
+
}
|
|
133815
134074
|
});
|
|
133816
134075
|
}
|
|
133817
134076
|
// ============================================================================
|
|
@@ -143208,6 +143467,44 @@ function extractHighlights(content, query) {
|
|
|
143208
143467
|
|
|
143209
143468
|
// src/mcp/tools/security-compliance/scan.ts
|
|
143210
143469
|
init_error_utils();
|
|
143470
|
+
var CROSS_LANG_SECRET_PATTERNS = [
|
|
143471
|
+
{
|
|
143472
|
+
id: "secret-key-assignment",
|
|
143473
|
+
pattern: /(?:SECRET_KEY|secret_key|SECRET|PRIVATE_KEY)\s*=\s*['"][^'"]{4,}['"]/g,
|
|
143474
|
+
severity: "critical",
|
|
143475
|
+
title: "Hardcoded Secret Key",
|
|
143476
|
+
description: "Secret key assigned as string literal in source code",
|
|
143477
|
+
cweId: "CWE-798",
|
|
143478
|
+
remediation: 'Use environment variables: SECRET_KEY = os.environ["SECRET_KEY"]'
|
|
143479
|
+
},
|
|
143480
|
+
{
|
|
143481
|
+
id: "cors-wildcard-credentials",
|
|
143482
|
+
pattern: /allow_origins\s*=\s*\[\s*["']\*["']\s*\]/g,
|
|
143483
|
+
severity: "high",
|
|
143484
|
+
title: "CORS Wildcard Origin",
|
|
143485
|
+
description: "CORS configured to allow all origins \u2014 combined with credentials this is a security risk",
|
|
143486
|
+
cweId: "CWE-942",
|
|
143487
|
+
remediation: "Restrict CORS origins to specific trusted domains"
|
|
143488
|
+
},
|
|
143489
|
+
{
|
|
143490
|
+
id: "cors-allow-credentials-wildcard",
|
|
143491
|
+
pattern: /allow_credentials\s*=\s*True/g,
|
|
143492
|
+
severity: "medium",
|
|
143493
|
+
title: "CORS Credentials Enabled",
|
|
143494
|
+
description: "CORS credentials enabled \u2014 verify origins are restricted",
|
|
143495
|
+
cweId: "CWE-942",
|
|
143496
|
+
remediation: 'Ensure allow_origins does not include "*" when credentials are enabled'
|
|
143497
|
+
},
|
|
143498
|
+
{
|
|
143499
|
+
id: "token-hardcoded",
|
|
143500
|
+
pattern: /(?:token|TOKEN)\s*[:=]\s*['"][a-zA-Z0-9_\-.]{20,}['"]/g,
|
|
143501
|
+
severity: "high",
|
|
143502
|
+
title: "Hardcoded Token",
|
|
143503
|
+
description: "Hardcoded token found in source code",
|
|
143504
|
+
cweId: "CWE-798",
|
|
143505
|
+
remediation: "Use environment variables or secrets manager for tokens"
|
|
143506
|
+
}
|
|
143507
|
+
];
|
|
143211
143508
|
var SecurityScanTool = class extends MCPToolBase {
|
|
143212
143509
|
config = {
|
|
143213
143510
|
name: "qe/security/scan",
|
|
@@ -143236,18 +143533,21 @@ var SecurityScanTool = class extends MCPToolBase {
|
|
|
143236
143533
|
if (this.isAborted(context)) {
|
|
143237
143534
|
return { success: false, error: "Operation aborted" };
|
|
143238
143535
|
}
|
|
143536
|
+
const files = await discoverFiles(target, depth);
|
|
143537
|
+
this.emitStream(context, {
|
|
143538
|
+
status: "discovered",
|
|
143539
|
+
message: `Found ${files.length} files to scan`
|
|
143540
|
+
});
|
|
143239
143541
|
const vulnerabilities = [];
|
|
143240
|
-
if (scanType.includes("sast")) {
|
|
143542
|
+
if (scanType.includes("sast") || scanType.includes("secret")) {
|
|
143241
143543
|
this.emitStream(context, { status: "sast", message: "Running static analysis" });
|
|
143242
|
-
|
|
143544
|
+
const sastVulns = await scanFilesWithPatterns(files, scanType);
|
|
143545
|
+
vulnerabilities.push(...sastVulns);
|
|
143243
143546
|
}
|
|
143244
143547
|
if (scanType.includes("dependency")) {
|
|
143245
143548
|
this.emitStream(context, { status: "dependency", message: "Scanning dependencies" });
|
|
143246
|
-
|
|
143247
|
-
|
|
143248
|
-
if (scanType.includes("secret")) {
|
|
143249
|
-
this.emitStream(context, { status: "secret", message: "Scanning for secrets" });
|
|
143250
|
-
vulnerabilities.push(...generateSecretFindings());
|
|
143549
|
+
const depVulns = await scanDependencies(target);
|
|
143550
|
+
vulnerabilities.push(...depVulns);
|
|
143251
143551
|
}
|
|
143252
143552
|
if (scanType.includes("dast") && dastUrl) {
|
|
143253
143553
|
this.emitStream(context, { status: "dast", message: `Scanning ${dastUrl}` });
|
|
@@ -143262,7 +143562,7 @@ var SecurityScanTool = class extends MCPToolBase {
|
|
|
143262
143562
|
medium: vulnerabilities.filter((v62) => v62.severity === "medium").length,
|
|
143263
143563
|
low: vulnerabilities.filter((v62) => v62.severity === "low").length,
|
|
143264
143564
|
informational: vulnerabilities.filter((v62) => v62.severity === "informational").length,
|
|
143265
|
-
totalFiles:
|
|
143565
|
+
totalFiles: files.length,
|
|
143266
143566
|
scanDurationMs: Date.now() - startTime
|
|
143267
143567
|
};
|
|
143268
143568
|
const severityOrder = ["critical", "high", "medium", "low", "informational"];
|
|
@@ -143271,7 +143571,7 @@ var SecurityScanTool = class extends MCPToolBase {
|
|
|
143271
143571
|
const passed = worstSeverity > failThreshold;
|
|
143272
143572
|
this.emitStream(context, {
|
|
143273
143573
|
status: "complete",
|
|
143274
|
-
message: `Scan complete: ${vulnerabilities.length} vulnerabilities found`,
|
|
143574
|
+
message: `Scan complete: ${vulnerabilities.length} vulnerabilities found in ${files.length} files`,
|
|
143275
143575
|
progress: 100
|
|
143276
143576
|
});
|
|
143277
143577
|
return {
|
|
@@ -143338,72 +143638,340 @@ var SECURITY_SCAN_SCHEMA = {
|
|
|
143338
143638
|
}
|
|
143339
143639
|
}
|
|
143340
143640
|
};
|
|
143341
|
-
|
|
143342
|
-
|
|
143343
|
-
|
|
143344
|
-
|
|
143345
|
-
|
|
143346
|
-
|
|
143347
|
-
|
|
143348
|
-
|
|
143349
|
-
|
|
143350
|
-
|
|
143351
|
-
|
|
143352
|
-
|
|
143353
|
-
|
|
143354
|
-
|
|
143355
|
-
|
|
143356
|
-
|
|
143357
|
-
|
|
143358
|
-
|
|
143359
|
-
|
|
143360
|
-
|
|
143361
|
-
|
|
143362
|
-
|
|
143363
|
-
|
|
143641
|
+
var SCANNABLE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
143642
|
+
".ts",
|
|
143643
|
+
".tsx",
|
|
143644
|
+
".js",
|
|
143645
|
+
".jsx",
|
|
143646
|
+
".mjs",
|
|
143647
|
+
".cjs",
|
|
143648
|
+
// JavaScript/TypeScript
|
|
143649
|
+
".py",
|
|
143650
|
+
".pyw",
|
|
143651
|
+
// Python
|
|
143652
|
+
".java",
|
|
143653
|
+
".kt",
|
|
143654
|
+
".scala",
|
|
143655
|
+
// JVM
|
|
143656
|
+
".go",
|
|
143657
|
+
// Go
|
|
143658
|
+
".rb",
|
|
143659
|
+
// Ruby
|
|
143660
|
+
".php",
|
|
143661
|
+
// PHP
|
|
143662
|
+
".rs",
|
|
143663
|
+
// Rust
|
|
143664
|
+
".cs",
|
|
143665
|
+
// C#
|
|
143666
|
+
".yaml",
|
|
143667
|
+
".yml",
|
|
143668
|
+
".json",
|
|
143669
|
+
".toml",
|
|
143670
|
+
".cfg",
|
|
143671
|
+
".ini",
|
|
143672
|
+
// Config
|
|
143673
|
+
".env",
|
|
143674
|
+
".env.local",
|
|
143675
|
+
".env.production",
|
|
143676
|
+
// Env files
|
|
143677
|
+
".sh",
|
|
143678
|
+
".bash"
|
|
143679
|
+
// Shell
|
|
143680
|
+
]);
|
|
143681
|
+
var SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
143682
|
+
"node_modules",
|
|
143683
|
+
".git",
|
|
143684
|
+
"__pycache__",
|
|
143685
|
+
".venv",
|
|
143686
|
+
"venv",
|
|
143687
|
+
"dist",
|
|
143688
|
+
"build",
|
|
143689
|
+
".next",
|
|
143690
|
+
".nuxt",
|
|
143691
|
+
"coverage",
|
|
143692
|
+
".tox"
|
|
143693
|
+
]);
|
|
143694
|
+
async function discoverFiles(target, depth) {
|
|
143695
|
+
const fs21 = await import("fs");
|
|
143696
|
+
const path23 = await import("path");
|
|
143697
|
+
const resolved = path23.resolve(target);
|
|
143698
|
+
const files = [];
|
|
143699
|
+
const maxFiles = depth === "quick" ? 50 : depth === "standard" ? 500 : 2e3;
|
|
143700
|
+
const maxDepth = depth === "quick" ? 3 : depth === "standard" ? 8 : 20;
|
|
143701
|
+
function walk(dir, currentDepth) {
|
|
143702
|
+
if (files.length >= maxFiles || currentDepth > maxDepth) return;
|
|
143703
|
+
let entries;
|
|
143704
|
+
try {
|
|
143705
|
+
entries = fs21.readdirSync(dir, { withFileTypes: true });
|
|
143706
|
+
} catch {
|
|
143707
|
+
return;
|
|
143364
143708
|
}
|
|
143365
|
-
|
|
143709
|
+
for (const entry of entries) {
|
|
143710
|
+
if (files.length >= maxFiles) break;
|
|
143711
|
+
const fullPath = path23.join(dir, entry.name);
|
|
143712
|
+
if (entry.isDirectory()) {
|
|
143713
|
+
const SCAN_DOT_DIRS = /* @__PURE__ */ new Set([".github", ".docker", ".aws", ".circleci", ".gitlab"]);
|
|
143714
|
+
if (SKIP_DIRS.has(entry.name)) {
|
|
143715
|
+
} else if (entry.name.startsWith(".") && !SCAN_DOT_DIRS.has(entry.name)) {
|
|
143716
|
+
} else {
|
|
143717
|
+
walk(fullPath, currentDepth + 1);
|
|
143718
|
+
}
|
|
143719
|
+
} else if (entry.isFile()) {
|
|
143720
|
+
const ext = path23.extname(entry.name).toLowerCase();
|
|
143721
|
+
if (SCANNABLE_EXTENSIONS.has(ext) || entry.name === "Dockerfile" || entry.name === "Makefile" || entry.name.startsWith(".env")) {
|
|
143722
|
+
files.push(fullPath);
|
|
143723
|
+
}
|
|
143724
|
+
}
|
|
143725
|
+
}
|
|
143726
|
+
}
|
|
143727
|
+
try {
|
|
143728
|
+
const stat6 = fs21.statSync(resolved);
|
|
143729
|
+
if (stat6.isFile()) {
|
|
143730
|
+
files.push(resolved);
|
|
143731
|
+
} else {
|
|
143732
|
+
walk(resolved, 0);
|
|
143733
|
+
}
|
|
143734
|
+
} catch {
|
|
143735
|
+
}
|
|
143736
|
+
return files;
|
|
143366
143737
|
}
|
|
143367
|
-
function
|
|
143368
|
-
|
|
143369
|
-
|
|
143370
|
-
|
|
143371
|
-
|
|
143372
|
-
|
|
143373
|
-
|
|
143374
|
-
|
|
143375
|
-
|
|
143376
|
-
|
|
143377
|
-
|
|
143378
|
-
|
|
143738
|
+
async function scanFilesWithPatterns(files, scanTypes) {
|
|
143739
|
+
const fs21 = await import("fs");
|
|
143740
|
+
const path23 = await import("path");
|
|
143741
|
+
const vulnerabilities = [];
|
|
143742
|
+
let vulnCounter = 0;
|
|
143743
|
+
const patterns = [];
|
|
143744
|
+
if (scanTypes.includes("sast")) {
|
|
143745
|
+
for (const p74 of ALL_SECURITY_PATTERNS) {
|
|
143746
|
+
patterns.push({
|
|
143747
|
+
id: p74.id,
|
|
143748
|
+
pattern: new RegExp(p74.pattern.source, p74.pattern.flags),
|
|
143749
|
+
severity: p74.severity,
|
|
143750
|
+
title: p74.title,
|
|
143751
|
+
description: p74.description,
|
|
143752
|
+
cweId: p74.cweId,
|
|
143753
|
+
remediation: p74.remediation,
|
|
143754
|
+
category: p74.category
|
|
143755
|
+
});
|
|
143379
143756
|
}
|
|
143380
|
-
|
|
143757
|
+
for (const p74 of CROSS_LANG_SECRET_PATTERNS) {
|
|
143758
|
+
patterns.push({
|
|
143759
|
+
id: p74.id,
|
|
143760
|
+
pattern: new RegExp(p74.pattern.source, p74.pattern.flags),
|
|
143761
|
+
severity: p74.severity,
|
|
143762
|
+
title: p74.title,
|
|
143763
|
+
description: p74.description,
|
|
143764
|
+
cweId: p74.cweId,
|
|
143765
|
+
remediation: p74.remediation,
|
|
143766
|
+
category: "sensitive-data"
|
|
143767
|
+
});
|
|
143768
|
+
}
|
|
143769
|
+
}
|
|
143770
|
+
if (scanTypes.includes("secret")) {
|
|
143771
|
+
for (const p74 of SECRET_PATTERNS) {
|
|
143772
|
+
if (!patterns.some((existing) => existing.id === p74.id)) {
|
|
143773
|
+
patterns.push({
|
|
143774
|
+
id: p74.id,
|
|
143775
|
+
pattern: new RegExp(p74.pattern.source, p74.pattern.flags),
|
|
143776
|
+
severity: p74.severity,
|
|
143777
|
+
title: p74.title,
|
|
143778
|
+
description: p74.description,
|
|
143779
|
+
cweId: p74.cweId,
|
|
143780
|
+
remediation: p74.remediation,
|
|
143781
|
+
category: p74.category
|
|
143782
|
+
});
|
|
143783
|
+
}
|
|
143784
|
+
}
|
|
143785
|
+
for (const p74 of CROSS_LANG_SECRET_PATTERNS) {
|
|
143786
|
+
if (!patterns.some((existing) => existing.id === p74.id)) {
|
|
143787
|
+
patterns.push({
|
|
143788
|
+
...p74,
|
|
143789
|
+
category: "sensitive-data"
|
|
143790
|
+
});
|
|
143791
|
+
}
|
|
143792
|
+
}
|
|
143793
|
+
}
|
|
143794
|
+
for (const filePath of files) {
|
|
143795
|
+
let content;
|
|
143796
|
+
try {
|
|
143797
|
+
content = fs21.readFileSync(filePath, "utf-8");
|
|
143798
|
+
} catch {
|
|
143799
|
+
continue;
|
|
143800
|
+
}
|
|
143801
|
+
if (content.includes("\0") || content.length > 1e6) continue;
|
|
143802
|
+
const lines = content.split("\n");
|
|
143803
|
+
const relPath = path23.relative(process.cwd(), filePath);
|
|
143804
|
+
for (const patternDef of patterns) {
|
|
143805
|
+
const regex = new RegExp(patternDef.pattern.source, patternDef.pattern.flags);
|
|
143806
|
+
let match;
|
|
143807
|
+
while ((match = regex.exec(content)) !== null) {
|
|
143808
|
+
vulnCounter++;
|
|
143809
|
+
const lineNum = content.substring(0, match.index).split("\n").length;
|
|
143810
|
+
const matchedLine = lines[lineNum - 1] || "";
|
|
143811
|
+
const snippet = matchedLine.trim().length > 100 ? matchedLine.trim().substring(0, 100) + "..." : matchedLine.trim();
|
|
143812
|
+
vulnerabilities.push({
|
|
143813
|
+
id: `${patternDef.id}-${vulnCounter}`,
|
|
143814
|
+
title: patternDef.title,
|
|
143815
|
+
severity: patternDef.severity,
|
|
143816
|
+
category: patternDef.category || "security-misconfiguration",
|
|
143817
|
+
location: {
|
|
143818
|
+
file: relPath,
|
|
143819
|
+
line: lineNum,
|
|
143820
|
+
snippet
|
|
143821
|
+
},
|
|
143822
|
+
description: patternDef.description,
|
|
143823
|
+
remediation: patternDef.remediation,
|
|
143824
|
+
cweId: patternDef.cweId,
|
|
143825
|
+
references: []
|
|
143826
|
+
});
|
|
143827
|
+
if (vulnCounter > 200) break;
|
|
143828
|
+
}
|
|
143829
|
+
}
|
|
143830
|
+
}
|
|
143831
|
+
return vulnerabilities;
|
|
143381
143832
|
}
|
|
143382
|
-
function
|
|
143383
|
-
|
|
143384
|
-
|
|
143385
|
-
|
|
143386
|
-
|
|
143387
|
-
|
|
143388
|
-
|
|
143389
|
-
|
|
143390
|
-
|
|
143391
|
-
|
|
143392
|
-
|
|
143833
|
+
async function scanDependencies(target) {
|
|
143834
|
+
const fs21 = await import("fs");
|
|
143835
|
+
const path23 = await import("path");
|
|
143836
|
+
const vulnerabilities = [];
|
|
143837
|
+
const resolved = path23.resolve(target);
|
|
143838
|
+
const pkgJsonPath = path23.join(resolved, "package.json");
|
|
143839
|
+
if (fs21.existsSync(pkgJsonPath)) {
|
|
143840
|
+
try {
|
|
143841
|
+
const pkg2 = JSON.parse(fs21.readFileSync(pkgJsonPath, "utf-8"));
|
|
143842
|
+
const allDeps = { ...pkg2.dependencies, ...pkg2.devDependencies };
|
|
143843
|
+
vulnerabilities.push(...checkKnownVulnerableDeps(allDeps, "package.json"));
|
|
143844
|
+
} catch {
|
|
143393
143845
|
}
|
|
143394
|
-
|
|
143846
|
+
}
|
|
143847
|
+
const pyprojectPath = path23.join(resolved, "pyproject.toml");
|
|
143848
|
+
if (fs21.existsSync(pyprojectPath)) {
|
|
143849
|
+
try {
|
|
143850
|
+
const content = fs21.readFileSync(pyprojectPath, "utf-8");
|
|
143851
|
+
const deps = extractPythonDeps(content);
|
|
143852
|
+
vulnerabilities.push(...checkKnownVulnerablePythonDeps(deps, "pyproject.toml"));
|
|
143853
|
+
} catch {
|
|
143854
|
+
}
|
|
143855
|
+
}
|
|
143856
|
+
const reqPath = path23.join(resolved, "requirements.txt");
|
|
143857
|
+
if (fs21.existsSync(reqPath)) {
|
|
143858
|
+
try {
|
|
143859
|
+
const content = fs21.readFileSync(reqPath, "utf-8");
|
|
143860
|
+
const deps = extractRequirementsTxtDeps(content);
|
|
143861
|
+
vulnerabilities.push(...checkKnownVulnerablePythonDeps(deps, "requirements.txt"));
|
|
143862
|
+
} catch {
|
|
143863
|
+
}
|
|
143864
|
+
}
|
|
143865
|
+
if (vulnerabilities.length === 0) {
|
|
143866
|
+
const manifests = [pkgJsonPath, pyprojectPath, reqPath].filter((p74) => fs21.existsSync(p74));
|
|
143867
|
+
if (manifests.length > 0) {
|
|
143868
|
+
vulnerabilities.push({
|
|
143869
|
+
id: "DEP-INFO-001",
|
|
143870
|
+
title: "Dependency audit recommended",
|
|
143871
|
+
severity: "informational",
|
|
143872
|
+
category: "vulnerable-components",
|
|
143873
|
+
location: { file: path23.relative(process.cwd(), manifests[0]) },
|
|
143874
|
+
description: `Found ${path23.basename(manifests[0])} \u2014 run language-specific dependency audit for comprehensive results`,
|
|
143875
|
+
remediation: "Run npm audit, pip-audit, or equivalent for full vulnerability check",
|
|
143876
|
+
references: []
|
|
143877
|
+
});
|
|
143878
|
+
}
|
|
143879
|
+
}
|
|
143880
|
+
return vulnerabilities;
|
|
143881
|
+
}
|
|
143882
|
+
var KNOWN_VULNERABLE_NPM = {
|
|
143883
|
+
"lodash": { maxSafe: "4.17.21", cve: "CVE-2021-23337", severity: "high", desc: "Prototype pollution in lodash" },
|
|
143884
|
+
"minimist": { maxSafe: "1.2.6", cve: "CVE-2021-44906", severity: "critical", desc: "Prototype pollution in minimist" },
|
|
143885
|
+
"node-fetch": { maxSafe: "2.6.7", cve: "CVE-2022-0235", severity: "high", desc: "Information exposure in node-fetch" },
|
|
143886
|
+
"express": { maxSafe: "4.19.2", cve: "CVE-2024-29041", severity: "medium", desc: "Open redirect in express" }
|
|
143887
|
+
};
|
|
143888
|
+
function checkKnownVulnerableDeps(deps, manifest) {
|
|
143889
|
+
const vulns = [];
|
|
143890
|
+
for (const [name, version] of Object.entries(deps)) {
|
|
143891
|
+
const known = KNOWN_VULNERABLE_NPM[name];
|
|
143892
|
+
if (known) {
|
|
143893
|
+
const cleanVersion = version.replace(/^[\^~>=<]+/, "");
|
|
143894
|
+
if (compareVersions(cleanVersion, known.maxSafe) < 0) {
|
|
143895
|
+
vulns.push({
|
|
143896
|
+
id: `DEP-${name}-${known.cve}`,
|
|
143897
|
+
title: `Vulnerable ${name} version`,
|
|
143898
|
+
severity: known.severity,
|
|
143899
|
+
category: "vulnerable-components",
|
|
143900
|
+
location: { file: manifest, dependency: { name, version: cleanVersion } },
|
|
143901
|
+
description: known.desc,
|
|
143902
|
+
remediation: `Upgrade ${name} to >= ${known.maxSafe}`,
|
|
143903
|
+
cveId: known.cve,
|
|
143904
|
+
references: [`https://nvd.nist.gov/vuln/detail/${known.cve}`]
|
|
143905
|
+
});
|
|
143906
|
+
}
|
|
143907
|
+
}
|
|
143908
|
+
}
|
|
143909
|
+
return vulns;
|
|
143910
|
+
}
|
|
143911
|
+
var KNOWN_VULNERABLE_PYTHON = {
|
|
143912
|
+
"python-jose": { cve: "CVE-2024-33663", severity: "critical", desc: "python-jose is abandoned and has known JWT vulnerabilities" },
|
|
143913
|
+
"pyjwt": { cve: "CVE-2022-29217", severity: "high", desc: "PyJWT algorithm confusion vulnerability (upgrade to >= 2.4.0)" },
|
|
143914
|
+
"python-multipart": { cve: "CVE-2026-24486", severity: "high", desc: "python-multipart DoS vulnerability" },
|
|
143915
|
+
"jinja2": { cve: "CVE-2024-34064", severity: "medium", desc: "Jinja2 XSS via template injection" },
|
|
143916
|
+
"urllib3": { cve: "CVE-2023-45803", severity: "medium", desc: "urllib3 request body exposure on redirect" },
|
|
143917
|
+
"requests": { cve: "CVE-2023-32681", severity: "medium", desc: "Requests proxy credential exposure" }
|
|
143918
|
+
};
|
|
143919
|
+
function extractPythonDeps(tomlContent) {
|
|
143920
|
+
const deps = [];
|
|
143921
|
+
const depMatch = tomlContent.match(/dependencies\s*=\s*\[([\s\S]*?)\]/);
|
|
143922
|
+
if (depMatch) {
|
|
143923
|
+
const matches = depMatch[1].matchAll(/["']([a-zA-Z0-9_-]+)/g);
|
|
143924
|
+
for (const m74 of matches) {
|
|
143925
|
+
deps.push(m74[1].toLowerCase());
|
|
143926
|
+
}
|
|
143927
|
+
}
|
|
143928
|
+
return deps;
|
|
143929
|
+
}
|
|
143930
|
+
function extractRequirementsTxtDeps(content) {
|
|
143931
|
+
return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map((line) => line.split(/[>=<!~\[]/)[0].trim().toLowerCase()).filter(Boolean);
|
|
143932
|
+
}
|
|
143933
|
+
function checkKnownVulnerablePythonDeps(deps, manifest) {
|
|
143934
|
+
const vulns = [];
|
|
143935
|
+
for (const dep of deps) {
|
|
143936
|
+
const known = KNOWN_VULNERABLE_PYTHON[dep];
|
|
143937
|
+
if (known) {
|
|
143938
|
+
vulns.push({
|
|
143939
|
+
id: `DEP-py-${dep}-${known.cve}`,
|
|
143940
|
+
title: `Vulnerable Python dependency: ${dep}`,
|
|
143941
|
+
severity: known.severity,
|
|
143942
|
+
category: "vulnerable-components",
|
|
143943
|
+
location: { file: manifest, dependency: { name: dep, version: "any" } },
|
|
143944
|
+
description: known.desc,
|
|
143945
|
+
remediation: dep === "python-jose" ? "Migrate to PyJWT or joserfc" : `Check for updates to ${dep}`,
|
|
143946
|
+
cveId: known.cve,
|
|
143947
|
+
references: [`https://nvd.nist.gov/vuln/detail/${known.cve}`]
|
|
143948
|
+
});
|
|
143949
|
+
}
|
|
143950
|
+
}
|
|
143951
|
+
return vulns;
|
|
143952
|
+
}
|
|
143953
|
+
function compareVersions(a37, b68) {
|
|
143954
|
+
const pa9 = a37.split(".").map(Number);
|
|
143955
|
+
const pb = b68.split(".").map(Number);
|
|
143956
|
+
for (let i58 = 0; i58 < 3; i58++) {
|
|
143957
|
+
const va5 = pa9[i58] || 0;
|
|
143958
|
+
const vb = pb[i58] || 0;
|
|
143959
|
+
if (va5 < vb) return -1;
|
|
143960
|
+
if (va5 > vb) return 1;
|
|
143961
|
+
}
|
|
143962
|
+
return 0;
|
|
143395
143963
|
}
|
|
143396
143964
|
function generateDASTFindings(url) {
|
|
143397
143965
|
return [
|
|
143398
143966
|
{
|
|
143399
|
-
id: "DAST-001",
|
|
143400
|
-
title: "
|
|
143401
|
-
severity: "
|
|
143967
|
+
id: "DAST-INFO-001",
|
|
143968
|
+
title: "DAST scan target noted",
|
|
143969
|
+
severity: "informational",
|
|
143402
143970
|
category: "security-misconfiguration",
|
|
143403
143971
|
location: { file: url },
|
|
143404
|
-
description:
|
|
143405
|
-
remediation: "
|
|
143406
|
-
references: ["https://owasp.org/www-project-
|
|
143972
|
+
description: `DAST target ${url} recorded. Full DAST requires integration with a dynamic scanner (e.g., ZAP, Burp).`,
|
|
143973
|
+
remediation: "Configure a DAST tool to scan the live application",
|
|
143974
|
+
references: ["https://owasp.org/www-project-zap/"]
|
|
143407
143975
|
}
|
|
143408
143976
|
];
|
|
143409
143977
|
}
|
|
@@ -143441,6 +144009,9 @@ function generateRecommendations5(vulnerabilities, summary) {
|
|
|
143441
144009
|
if (vulnerabilities.some((v62) => v62.category === "sensitive-data")) {
|
|
143442
144010
|
recs.push("Implement proper secrets management");
|
|
143443
144011
|
}
|
|
144012
|
+
if (vulnerabilities.some((v62) => v62.category === "vulnerable-components")) {
|
|
144013
|
+
recs.push("Run full dependency audit and update vulnerable packages");
|
|
144014
|
+
}
|
|
143444
144015
|
if (recs.length === 0) {
|
|
143445
144016
|
recs.push("No critical issues found. Continue regular security reviews.");
|
|
143446
144017
|
}
|
|
@@ -147777,7 +148348,7 @@ function getSharedGOAPPlanner() {
|
|
|
147777
148348
|
}
|
|
147778
148349
|
|
|
147779
148350
|
// src/planning/plan-executor.ts
|
|
147780
|
-
|
|
148351
|
+
init_safe_db();
|
|
147781
148352
|
init_unified_memory();
|
|
147782
148353
|
init_error_utils();
|
|
147783
148354
|
init_safe_json();
|
|
@@ -147812,7 +148383,7 @@ var PlanExecutor = class {
|
|
|
147812
148383
|
this.spawner = spawner;
|
|
147813
148384
|
this.config = { ...DEFAULT_CONFIG69, ...config };
|
|
147814
148385
|
if (!this.config.useUnified) {
|
|
147815
|
-
this.db =
|
|
148386
|
+
this.db = openDatabase(dbPath ?? ":memory:", { walMode: false });
|
|
147816
148387
|
this.db.pragma("journal_mode = WAL");
|
|
147817
148388
|
}
|
|
147818
148389
|
}
|
|
@@ -149756,7 +150327,7 @@ init_logging();
|
|
|
149756
150327
|
init_types();
|
|
149757
150328
|
|
|
149758
150329
|
// src/learning/v2-to-v3-migration.ts
|
|
149759
|
-
|
|
150330
|
+
init_safe_db();
|
|
149760
150331
|
init_error_utils();
|
|
149761
150332
|
init_safe_json();
|
|
149762
150333
|
init_logging();
|
|
@@ -150201,7 +150772,7 @@ init_logging();
|
|
|
150201
150772
|
var logger17 = LoggerFactory.create("pattern-lifecycle");
|
|
150202
150773
|
|
|
150203
150774
|
// src/learning/metrics-tracker.ts
|
|
150204
|
-
|
|
150775
|
+
init_safe_db();
|
|
150205
150776
|
init_qe_patterns();
|
|
150206
150777
|
init_safe_json();
|
|
150207
150778
|
init_logging();
|