@rigour-labs/core 5.1.2 → 5.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.
|
@@ -21,5 +21,9 @@ export declare class SecurityDetector {
|
|
|
21
21
|
getSecuritySummary(): Promise<string>;
|
|
22
22
|
private getLockfileHash;
|
|
23
23
|
private getCachedResult;
|
|
24
|
+
private runBestAvailableAudit;
|
|
25
|
+
private getAuditCommandCandidates;
|
|
26
|
+
private extractVulnerabilities;
|
|
27
|
+
private toSecurityEntry;
|
|
24
28
|
private saveCache;
|
|
25
29
|
}
|
|
@@ -27,29 +27,8 @@ export class SecurityDetector {
|
|
|
27
27
|
if (cached) {
|
|
28
28
|
return cached;
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
cwd: this.rootDir,
|
|
33
|
-
reject: false // npm audit returns non-zero for found vulnerabilities
|
|
34
|
-
});
|
|
35
|
-
const auditData = JSON.parse(stdout);
|
|
36
|
-
const vulnerabilities = [];
|
|
37
|
-
if (auditData.vulnerabilities) {
|
|
38
|
-
for (const [name, vuln] of Object.entries(auditData.vulnerabilities)) {
|
|
39
|
-
const v = vuln;
|
|
40
|
-
// Dig into the advisory data
|
|
41
|
-
const via = v.via && Array.isArray(v.via) ? v.via[0] : null;
|
|
42
|
-
vulnerabilities.push({
|
|
43
|
-
cveId: via?.name || 'N/A',
|
|
44
|
-
packageName: name,
|
|
45
|
-
vulnerableRange: v.range,
|
|
46
|
-
severity: v.severity,
|
|
47
|
-
title: via?.title || `Vulnerability in ${name}`,
|
|
48
|
-
url: via?.url || `https://www.npmjs.com/package/${name}/vulnerability`,
|
|
49
|
-
currentVersion: v.nodes && v.nodes[0] ? v.version : undefined
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
}
|
|
30
|
+
const auditData = await this.runBestAvailableAudit();
|
|
31
|
+
const vulnerabilities = this.extractVulnerabilities(auditData);
|
|
53
32
|
const result = {
|
|
54
33
|
status: vulnerabilities.length > 0 ? 'VULNERABLE' : 'SECURE',
|
|
55
34
|
vulnerabilities: vulnerabilities.sort((a, b) => {
|
|
@@ -110,6 +89,68 @@ export class SecurityDetector {
|
|
|
110
89
|
}
|
|
111
90
|
return null;
|
|
112
91
|
}
|
|
92
|
+
async runBestAvailableAudit() {
|
|
93
|
+
const candidates = await this.getAuditCommandCandidates();
|
|
94
|
+
let lastError = null;
|
|
95
|
+
for (const candidate of candidates) {
|
|
96
|
+
try {
|
|
97
|
+
const { stdout, stderr } = await execa(candidate.cmd, candidate.args, {
|
|
98
|
+
cwd: this.rootDir,
|
|
99
|
+
reject: false // audit tools return non-zero when vulnerabilities are found
|
|
100
|
+
});
|
|
101
|
+
const output = stdout || stderr;
|
|
102
|
+
return JSON.parse(output);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
lastError = error;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
throw lastError || new Error('No audit command available');
|
|
109
|
+
}
|
|
110
|
+
async getAuditCommandCandidates() {
|
|
111
|
+
const hasPnpmLock = await fs.access(path.join(this.rootDir, 'pnpm-lock.yaml')).then(() => true).catch(() => false);
|
|
112
|
+
if (hasPnpmLock) {
|
|
113
|
+
return [
|
|
114
|
+
{ cmd: 'pnpm', args: ['audit', '--json'] },
|
|
115
|
+
{ cmd: 'npm', args: ['audit', '--json'] }
|
|
116
|
+
];
|
|
117
|
+
}
|
|
118
|
+
const hasYarnLock = await fs.access(path.join(this.rootDir, 'yarn.lock')).then(() => true).catch(() => false);
|
|
119
|
+
if (hasYarnLock) {
|
|
120
|
+
return [
|
|
121
|
+
{ cmd: 'yarn', args: ['npm', 'audit', '--json'] },
|
|
122
|
+
{ cmd: 'npm', args: ['audit', '--json'] }
|
|
123
|
+
];
|
|
124
|
+
}
|
|
125
|
+
return [{ cmd: 'npm', args: ['audit', '--json'] }];
|
|
126
|
+
}
|
|
127
|
+
extractVulnerabilities(auditData) {
|
|
128
|
+
const vulnerabilities = [];
|
|
129
|
+
if (!auditData || !auditData.vulnerabilities || typeof auditData.vulnerabilities !== 'object') {
|
|
130
|
+
return vulnerabilities;
|
|
131
|
+
}
|
|
132
|
+
for (const [name, vuln] of Object.entries(auditData.vulnerabilities)) {
|
|
133
|
+
vulnerabilities.push(this.toSecurityEntry(name, vuln));
|
|
134
|
+
}
|
|
135
|
+
return vulnerabilities;
|
|
136
|
+
}
|
|
137
|
+
toSecurityEntry(name, vuln) {
|
|
138
|
+
const viaList = Array.isArray(vuln?.via) ? vuln.via : [];
|
|
139
|
+
const via = viaList[0];
|
|
140
|
+
const cveId = via?.name ?? 'N/A';
|
|
141
|
+
const title = via?.title ?? `Vulnerability in ${name}`;
|
|
142
|
+
const url = via?.url ?? `https://www.npmjs.com/package/${name}/vulnerability`;
|
|
143
|
+
const currentVersion = vuln?.nodes?.[0] ? vuln.version : undefined;
|
|
144
|
+
return {
|
|
145
|
+
cveId,
|
|
146
|
+
packageName: name,
|
|
147
|
+
vulnerableRange: vuln.range,
|
|
148
|
+
severity: vuln.severity,
|
|
149
|
+
title,
|
|
150
|
+
url,
|
|
151
|
+
currentVersion,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
113
154
|
async saveCache(hash, result) {
|
|
114
155
|
try {
|
|
115
156
|
await fs.mkdir(path.dirname(this.cachePath), { recursive: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rigour-labs/core",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.2.0",
|
|
4
4
|
"description": "Deterministic quality gate engine for AI-generated code. AST analysis, drift detection, and Fix Packet generation across TypeScript, JavaScript, Python, Go, Ruby, and C#.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://rigour.run",
|
|
@@ -59,11 +59,11 @@
|
|
|
59
59
|
"@xenova/transformers": "^2.17.2",
|
|
60
60
|
"sqlite3": "^5.1.7",
|
|
61
61
|
"openai": "^4.104.0",
|
|
62
|
-
"@rigour-labs/brain-darwin-arm64": "5.
|
|
63
|
-
"@rigour-labs/brain-linux-x64": "5.
|
|
64
|
-
"@rigour-labs/brain-linux-arm64": "5.
|
|
65
|
-
"@rigour-labs/brain-
|
|
66
|
-
"@rigour-labs/brain-
|
|
62
|
+
"@rigour-labs/brain-darwin-arm64": "5.2.0",
|
|
63
|
+
"@rigour-labs/brain-linux-x64": "5.2.0",
|
|
64
|
+
"@rigour-labs/brain-linux-arm64": "5.2.0",
|
|
65
|
+
"@rigour-labs/brain-darwin-x64": "5.2.0",
|
|
66
|
+
"@rigour-labs/brain-win-x64": "5.2.0"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@types/fs-extra": "^11.0.4",
|