verdaccio-security-filter 0.0.0 → 1.1.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/LICENSE +21 -0
- package/README.md +719 -4
- package/build/index.d.ts +86 -0
- package/build/index.js +583 -0
- package/build/lib/cve-checker.d.ts +47 -0
- package/build/lib/cve-checker.js +286 -0
- package/build/lib/license-checker.d.ts +37 -0
- package/build/lib/license-checker.js +124 -0
- package/build/lib/logger.d.ts +42 -0
- package/build/lib/logger.js +95 -0
- package/build/lib/metrics.d.ts +54 -0
- package/build/lib/metrics.js +202 -0
- package/build/lib/package-age-checker.d.ts +49 -0
- package/build/lib/package-age-checker.js +138 -0
- package/build/lib/whitelist-checker.d.ts +48 -0
- package/build/lib/whitelist-checker.js +168 -0
- package/build/types.d.ts +119 -0
- package/build/types.js +2 -0
- package/package.json +61 -6
- package/index.js +0 -3
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.MetricsCollector = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
/**
|
|
40
|
+
* Metrics collector for tracking security events
|
|
41
|
+
*/
|
|
42
|
+
class MetricsCollector {
|
|
43
|
+
constructor(config) {
|
|
44
|
+
this.metricsBuffer = [];
|
|
45
|
+
this.bufferSize = 100;
|
|
46
|
+
this.config = {
|
|
47
|
+
enabled: (config === null || config === void 0 ? void 0 : config.enabled) || false,
|
|
48
|
+
output: (config === null || config === void 0 ? void 0 : config.output) || 'stdout',
|
|
49
|
+
filePath: (config === null || config === void 0 ? void 0 : config.filePath) || './security-metrics.json',
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Record a security event
|
|
54
|
+
*/
|
|
55
|
+
record(event) {
|
|
56
|
+
if (!this.config.enabled) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
this.metricsBuffer.push(event);
|
|
60
|
+
if (this.metricsBuffer.length >= this.bufferSize) {
|
|
61
|
+
this.flush();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Record a block event
|
|
66
|
+
*/
|
|
67
|
+
recordBlock(packageName, version, reason, metadata) {
|
|
68
|
+
this.record({
|
|
69
|
+
timestamp: new Date().toISOString(),
|
|
70
|
+
event: 'block',
|
|
71
|
+
packageName,
|
|
72
|
+
version,
|
|
73
|
+
reason,
|
|
74
|
+
metadata,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Record a fallback event
|
|
79
|
+
*/
|
|
80
|
+
recordFallback(packageName, fromVersion, toVersion, reason) {
|
|
81
|
+
this.record({
|
|
82
|
+
timestamp: new Date().toISOString(),
|
|
83
|
+
event: 'fallback',
|
|
84
|
+
packageName,
|
|
85
|
+
version: fromVersion,
|
|
86
|
+
reason,
|
|
87
|
+
metadata: { toVersion },
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Record a publish rejection
|
|
92
|
+
*/
|
|
93
|
+
recordPublishRejected(packageName, version, reason) {
|
|
94
|
+
this.record({
|
|
95
|
+
timestamp: new Date().toISOString(),
|
|
96
|
+
event: 'publish_rejected',
|
|
97
|
+
packageName,
|
|
98
|
+
version,
|
|
99
|
+
reason,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Record a CVE detection
|
|
104
|
+
*/
|
|
105
|
+
recordCVE(packageName, version, cveId, severity) {
|
|
106
|
+
this.record({
|
|
107
|
+
timestamp: new Date().toISOString(),
|
|
108
|
+
event: 'cve_detected',
|
|
109
|
+
packageName,
|
|
110
|
+
version,
|
|
111
|
+
reason: `CVE ${cveId} (${severity})`,
|
|
112
|
+
metadata: { cveId, severity },
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Record a license block
|
|
117
|
+
*/
|
|
118
|
+
recordLicenseBlock(packageName, version, license, reason) {
|
|
119
|
+
this.record({
|
|
120
|
+
timestamp: new Date().toISOString(),
|
|
121
|
+
event: 'license_blocked',
|
|
122
|
+
packageName,
|
|
123
|
+
version,
|
|
124
|
+
reason,
|
|
125
|
+
metadata: { license },
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Record a package-too-new event
|
|
130
|
+
*/
|
|
131
|
+
recordPackageTooNew(packageName, version, reason, metadata) {
|
|
132
|
+
this.record({
|
|
133
|
+
timestamp: new Date().toISOString(),
|
|
134
|
+
event: 'package_too_new',
|
|
135
|
+
packageName,
|
|
136
|
+
version,
|
|
137
|
+
reason,
|
|
138
|
+
metadata,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Flush metrics buffer to output
|
|
143
|
+
*/
|
|
144
|
+
flush() {
|
|
145
|
+
if (this.metricsBuffer.length === 0) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (this.config.output === 'stdout') {
|
|
149
|
+
this.metricsBuffer.forEach(metric => {
|
|
150
|
+
console.log(JSON.stringify(metric));
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
else if (this.config.output === 'file' && this.config.filePath) {
|
|
154
|
+
this.writeToFile(this.metricsBuffer);
|
|
155
|
+
}
|
|
156
|
+
this.metricsBuffer = [];
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Write metrics to file
|
|
160
|
+
*/
|
|
161
|
+
writeToFile(metrics) {
|
|
162
|
+
try {
|
|
163
|
+
const filePath = this.config.filePath;
|
|
164
|
+
const dir = path.dirname(filePath);
|
|
165
|
+
// Ensure directory exists
|
|
166
|
+
if (!fs.existsSync(dir)) {
|
|
167
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
168
|
+
}
|
|
169
|
+
// Append to file
|
|
170
|
+
const content = metrics.map(m => JSON.stringify(m)).join('\n') + '\n';
|
|
171
|
+
fs.appendFileSync(filePath, content, 'utf8');
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
175
|
+
console.error('[Security Filter] Failed to write metrics:', message);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Get metrics summary
|
|
180
|
+
*/
|
|
181
|
+
getSummary() {
|
|
182
|
+
const summary = {
|
|
183
|
+
block: 0,
|
|
184
|
+
fallback: 0,
|
|
185
|
+
publish_rejected: 0,
|
|
186
|
+
cve_detected: 0,
|
|
187
|
+
license_blocked: 0,
|
|
188
|
+
package_too_new: 0,
|
|
189
|
+
};
|
|
190
|
+
this.metricsBuffer.forEach(metric => {
|
|
191
|
+
summary[metric.event] = (summary[metric.event] || 0) + 1;
|
|
192
|
+
});
|
|
193
|
+
return summary;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Cleanup - flush remaining metrics
|
|
197
|
+
*/
|
|
198
|
+
cleanup() {
|
|
199
|
+
this.flush();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
exports.MetricsCollector = MetricsCollector;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { PackageAgeConfig } from '../types';
|
|
2
|
+
import { Package } from '@verdaccio/types';
|
|
3
|
+
/**
|
|
4
|
+
* Package age checker to protect against newly created malicious packages
|
|
5
|
+
*/
|
|
6
|
+
export declare class PackageAgeChecker {
|
|
7
|
+
private config;
|
|
8
|
+
constructor(config?: PackageAgeConfig);
|
|
9
|
+
/**
|
|
10
|
+
* Check if a package is old enough to be trusted
|
|
11
|
+
*/
|
|
12
|
+
checkPackageAge(packageData: Package): {
|
|
13
|
+
allowed: boolean;
|
|
14
|
+
reason?: string;
|
|
15
|
+
ageDays?: number;
|
|
16
|
+
warnOnly?: boolean;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Check if a specific version is old enough to be trusted
|
|
20
|
+
*/
|
|
21
|
+
checkVersionAge(packageData: Package, version: string): {
|
|
22
|
+
allowed: boolean;
|
|
23
|
+
reason?: string;
|
|
24
|
+
ageDays?: number;
|
|
25
|
+
warnOnly?: boolean;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Get package creation date from time field
|
|
29
|
+
* The 'created' field in package.time represents when the package was first published
|
|
30
|
+
*/
|
|
31
|
+
private getPackageCreationDate;
|
|
32
|
+
/**
|
|
33
|
+
* Get version publish date from time field
|
|
34
|
+
*/
|
|
35
|
+
private getVersionPublishDate;
|
|
36
|
+
/**
|
|
37
|
+
* Calculate age in days from a date
|
|
38
|
+
*/
|
|
39
|
+
private calculateAgeDays;
|
|
40
|
+
/**
|
|
41
|
+
* Get summary of configuration
|
|
42
|
+
*/
|
|
43
|
+
getSummary(): {
|
|
44
|
+
enabled: boolean;
|
|
45
|
+
minPackageAgeDays: number;
|
|
46
|
+
minVersionAgeDays?: number;
|
|
47
|
+
warnOnly: boolean;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PackageAgeChecker = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Package age checker to protect against newly created malicious packages
|
|
6
|
+
*/
|
|
7
|
+
class PackageAgeChecker {
|
|
8
|
+
constructor(config) {
|
|
9
|
+
var _a, _b, _c;
|
|
10
|
+
this.config = {
|
|
11
|
+
enabled: (_a = config === null || config === void 0 ? void 0 : config.enabled) !== null && _a !== void 0 ? _a : false,
|
|
12
|
+
minPackageAgeDays: (_b = config === null || config === void 0 ? void 0 : config.minPackageAgeDays) !== null && _b !== void 0 ? _b : 0,
|
|
13
|
+
minVersionAgeDays: config === null || config === void 0 ? void 0 : config.minVersionAgeDays,
|
|
14
|
+
warnOnly: (_c = config === null || config === void 0 ? void 0 : config.warnOnly) !== null && _c !== void 0 ? _c : false,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Check if a package is old enough to be trusted
|
|
19
|
+
*/
|
|
20
|
+
checkPackageAge(packageData) {
|
|
21
|
+
if (!this.config.enabled) {
|
|
22
|
+
return { allowed: true };
|
|
23
|
+
}
|
|
24
|
+
// Get package creation date from time field
|
|
25
|
+
const createdDate = this.getPackageCreationDate(packageData);
|
|
26
|
+
if (!createdDate) {
|
|
27
|
+
// If we can't determine creation date, allow but warn
|
|
28
|
+
return {
|
|
29
|
+
allowed: true,
|
|
30
|
+
reason: 'Cannot determine package creation date',
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const ageDays = this.calculateAgeDays(createdDate);
|
|
34
|
+
if (ageDays < this.config.minPackageAgeDays) {
|
|
35
|
+
const warnOnlyValue = this.config.warnOnly || false;
|
|
36
|
+
return {
|
|
37
|
+
allowed: warnOnlyValue,
|
|
38
|
+
reason: `Package is only ${ageDays} days old (minimum: ${this.config.minPackageAgeDays} days)`,
|
|
39
|
+
ageDays,
|
|
40
|
+
warnOnly: warnOnlyValue,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return { allowed: true, ageDays };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Check if a specific version is old enough to be trusted
|
|
47
|
+
*/
|
|
48
|
+
checkVersionAge(packageData, version) {
|
|
49
|
+
if (!this.config.enabled || !this.config.minVersionAgeDays) {
|
|
50
|
+
return { allowed: true };
|
|
51
|
+
}
|
|
52
|
+
// Get version publish date from time field
|
|
53
|
+
const versionDate = this.getVersionPublishDate(packageData, version);
|
|
54
|
+
if (!versionDate) {
|
|
55
|
+
// If we can't determine version date, allow but warn
|
|
56
|
+
return {
|
|
57
|
+
allowed: true,
|
|
58
|
+
reason: `Cannot determine version ${version} publish date`,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
const ageDays = this.calculateAgeDays(versionDate);
|
|
62
|
+
if (ageDays < this.config.minVersionAgeDays) {
|
|
63
|
+
const warnOnlyValue = this.config.warnOnly || false;
|
|
64
|
+
return {
|
|
65
|
+
allowed: warnOnlyValue,
|
|
66
|
+
reason: `Version ${version} is only ${ageDays} days old (minimum: ${this.config.minVersionAgeDays} days)`,
|
|
67
|
+
ageDays,
|
|
68
|
+
warnOnly: warnOnlyValue,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
return { allowed: true, ageDays };
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Get package creation date from time field
|
|
75
|
+
* The 'created' field in package.time represents when the package was first published
|
|
76
|
+
*/
|
|
77
|
+
getPackageCreationDate(packageData) {
|
|
78
|
+
if (!packageData.time) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
// Try to get 'created' field first
|
|
82
|
+
if ('created' in packageData.time) {
|
|
83
|
+
const created = packageData.time.created;
|
|
84
|
+
if (typeof created === 'string') {
|
|
85
|
+
return new Date(created);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Fallback: find the oldest version
|
|
89
|
+
const versions = Object.keys(packageData.time).filter(key => key !== 'modified' && key !== 'created');
|
|
90
|
+
if (versions.length === 0) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
const dates = versions
|
|
94
|
+
.map(v => {
|
|
95
|
+
const timeValue = packageData.time[v];
|
|
96
|
+
return typeof timeValue === 'string' ? new Date(timeValue) : null;
|
|
97
|
+
})
|
|
98
|
+
.filter((d) => d !== null);
|
|
99
|
+
if (dates.length === 0) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
// Return the oldest date
|
|
103
|
+
return new Date(Math.min(...dates.map(d => d.getTime())));
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get version publish date from time field
|
|
107
|
+
*/
|
|
108
|
+
getVersionPublishDate(packageData, version) {
|
|
109
|
+
if (!packageData.time || !(version in packageData.time)) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
const timeValue = packageData.time[version];
|
|
113
|
+
if (typeof timeValue === 'string') {
|
|
114
|
+
return new Date(timeValue);
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Calculate age in days from a date
|
|
120
|
+
*/
|
|
121
|
+
calculateAgeDays(date) {
|
|
122
|
+
const now = new Date();
|
|
123
|
+
const diffMs = now.getTime() - date.getTime();
|
|
124
|
+
return Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Get summary of configuration
|
|
128
|
+
*/
|
|
129
|
+
getSummary() {
|
|
130
|
+
return {
|
|
131
|
+
enabled: this.config.enabled,
|
|
132
|
+
minPackageAgeDays: this.config.minPackageAgeDays,
|
|
133
|
+
minVersionAgeDays: this.config.minVersionAgeDays,
|
|
134
|
+
warnOnly: this.config.warnOnly || false,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
exports.PackageAgeChecker = PackageAgeChecker;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { WhitelistConfig } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Whitelist checker for package validation
|
|
4
|
+
*/
|
|
5
|
+
export declare class WhitelistChecker {
|
|
6
|
+
private config;
|
|
7
|
+
constructor(config?: WhitelistConfig);
|
|
8
|
+
/**
|
|
9
|
+
* Check if a package is whitelisted
|
|
10
|
+
*/
|
|
11
|
+
isWhitelisted(packageName: string, version?: string): {
|
|
12
|
+
allowed: boolean;
|
|
13
|
+
reason?: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Check if package name matches any whitelist pattern
|
|
17
|
+
*/
|
|
18
|
+
private matchesPattern;
|
|
19
|
+
/**
|
|
20
|
+
* Add package to whitelist
|
|
21
|
+
*/
|
|
22
|
+
addPackage(packageName: string, versionRange?: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* Remove package from whitelist
|
|
25
|
+
*/
|
|
26
|
+
removePackage(packageName: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* Add pattern to whitelist
|
|
29
|
+
*/
|
|
30
|
+
addPattern(pattern: string): void;
|
|
31
|
+
/**
|
|
32
|
+
* Check if package meets auto-approve criteria
|
|
33
|
+
* Note: This is a placeholder. Real implementation would require
|
|
34
|
+
* integration with npm registry API to fetch download stats, etc.
|
|
35
|
+
*/
|
|
36
|
+
meetsAutoApproveCriteria(_packageName: string): Promise<{
|
|
37
|
+
approved: boolean;
|
|
38
|
+
reason?: string;
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* Get whitelist summary
|
|
42
|
+
*/
|
|
43
|
+
getSummary(): {
|
|
44
|
+
totalPackages: number;
|
|
45
|
+
totalPatterns: number;
|
|
46
|
+
hasAutoApprove: boolean;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.WhitelistChecker = void 0;
|
|
46
|
+
const semver = __importStar(require("semver"));
|
|
47
|
+
/**
|
|
48
|
+
* Whitelist checker for package validation
|
|
49
|
+
*/
|
|
50
|
+
class WhitelistChecker {
|
|
51
|
+
constructor(config) {
|
|
52
|
+
this.config = {
|
|
53
|
+
packages: (config === null || config === void 0 ? void 0 : config.packages) || [],
|
|
54
|
+
patterns: (config === null || config === void 0 ? void 0 : config.patterns) || [],
|
|
55
|
+
versions: (config === null || config === void 0 ? void 0 : config.versions) || {},
|
|
56
|
+
autoApprove: config === null || config === void 0 ? void 0 : config.autoApprove,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Check if a package is whitelisted
|
|
61
|
+
*/
|
|
62
|
+
isWhitelisted(packageName, version) {
|
|
63
|
+
// Check exact package name match
|
|
64
|
+
if (this.config.packages.includes(packageName)) {
|
|
65
|
+
// If version is specified, check version constraint
|
|
66
|
+
if (version && this.config.versions && packageName in this.config.versions) {
|
|
67
|
+
const versionRange = this.config.versions[packageName];
|
|
68
|
+
if (!semver.satisfies(version, versionRange)) {
|
|
69
|
+
return {
|
|
70
|
+
allowed: false,
|
|
71
|
+
reason: `Version ${version} does not satisfy whitelist constraint ${versionRange}`,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return { allowed: true };
|
|
76
|
+
}
|
|
77
|
+
// Check pattern match
|
|
78
|
+
if (this.matchesPattern(packageName)) {
|
|
79
|
+
return { allowed: true };
|
|
80
|
+
}
|
|
81
|
+
// Not in whitelist
|
|
82
|
+
return {
|
|
83
|
+
allowed: false,
|
|
84
|
+
reason: 'Package is not in whitelist',
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Check if package name matches any whitelist pattern
|
|
89
|
+
*/
|
|
90
|
+
matchesPattern(packageName) {
|
|
91
|
+
return this.config.patterns.some(pattern => {
|
|
92
|
+
try {
|
|
93
|
+
const regex = new RegExp(pattern);
|
|
94
|
+
return regex.test(packageName);
|
|
95
|
+
}
|
|
96
|
+
catch (_a) {
|
|
97
|
+
console.error(`[Whitelist] Invalid pattern: ${pattern}`);
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Add package to whitelist
|
|
104
|
+
*/
|
|
105
|
+
addPackage(packageName, versionRange) {
|
|
106
|
+
if (!this.config.packages.includes(packageName)) {
|
|
107
|
+
this.config.packages.push(packageName);
|
|
108
|
+
}
|
|
109
|
+
if (versionRange) {
|
|
110
|
+
this.config.versions = this.config.versions || {};
|
|
111
|
+
this.config.versions[packageName] = versionRange;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Remove package from whitelist
|
|
116
|
+
*/
|
|
117
|
+
removePackage(packageName) {
|
|
118
|
+
const index = this.config.packages.indexOf(packageName);
|
|
119
|
+
if (index > -1) {
|
|
120
|
+
this.config.packages.splice(index, 1);
|
|
121
|
+
}
|
|
122
|
+
if (this.config.versions && packageName in this.config.versions) {
|
|
123
|
+
delete this.config.versions[packageName];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Add pattern to whitelist
|
|
128
|
+
*/
|
|
129
|
+
addPattern(pattern) {
|
|
130
|
+
if (!this.config.patterns.includes(pattern)) {
|
|
131
|
+
this.config.patterns.push(pattern);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Check if package meets auto-approve criteria
|
|
136
|
+
* Note: This is a placeholder. Real implementation would require
|
|
137
|
+
* integration with npm registry API to fetch download stats, etc.
|
|
138
|
+
*/
|
|
139
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
140
|
+
meetsAutoApproveCriteria(_packageName) {
|
|
141
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
142
|
+
if (!this.config.autoApprove) {
|
|
143
|
+
return { approved: false, reason: 'Auto-approve not configured' };
|
|
144
|
+
}
|
|
145
|
+
// Placeholder for npm registry API integration
|
|
146
|
+
// In a real implementation, you would:
|
|
147
|
+
// 1. Fetch package info from npm registry
|
|
148
|
+
// 2. Check weekly downloads against minDownloads
|
|
149
|
+
// 3. Check GitHub stars against minStars
|
|
150
|
+
// 4. Check if publisher is verified
|
|
151
|
+
return {
|
|
152
|
+
approved: false,
|
|
153
|
+
reason: 'Auto-approve requires npm registry API integration (not implemented)',
|
|
154
|
+
};
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Get whitelist summary
|
|
159
|
+
*/
|
|
160
|
+
getSummary() {
|
|
161
|
+
return {
|
|
162
|
+
totalPackages: this.config.packages.length,
|
|
163
|
+
totalPatterns: this.config.patterns.length,
|
|
164
|
+
hasAutoApprove: !!this.config.autoApprove,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
exports.WhitelistChecker = WhitelistChecker;
|