circle-ir 3.2.0 → 3.3.1
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 +2 -2
- package/dist/analysis/index.d.ts +2 -5
- package/dist/analysis/index.js +2 -6
- package/dist/analysis/index.js.map +1 -1
- package/dist/analysis/taint-matcher.js +1 -1
- package/dist/analysis/taint-matcher.js.map +1 -1
- package/dist/browser/circle-ir.js +38 -95
- package/dist/core/circle-ir-core.cjs +1 -1
- package/dist/core/circle-ir-core.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/logger.d.ts +28 -40
- package/dist/utils/logger.js +64 -137
- package/dist/utils/logger.js.map +1 -1
- package/package.json +3 -5
- package/dist/analysis/advisory-db.d.ts +0 -86
- package/dist/analysis/advisory-db.js +0 -104
- package/dist/analysis/advisory-db.js.map +0 -1
- package/dist/analysis/cargo-parser.d.ts +0 -42
- package/dist/analysis/cargo-parser.js +0 -102
- package/dist/analysis/cargo-parser.js.map +0 -1
- package/dist/analysis/dependency-scanner.d.ts +0 -79
- package/dist/analysis/dependency-scanner.js +0 -122
- package/dist/analysis/dependency-scanner.js.map +0 -1
package/dist/utils/logger.js
CHANGED
|
@@ -1,198 +1,125 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Centralized logging module
|
|
2
|
+
* Centralized logging module with dependency injection.
|
|
3
|
+
*
|
|
4
|
+
* By default uses a simple console-based logger (zero dependencies).
|
|
5
|
+
* Consumers can inject a custom logger (e.g. pino) via setLogger().
|
|
3
6
|
*
|
|
4
7
|
* Usage:
|
|
5
8
|
* import { logger } from './utils/logger.js';
|
|
6
9
|
* logger.info('Processing file', { file: 'test.java' });
|
|
7
10
|
* logger.error('Failed to parse', { error: err.message });
|
|
8
11
|
*
|
|
12
|
+
* Injecting a custom logger (e.g. from circle-pack):
|
|
13
|
+
* import pino from 'pino';
|
|
14
|
+
* import { setLogger } from 'circle-ir';
|
|
15
|
+
* setLogger(pino({ level: 'debug' }));
|
|
16
|
+
*
|
|
9
17
|
* Log Levels (in order of severity):
|
|
10
18
|
* - trace: Very detailed debugging
|
|
11
19
|
* - debug: Debugging information
|
|
12
|
-
* - info: General information (default
|
|
20
|
+
* - info: General information (default)
|
|
13
21
|
* - warn: Warnings
|
|
14
22
|
* - error: Errors
|
|
15
23
|
* - fatal: Fatal errors
|
|
16
24
|
* - silent: No logging
|
|
17
|
-
*
|
|
18
|
-
* Configuration:
|
|
19
|
-
* - Set LOG_LEVEL env var to change level
|
|
20
|
-
* - Set LOG_FORMAT=json for JSON output (default in non-TTY)
|
|
21
|
-
* - Set LOG_FORMAT=pretty for human-readable output
|
|
22
25
|
*/
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
const LOG_LEVELS = {
|
|
27
|
+
trace: 0,
|
|
28
|
+
debug: 1,
|
|
29
|
+
info: 2,
|
|
30
|
+
warn: 3,
|
|
31
|
+
error: 4,
|
|
32
|
+
fatal: 5,
|
|
33
|
+
silent: 6,
|
|
29
34
|
};
|
|
30
|
-
let
|
|
31
|
-
let
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
*/
|
|
35
|
-
function createLoggerOptions(config) {
|
|
36
|
-
const options = {
|
|
37
|
-
name: config.name,
|
|
38
|
-
level: config.level || 'info',
|
|
39
|
-
};
|
|
40
|
-
// Add pretty printing for TTY or when explicitly requested
|
|
41
|
-
if (config.pretty) {
|
|
42
|
-
options.transport = {
|
|
43
|
-
target: 'pino-pretty',
|
|
44
|
-
options: {
|
|
45
|
-
colorize: true,
|
|
46
|
-
translateTime: 'SYS:standard',
|
|
47
|
-
ignore: 'pid,hostname',
|
|
48
|
-
messageFormat: '{msg}',
|
|
49
|
-
singleLine: true,
|
|
50
|
-
},
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
return options;
|
|
35
|
+
let currentLevel = 'info';
|
|
36
|
+
let customLogger = null;
|
|
37
|
+
function shouldLog(level) {
|
|
38
|
+
return LOG_LEVELS[level] >= LOG_LEVELS[currentLevel];
|
|
54
39
|
}
|
|
55
40
|
/**
|
|
56
|
-
*
|
|
41
|
+
* Configure the logger. Should be called early in application startup.
|
|
57
42
|
*/
|
|
58
|
-
function
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
// Write to stderr to avoid polluting stdout for CLI tools
|
|
62
|
-
if (options.transport) {
|
|
63
|
-
// When using transport (pino-pretty), specify destination in options
|
|
64
|
-
options.transport.options = {
|
|
65
|
-
...options.transport.options,
|
|
66
|
-
destination: 2, // stderr file descriptor
|
|
67
|
-
};
|
|
68
|
-
loggerInstance = pino(options);
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
loggerInstance = pino(options, process.stderr);
|
|
72
|
-
}
|
|
43
|
+
export function configureLogger(config) {
|
|
44
|
+
if (config.level) {
|
|
45
|
+
currentLevel = config.level;
|
|
73
46
|
}
|
|
74
|
-
return loggerInstance;
|
|
75
47
|
}
|
|
76
48
|
/**
|
|
77
|
-
*
|
|
78
|
-
*
|
|
49
|
+
* Inject a custom logger implementation (e.g. pino).
|
|
50
|
+
* The custom logger receives all log calls regardless of level filtering —
|
|
51
|
+
* it is expected to handle its own level filtering.
|
|
79
52
|
*/
|
|
80
|
-
export function
|
|
81
|
-
|
|
82
|
-
const options = createLoggerOptions(currentConfig);
|
|
83
|
-
// Write to stderr to avoid polluting stdout for CLI tools
|
|
84
|
-
if (options.transport) {
|
|
85
|
-
options.transport.options = {
|
|
86
|
-
...options.transport.options,
|
|
87
|
-
destination: 2, // stderr file descriptor
|
|
88
|
-
};
|
|
89
|
-
loggerInstance = pino(options);
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
loggerInstance = pino(options, process.stderr);
|
|
93
|
-
}
|
|
53
|
+
export function setLogger(instance) {
|
|
54
|
+
customLogger = instance;
|
|
94
55
|
}
|
|
95
56
|
/**
|
|
96
57
|
* Set the log level dynamically
|
|
97
58
|
*/
|
|
98
59
|
export function setLogLevel(level) {
|
|
99
|
-
|
|
100
|
-
if (loggerInstance) {
|
|
101
|
-
loggerInstance.level = level;
|
|
102
|
-
}
|
|
60
|
+
currentLevel = level;
|
|
103
61
|
}
|
|
104
62
|
/**
|
|
105
63
|
* Get the current log level
|
|
106
64
|
*/
|
|
107
65
|
export function getLogLevel() {
|
|
108
|
-
return
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Create a child logger with additional context
|
|
112
|
-
*/
|
|
113
|
-
export function createChildLogger(bindings) {
|
|
114
|
-
return getLogger().child(bindings);
|
|
66
|
+
return currentLevel;
|
|
115
67
|
}
|
|
116
68
|
/**
|
|
117
69
|
* The main logger instance.
|
|
118
70
|
* Use this for all logging throughout the application.
|
|
119
71
|
*/
|
|
120
72
|
export const logger = {
|
|
121
|
-
/**
|
|
122
|
-
* Log at trace level (most verbose)
|
|
123
|
-
*/
|
|
124
73
|
trace: (msg, obj) => {
|
|
125
|
-
if (
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
else {
|
|
129
|
-
getLogger().trace(msg);
|
|
74
|
+
if (customLogger) {
|
|
75
|
+
customLogger.trace(msg, obj);
|
|
76
|
+
return;
|
|
130
77
|
}
|
|
78
|
+
if (shouldLog('trace'))
|
|
79
|
+
console.debug(obj ? `[TRACE] ${msg} ${JSON.stringify(obj)}` : `[TRACE] ${msg}`);
|
|
131
80
|
},
|
|
132
|
-
/**
|
|
133
|
-
* Log at debug level
|
|
134
|
-
*/
|
|
135
81
|
debug: (msg, obj) => {
|
|
136
|
-
if (
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
else {
|
|
140
|
-
getLogger().debug(msg);
|
|
82
|
+
if (customLogger) {
|
|
83
|
+
customLogger.debug(msg, obj);
|
|
84
|
+
return;
|
|
141
85
|
}
|
|
86
|
+
if (shouldLog('debug'))
|
|
87
|
+
console.debug(obj ? `[DEBUG] ${msg} ${JSON.stringify(obj)}` : `[DEBUG] ${msg}`);
|
|
142
88
|
},
|
|
143
|
-
/**
|
|
144
|
-
* Log at info level (default)
|
|
145
|
-
*/
|
|
146
89
|
info: (msg, obj) => {
|
|
147
|
-
if (
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
else {
|
|
151
|
-
getLogger().info(msg);
|
|
90
|
+
if (customLogger) {
|
|
91
|
+
customLogger.info(msg, obj);
|
|
92
|
+
return;
|
|
152
93
|
}
|
|
94
|
+
if (shouldLog('info'))
|
|
95
|
+
console.log(obj ? `[INFO] ${msg} ${JSON.stringify(obj)}` : `[INFO] ${msg}`);
|
|
153
96
|
},
|
|
154
|
-
/**
|
|
155
|
-
* Log at warn level
|
|
156
|
-
*/
|
|
157
97
|
warn: (msg, obj) => {
|
|
158
|
-
if (
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
else {
|
|
162
|
-
getLogger().warn(msg);
|
|
98
|
+
if (customLogger) {
|
|
99
|
+
customLogger.warn(msg, obj);
|
|
100
|
+
return;
|
|
163
101
|
}
|
|
102
|
+
if (shouldLog('warn'))
|
|
103
|
+
console.warn(obj ? `[WARN] ${msg} ${JSON.stringify(obj)}` : `[WARN] ${msg}`);
|
|
164
104
|
},
|
|
165
|
-
/**
|
|
166
|
-
* Log at error level
|
|
167
|
-
*/
|
|
168
105
|
error: (msg, obj) => {
|
|
169
|
-
if (
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
else {
|
|
173
|
-
getLogger().error(msg);
|
|
106
|
+
if (customLogger) {
|
|
107
|
+
customLogger.error(msg, obj);
|
|
108
|
+
return;
|
|
174
109
|
}
|
|
110
|
+
if (shouldLog('error'))
|
|
111
|
+
console.error(obj ? `[ERROR] ${msg} ${JSON.stringify(obj)}` : `[ERROR] ${msg}`);
|
|
175
112
|
},
|
|
176
|
-
/**
|
|
177
|
-
* Log at fatal level (most severe)
|
|
178
|
-
*/
|
|
179
113
|
fatal: (msg, obj) => {
|
|
180
|
-
if (
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
else {
|
|
184
|
-
getLogger().fatal(msg);
|
|
114
|
+
if (customLogger) {
|
|
115
|
+
customLogger.fatal(msg, obj);
|
|
116
|
+
return;
|
|
185
117
|
}
|
|
118
|
+
if (shouldLog('fatal'))
|
|
119
|
+
console.error(obj ? `[FATAL] ${msg} ${JSON.stringify(obj)}` : `[FATAL] ${msg}`);
|
|
186
120
|
},
|
|
187
|
-
/**
|
|
188
|
-
* Create a child logger with additional context
|
|
189
|
-
*/
|
|
190
|
-
child: (bindings) => createChildLogger(bindings),
|
|
191
|
-
/**
|
|
192
|
-
* Check if a level is enabled
|
|
193
|
-
*/
|
|
194
121
|
isLevelEnabled: (level) => {
|
|
195
|
-
return
|
|
122
|
+
return shouldLog(level);
|
|
196
123
|
},
|
|
197
124
|
};
|
|
198
125
|
//# sourceMappingURL=logger.js.map
|
package/dist/utils/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "circle-ir",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.1",
|
|
4
4
|
"description": "High-performance Static Application Security Testing (SAST) library for detecting security vulnerabilities through taint analysis",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"test:watch": "vitest",
|
|
35
35
|
"test:coverage": "vitest run --coverage",
|
|
36
36
|
"build": "tsc",
|
|
37
|
-
"build:browser": "esbuild src/browser.ts --bundle --format=esm --platform=browser --external:fs --external:fs/promises --external:path --external:module --external:crypto --
|
|
38
|
-
"build:core": "esbuild src/core-lib.ts --bundle --format=esm --platform=neutral --external:fs --external:fs/promises --external:path --external:module --external:
|
|
37
|
+
"build:browser": "esbuild src/browser.ts --bundle --format=esm --platform=browser --external:fs --external:fs/promises --external:path --external:module --external:crypto --outfile=dist/browser/circle-ir.js && mkdir -p dist/wasm && cp node_modules/web-tree-sitter/web-tree-sitter.wasm dist/wasm/ && cp wasm/*.wasm dist/wasm/",
|
|
38
|
+
"build:core": "esbuild src/core-lib.ts --bundle --format=esm --platform=neutral --external:fs --external:fs/promises --external:path --external:module --external:crypto --outfile=dist/core/circle-ir-core.js && esbuild src/core-lib.ts --bundle --format=cjs --platform=neutral --external:fs --external:fs/promises --external:path --external:module --external:crypto --outfile=dist/core/circle-ir-core.cjs && cp dist/core-lib.d.ts dist/core/circle-ir-core.d.ts",
|
|
39
39
|
"build:all": "npm run build && npm run build:browser && npm run build:core",
|
|
40
40
|
"clean": "rm -rf dist coverage *.tsbuildinfo *.tgz",
|
|
41
41
|
"typecheck": "tsc --noEmit",
|
|
@@ -87,7 +87,6 @@
|
|
|
87
87
|
"registry": "https://registry.npmjs.org/"
|
|
88
88
|
},
|
|
89
89
|
"dependencies": {
|
|
90
|
-
"pino": "^10.3.0",
|
|
91
90
|
"web-tree-sitter": "^0.26.3",
|
|
92
91
|
"yaml": "^2.8.2"
|
|
93
92
|
},
|
|
@@ -96,7 +95,6 @@
|
|
|
96
95
|
"@types/unzipper": "^0.10.11",
|
|
97
96
|
"@vitest/coverage-v8": "^3.0.0",
|
|
98
97
|
"esbuild": "^0.27.2",
|
|
99
|
-
"pino-pretty": "^13.1.3",
|
|
100
98
|
"tree-sitter-java": "^0.23.5",
|
|
101
99
|
"tree-sitter-python": "^0.25.0",
|
|
102
100
|
"tree-sitter-rust": "^0.24.0",
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* RustSec Advisory Database Integration
|
|
3
|
-
*
|
|
4
|
-
* Provides vulnerability data from the RustSec advisory database.
|
|
5
|
-
* Advisory data is bundled at build time for offline/deterministic usage.
|
|
6
|
-
*/
|
|
7
|
-
import type { Severity } from '../types/index.js';
|
|
8
|
-
export interface AdvisoryVulnerability {
|
|
9
|
-
/** Unique advisory ID (RUSTSEC-YYYY-NNNN) */
|
|
10
|
-
id: string;
|
|
11
|
-
/** Crate name */
|
|
12
|
-
package: string;
|
|
13
|
-
/** Advisory date (RFC 3339) */
|
|
14
|
-
date: string;
|
|
15
|
-
/** Advisory URL */
|
|
16
|
-
url: string;
|
|
17
|
-
/** CVSS score string */
|
|
18
|
-
cvss?: string;
|
|
19
|
-
/** Vulnerability categories */
|
|
20
|
-
categories: string[];
|
|
21
|
-
/** Search keywords */
|
|
22
|
-
keywords: string[];
|
|
23
|
-
/** Related identifiers (CVE, etc.) */
|
|
24
|
-
aliases: string[];
|
|
25
|
-
/** Affected functions with version constraints */
|
|
26
|
-
affectedFunctions?: {
|
|
27
|
-
name: string;
|
|
28
|
-
versions: string[];
|
|
29
|
-
}[];
|
|
30
|
-
/** Version constraints */
|
|
31
|
-
versions: {
|
|
32
|
-
patched?: string[];
|
|
33
|
-
unaffected?: string[];
|
|
34
|
-
};
|
|
35
|
-
/** Affected architectures */
|
|
36
|
-
affectedArch?: string[];
|
|
37
|
-
/** Affected operating systems */
|
|
38
|
-
affectedOs?: string[];
|
|
39
|
-
/** Human-readable description */
|
|
40
|
-
description: string;
|
|
41
|
-
/** Title/summary of the vulnerability */
|
|
42
|
-
title?: string;
|
|
43
|
-
}
|
|
44
|
-
export interface AdvisoryDatabase {
|
|
45
|
-
/** Map of crate name to list of advisories */
|
|
46
|
-
advisories: Map<string, AdvisoryVulnerability[]>;
|
|
47
|
-
/** When the database was last updated */
|
|
48
|
-
lastUpdated: string;
|
|
49
|
-
/** Source of the database */
|
|
50
|
-
source: 'bundled' | 'fetched';
|
|
51
|
-
/** Database format version */
|
|
52
|
-
version: string;
|
|
53
|
-
/** Statistics */
|
|
54
|
-
stats?: {
|
|
55
|
-
totalAdvisories: number;
|
|
56
|
-
uniqueCrates: number;
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Load the bundled advisory database
|
|
61
|
-
*/
|
|
62
|
-
export declare function loadBundledAdvisories(): AdvisoryDatabase;
|
|
63
|
-
/**
|
|
64
|
-
* Parse advisory JSON into database structure
|
|
65
|
-
*/
|
|
66
|
-
export declare function parseAdvisoryJson(json: {
|
|
67
|
-
version: string;
|
|
68
|
-
lastUpdated: string;
|
|
69
|
-
advisories: AdvisoryVulnerability[];
|
|
70
|
-
}): AdvisoryDatabase;
|
|
71
|
-
/**
|
|
72
|
-
* Map RustSec categories to severity levels
|
|
73
|
-
*/
|
|
74
|
-
export declare function categoryToSeverity(categories: string[]): Severity;
|
|
75
|
-
/**
|
|
76
|
-
* Get advisories for a specific crate
|
|
77
|
-
*/
|
|
78
|
-
export declare function getAdvisoriesForCrate(db: AdvisoryDatabase, crateName: string): AdvisoryVulnerability[];
|
|
79
|
-
/**
|
|
80
|
-
* Search advisories by CVE ID
|
|
81
|
-
*/
|
|
82
|
-
export declare function findAdvisoryByCve(db: AdvisoryDatabase, cveId: string): AdvisoryVulnerability | undefined;
|
|
83
|
-
/**
|
|
84
|
-
* Get all unique crate names with advisories
|
|
85
|
-
*/
|
|
86
|
-
export declare function getVulnerableCrates(db: AdvisoryDatabase): string[];
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* RustSec Advisory Database Integration
|
|
3
|
-
*
|
|
4
|
-
* Provides vulnerability data from the RustSec advisory database.
|
|
5
|
-
* Advisory data is bundled at build time for offline/deterministic usage.
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* Bundled advisory database (loaded lazily)
|
|
9
|
-
*/
|
|
10
|
-
let bundledDb = null;
|
|
11
|
-
/**
|
|
12
|
-
* Load the bundled advisory database
|
|
13
|
-
*/
|
|
14
|
-
export function loadBundledAdvisories() {
|
|
15
|
-
if (bundledDb) {
|
|
16
|
-
return bundledDb;
|
|
17
|
-
}
|
|
18
|
-
// Try to load bundled advisories
|
|
19
|
-
try {
|
|
20
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
21
|
-
const json = require('../../advisory-db.json');
|
|
22
|
-
bundledDb = parseAdvisoryJson(json);
|
|
23
|
-
return bundledDb;
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
// Return empty database if bundled data not available
|
|
27
|
-
return {
|
|
28
|
-
advisories: new Map(),
|
|
29
|
-
lastUpdated: new Date().toISOString(),
|
|
30
|
-
source: 'bundled',
|
|
31
|
-
version: '1.0',
|
|
32
|
-
stats: { totalAdvisories: 0, uniqueCrates: 0 },
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Parse advisory JSON into database structure
|
|
38
|
-
*/
|
|
39
|
-
export function parseAdvisoryJson(json) {
|
|
40
|
-
const advisories = new Map();
|
|
41
|
-
for (const advisory of json.advisories) {
|
|
42
|
-
const existing = advisories.get(advisory.package) || [];
|
|
43
|
-
existing.push(advisory);
|
|
44
|
-
advisories.set(advisory.package, existing);
|
|
45
|
-
}
|
|
46
|
-
return {
|
|
47
|
-
advisories,
|
|
48
|
-
lastUpdated: json.lastUpdated,
|
|
49
|
-
source: 'bundled',
|
|
50
|
-
version: json.version,
|
|
51
|
-
stats: {
|
|
52
|
-
totalAdvisories: json.advisories.length,
|
|
53
|
-
uniqueCrates: advisories.size,
|
|
54
|
-
},
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Map RustSec categories to severity levels
|
|
59
|
-
*/
|
|
60
|
-
export function categoryToSeverity(categories) {
|
|
61
|
-
const categorySet = new Set(categories);
|
|
62
|
-
// Critical: code execution, privilege escalation
|
|
63
|
-
if (categorySet.has('code-execution') ||
|
|
64
|
-
categorySet.has('privilege-escalation')) {
|
|
65
|
-
return 'critical';
|
|
66
|
-
}
|
|
67
|
-
// High: memory safety, denial of service
|
|
68
|
-
if (categorySet.has('memory-safety') || categorySet.has('denial-of-service')) {
|
|
69
|
-
return 'high';
|
|
70
|
-
}
|
|
71
|
-
// Medium: crypto issues, information disclosure
|
|
72
|
-
if (categorySet.has('crypto-failure') ||
|
|
73
|
-
categorySet.has('information-disclosure')) {
|
|
74
|
-
return 'medium';
|
|
75
|
-
}
|
|
76
|
-
// Default to medium for unknown categories
|
|
77
|
-
return 'medium';
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Get advisories for a specific crate
|
|
81
|
-
*/
|
|
82
|
-
export function getAdvisoriesForCrate(db, crateName) {
|
|
83
|
-
return db.advisories.get(crateName) || [];
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Search advisories by CVE ID
|
|
87
|
-
*/
|
|
88
|
-
export function findAdvisoryByCve(db, cveId) {
|
|
89
|
-
for (const advisories of db.advisories.values()) {
|
|
90
|
-
for (const advisory of advisories) {
|
|
91
|
-
if (advisory.aliases.includes(cveId)) {
|
|
92
|
-
return advisory;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return undefined;
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Get all unique crate names with advisories
|
|
100
|
-
*/
|
|
101
|
-
export function getVulnerableCrates(db) {
|
|
102
|
-
return Array.from(db.advisories.keys());
|
|
103
|
-
}
|
|
104
|
-
//# sourceMappingURL=advisory-db.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"advisory-db.js","sourceRoot":"","sources":["../../src/analysis/advisory-db.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cargo.lock parser for extracting crate dependencies and versions
|
|
3
|
-
*/
|
|
4
|
-
export interface CargoLockDependency {
|
|
5
|
-
name: string;
|
|
6
|
-
version: string;
|
|
7
|
-
source?: string;
|
|
8
|
-
checksum?: string;
|
|
9
|
-
}
|
|
10
|
-
export interface CargoLock {
|
|
11
|
-
version: number;
|
|
12
|
-
dependencies: CargoLockDependency[];
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Parse Cargo.lock TOML file content
|
|
16
|
-
*/
|
|
17
|
-
export declare function parseCargoLock(content: string): CargoLock;
|
|
18
|
-
/**
|
|
19
|
-
* Parse Cargo.toml to extract direct dependencies
|
|
20
|
-
*/
|
|
21
|
-
export interface CargoTomlDependency {
|
|
22
|
-
name: string;
|
|
23
|
-
version?: string;
|
|
24
|
-
path?: string;
|
|
25
|
-
git?: string;
|
|
26
|
-
features?: string[];
|
|
27
|
-
}
|
|
28
|
-
export interface CargoToml {
|
|
29
|
-
name?: string;
|
|
30
|
-
version?: string;
|
|
31
|
-
dependencies: CargoTomlDependency[];
|
|
32
|
-
devDependencies: CargoTomlDependency[];
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Parse Cargo.toml file content
|
|
36
|
-
*/
|
|
37
|
-
export declare function parseCargoToml(content: string): CargoToml;
|
|
38
|
-
/**
|
|
39
|
-
* Filter dependencies to only include registry-sourced crates
|
|
40
|
-
* (excludes path and git dependencies which can't be vulnerability-checked)
|
|
41
|
-
*/
|
|
42
|
-
export declare function filterRegistryDeps(deps: CargoLockDependency[]): CargoLockDependency[];
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cargo.lock parser for extracting crate dependencies and versions
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* Parse Cargo.lock TOML file content
|
|
6
|
-
*/
|
|
7
|
-
export function parseCargoLock(content) {
|
|
8
|
-
const dependencies = [];
|
|
9
|
-
// Extract version from the file
|
|
10
|
-
const versionMatch = content.match(/^version\s*=\s*(\d+)/m);
|
|
11
|
-
const version = versionMatch ? parseInt(versionMatch[1], 10) : 3;
|
|
12
|
-
// Parse [[package]] sections
|
|
13
|
-
// Format:
|
|
14
|
-
// [[package]]
|
|
15
|
-
// name = "crate-name"
|
|
16
|
-
// version = "1.0.0"
|
|
17
|
-
// source = "registry+..."
|
|
18
|
-
// checksum = "abc123..."
|
|
19
|
-
const packagePattern = /\[\[package\]\]\s*\n((?:(?!^\[\[|\[package\]).*\n?)*)/gm;
|
|
20
|
-
let match;
|
|
21
|
-
while ((match = packagePattern.exec(content)) !== null) {
|
|
22
|
-
const block = match[1];
|
|
23
|
-
const nameMatch = block.match(/^name\s*=\s*"([^"]+)"/m);
|
|
24
|
-
const versionMatch = block.match(/^version\s*=\s*"([^"]+)"/m);
|
|
25
|
-
const sourceMatch = block.match(/^source\s*=\s*"([^"]+)"/m);
|
|
26
|
-
const checksumMatch = block.match(/^checksum\s*=\s*"([^"]+)"/m);
|
|
27
|
-
if (nameMatch && versionMatch) {
|
|
28
|
-
dependencies.push({
|
|
29
|
-
name: nameMatch[1],
|
|
30
|
-
version: versionMatch[1],
|
|
31
|
-
source: sourceMatch?.[1],
|
|
32
|
-
checksum: checksumMatch?.[1],
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return { version, dependencies };
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Parse Cargo.toml file content
|
|
40
|
-
*/
|
|
41
|
-
export function parseCargoToml(content) {
|
|
42
|
-
const dependencies = [];
|
|
43
|
-
const devDependencies = [];
|
|
44
|
-
// Extract package name and version
|
|
45
|
-
const nameMatch = content.match(/^\[package\][^[]*name\s*=\s*"([^"]+)"/ms);
|
|
46
|
-
const versionMatch = content.match(/^\[package\][^[]*version\s*=\s*"([^"]+)"/ms);
|
|
47
|
-
// Parse [dependencies] section
|
|
48
|
-
const depsMatch = content.match(/\[dependencies\]\s*\n((?:(?!\[(?!dependencies\.))[^\n]*\n?)*)/m);
|
|
49
|
-
if (depsMatch) {
|
|
50
|
-
parseDependencySection(depsMatch[1], dependencies);
|
|
51
|
-
}
|
|
52
|
-
// Parse [dev-dependencies] section
|
|
53
|
-
const devDepsMatch = content.match(/\[dev-dependencies\]\s*\n((?:(?!\[(?!dev-dependencies\.))[^\n]*\n?)*)/m);
|
|
54
|
-
if (devDepsMatch) {
|
|
55
|
-
parseDependencySection(devDepsMatch[1], devDependencies);
|
|
56
|
-
}
|
|
57
|
-
return {
|
|
58
|
-
name: nameMatch?.[1],
|
|
59
|
-
version: versionMatch?.[1],
|
|
60
|
-
dependencies,
|
|
61
|
-
devDependencies,
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
function parseDependencySection(section, deps) {
|
|
65
|
-
// Simple dependency: crate = "1.0"
|
|
66
|
-
const simplePattern = /^(\w[\w-]*)\s*=\s*"([^"]+)"/gm;
|
|
67
|
-
let match;
|
|
68
|
-
while ((match = simplePattern.exec(section)) !== null) {
|
|
69
|
-
deps.push({
|
|
70
|
-
name: match[1],
|
|
71
|
-
version: match[2],
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
// Complex dependency: crate = { version = "1.0", features = [...] }
|
|
75
|
-
const complexPattern = /^(\w[\w-]*)\s*=\s*\{([^}]+)\}/gm;
|
|
76
|
-
while ((match = complexPattern.exec(section)) !== null) {
|
|
77
|
-
const name = match[1];
|
|
78
|
-
const attrs = match[2];
|
|
79
|
-
const versionMatch = attrs.match(/version\s*=\s*"([^"]+)"/);
|
|
80
|
-
const pathMatch = attrs.match(/path\s*=\s*"([^"]+)"/);
|
|
81
|
-
const gitMatch = attrs.match(/git\s*=\s*"([^"]+)"/);
|
|
82
|
-
deps.push({
|
|
83
|
-
name,
|
|
84
|
-
version: versionMatch?.[1],
|
|
85
|
-
path: pathMatch?.[1],
|
|
86
|
-
git: gitMatch?.[1],
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Filter dependencies to only include registry-sourced crates
|
|
92
|
-
* (excludes path and git dependencies which can't be vulnerability-checked)
|
|
93
|
-
*/
|
|
94
|
-
export function filterRegistryDeps(deps) {
|
|
95
|
-
return deps.filter((dep) => {
|
|
96
|
-
// Include if no source (defaults to registry) or explicitly from registry
|
|
97
|
-
if (!dep.source)
|
|
98
|
-
return true;
|
|
99
|
-
return dep.source.startsWith('registry+');
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
//# sourceMappingURL=cargo-parser.js.map
|