@preship/core 1.0.2 → 2.0.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/dist/index.d.ts +123 -1
- package/dist/index.js +129 -3
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -40,7 +40,125 @@ interface ScanResult {
|
|
|
40
40
|
passed: boolean;
|
|
41
41
|
scanDurationMs: number;
|
|
42
42
|
}
|
|
43
|
+
type SecuritySeverity = 'critical' | 'high' | 'medium' | 'low';
|
|
44
|
+
interface SecurityVulnerability {
|
|
45
|
+
id: string;
|
|
46
|
+
package: string;
|
|
47
|
+
version: string;
|
|
48
|
+
severity: SecuritySeverity;
|
|
49
|
+
summary: string;
|
|
50
|
+
fixedVersion?: string;
|
|
51
|
+
references: string[];
|
|
52
|
+
source: 'osv' | 'github-advisory' | 'npm-audit';
|
|
53
|
+
}
|
|
54
|
+
interface PackageHealth {
|
|
55
|
+
package: string;
|
|
56
|
+
version: string;
|
|
57
|
+
deprecated: boolean;
|
|
58
|
+
deprecationMessage?: string;
|
|
59
|
+
outdated: boolean;
|
|
60
|
+
latestVersion?: string;
|
|
61
|
+
majorVersionsBehind?: number;
|
|
62
|
+
unmaintained: boolean;
|
|
63
|
+
lastPublishDate?: string;
|
|
64
|
+
weeklyDownloads?: number;
|
|
65
|
+
}
|
|
66
|
+
type SecurityPolicyLevel = 'default' | 'strict' | 'lenient';
|
|
67
|
+
interface SecurityFinding {
|
|
68
|
+
type: 'vulnerability' | 'deprecated' | 'outdated' | 'unmaintained';
|
|
69
|
+
severity: SecuritySeverity;
|
|
70
|
+
package: string;
|
|
71
|
+
version: string;
|
|
72
|
+
message: string;
|
|
73
|
+
details?: SecurityVulnerability | PackageHealth;
|
|
74
|
+
}
|
|
75
|
+
interface SecurityResult {
|
|
76
|
+
enabled: boolean;
|
|
77
|
+
passed: boolean;
|
|
78
|
+
totalPackages: number;
|
|
79
|
+
vulnerabilities: SecurityVulnerability[];
|
|
80
|
+
healthIssues: PackageHealth[];
|
|
81
|
+
findings: SecurityFinding[];
|
|
82
|
+
stats: {
|
|
83
|
+
critical: number;
|
|
84
|
+
high: number;
|
|
85
|
+
medium: number;
|
|
86
|
+
low: number;
|
|
87
|
+
deprecated: number;
|
|
88
|
+
outdated: number;
|
|
89
|
+
unmaintained: number;
|
|
90
|
+
};
|
|
91
|
+
scanDurationMs: number;
|
|
92
|
+
}
|
|
93
|
+
type SecretSeverity = 'critical' | 'high' | 'medium' | 'low';
|
|
94
|
+
interface SecretRule {
|
|
95
|
+
id: string;
|
|
96
|
+
description: string;
|
|
97
|
+
severity: SecretSeverity;
|
|
98
|
+
keywords: string[];
|
|
99
|
+
pattern: RegExp;
|
|
100
|
+
entropyThreshold?: number;
|
|
101
|
+
allowPatterns?: RegExp[];
|
|
102
|
+
}
|
|
103
|
+
interface SecretFinding {
|
|
104
|
+
ruleId: string;
|
|
105
|
+
description: string;
|
|
106
|
+
severity: SecretSeverity;
|
|
107
|
+
file: string;
|
|
108
|
+
line: number;
|
|
109
|
+
column: number;
|
|
110
|
+
match: string;
|
|
111
|
+
entropy?: number;
|
|
112
|
+
}
|
|
113
|
+
interface SecretsResult {
|
|
114
|
+
enabled: boolean;
|
|
115
|
+
passed: boolean;
|
|
116
|
+
filesScanned: number;
|
|
117
|
+
findings: SecretFinding[];
|
|
118
|
+
stats: {
|
|
119
|
+
critical: number;
|
|
120
|
+
high: number;
|
|
121
|
+
medium: number;
|
|
122
|
+
low: number;
|
|
123
|
+
};
|
|
124
|
+
scanDurationMs: number;
|
|
125
|
+
}
|
|
126
|
+
interface UnifiedScanResult {
|
|
127
|
+
version: string;
|
|
128
|
+
projectPath: string;
|
|
129
|
+
projectType: ProjectType;
|
|
130
|
+
framework?: string;
|
|
131
|
+
timestamp: string;
|
|
132
|
+
passed: boolean;
|
|
133
|
+
mode: ResolverMode;
|
|
134
|
+
policy: string;
|
|
135
|
+
modules: {
|
|
136
|
+
license?: ScanResult;
|
|
137
|
+
security?: SecurityResult;
|
|
138
|
+
secrets?: SecretsResult;
|
|
139
|
+
};
|
|
140
|
+
totalScanDurationMs: number;
|
|
141
|
+
}
|
|
43
142
|
type ResolverMode = 'auto' | 'online' | 'local';
|
|
143
|
+
interface ModuleConfig {
|
|
144
|
+
license: boolean;
|
|
145
|
+
security: boolean;
|
|
146
|
+
secrets: boolean;
|
|
147
|
+
}
|
|
148
|
+
interface SecurityConfig {
|
|
149
|
+
severity: SecurityPolicyLevel;
|
|
150
|
+
failOn: SecuritySeverity;
|
|
151
|
+
checkOutdated: boolean;
|
|
152
|
+
checkDeprecated: boolean;
|
|
153
|
+
checkUnmaintained: boolean;
|
|
154
|
+
outdatedMajorThreshold: number;
|
|
155
|
+
unmaintainedYears: number;
|
|
156
|
+
}
|
|
157
|
+
interface SecretsConfig {
|
|
158
|
+
scanPaths: string[];
|
|
159
|
+
allowPaths: string[];
|
|
160
|
+
allowRules: string[];
|
|
161
|
+
}
|
|
44
162
|
interface PreshipConfig {
|
|
45
163
|
policy?: string;
|
|
46
164
|
reject?: string[];
|
|
@@ -56,6 +174,9 @@ interface PreshipConfig {
|
|
|
56
174
|
cache?: boolean;
|
|
57
175
|
cacheTTL?: number;
|
|
58
176
|
scanTimeout?: number;
|
|
177
|
+
modules?: Partial<ModuleConfig>;
|
|
178
|
+
security?: Partial<SecurityConfig>;
|
|
179
|
+
secrets?: Partial<SecretsConfig>;
|
|
59
180
|
}
|
|
60
181
|
interface ExceptionEntry {
|
|
61
182
|
package: string;
|
|
@@ -73,6 +194,7 @@ interface PolicyTemplate {
|
|
|
73
194
|
scanDevDependencies: boolean;
|
|
74
195
|
}
|
|
75
196
|
|
|
197
|
+
declare function getDefaultConfig(): PreshipConfig;
|
|
76
198
|
declare function loadConfig(projectPath: string): PreshipConfig;
|
|
77
199
|
|
|
78
200
|
declare function detectProjects(rootPath: string): DetectedProject[];
|
|
@@ -238,4 +360,4 @@ interface ScanTimeoutController {
|
|
|
238
360
|
*/
|
|
239
361
|
declare function createScanTimeoutController(timeout?: number): ScanTimeoutController;
|
|
240
362
|
|
|
241
|
-
export { AdaptiveRateLimiter, type CacheEntry, type CacheFile, type Dependency, type DetectedProject, type ExceptionEntry, type LicenseSource, type ParsedDependency, type PolicyResult, type PolicyTemplate, type PolicyVerdict, type PreshipConfig, type ProjectType, type ResolverMode, type ScanResult, type ScanTimeoutController, cacheKey, createEmptyCache, createScanTimeoutController, detectProjects, getCacheEntry, getOrCreateKey, loadCache, loadConfig, parseNpmLockfile, parsePnpmLockfile, parseYarnLockfile, saveCache, setCacheEntry };
|
|
363
|
+
export { AdaptiveRateLimiter, type CacheEntry, type CacheFile, type Dependency, type DetectedProject, type ExceptionEntry, type LicenseSource, type ModuleConfig, type PackageHealth, type ParsedDependency, type PolicyResult, type PolicyTemplate, type PolicyVerdict, type PreshipConfig, type ProjectType, type ResolverMode, type ScanResult, type ScanTimeoutController, type SecretFinding, type SecretRule, type SecretSeverity, type SecretsConfig, type SecretsResult, type SecurityConfig, type SecurityFinding, type SecurityPolicyLevel, type SecurityResult, type SecuritySeverity, type SecurityVulnerability, type UnifiedScanResult, cacheKey, createEmptyCache, createScanTimeoutController, detectProjects, getCacheEntry, getDefaultConfig, getOrCreateKey, loadCache, loadConfig, parseNpmLockfile, parsePnpmLockfile, parseYarnLockfile, saveCache, setCacheEntry };
|
package/dist/index.js
CHANGED
|
@@ -36,6 +36,7 @@ __export(index_exports, {
|
|
|
36
36
|
createScanTimeoutController: () => createScanTimeoutController,
|
|
37
37
|
detectProjects: () => detectProjects,
|
|
38
38
|
getCacheEntry: () => getCacheEntry,
|
|
39
|
+
getDefaultConfig: () => getDefaultConfig,
|
|
39
40
|
getOrCreateKey: () => getOrCreateKey,
|
|
40
41
|
loadCache: () => loadCache,
|
|
41
42
|
loadConfig: () => loadConfig,
|
|
@@ -56,9 +57,11 @@ var CONFIG_FILENAMES = [
|
|
|
56
57
|
"preship-config.yaml",
|
|
57
58
|
"preship-config.json"
|
|
58
59
|
];
|
|
59
|
-
var VALID_POLICIES = ["commercial-safe", "strict", "permissive-only"];
|
|
60
|
+
var VALID_POLICIES = ["commercial-safe", "saas-safe", "distribution-safe", "strict", "permissive-only"];
|
|
60
61
|
var VALID_OUTPUTS = ["table", "json", "csv"];
|
|
61
62
|
var VALID_MODES = ["auto", "online", "local"];
|
|
63
|
+
var VALID_SECURITY_SEVERITIES = ["default", "strict", "lenient"];
|
|
64
|
+
var VALID_SECURITY_FAIL_ON = ["critical", "high", "medium", "low"];
|
|
62
65
|
function validateConfig(config, filePath) {
|
|
63
66
|
if (config.policy !== void 0) {
|
|
64
67
|
if (typeof config.policy !== "string" || !VALID_POLICIES.includes(config.policy)) {
|
|
@@ -190,6 +193,97 @@ function validateConfig(config, filePath) {
|
|
|
190
193
|
);
|
|
191
194
|
}
|
|
192
195
|
}
|
|
196
|
+
if (config.modules !== void 0) {
|
|
197
|
+
if (typeof config.modules !== "object" || config.modules === null || Array.isArray(config.modules)) {
|
|
198
|
+
throw new Error(
|
|
199
|
+
`Invalid preship-config at ${filePath}:
|
|
200
|
+
'modules' must be an object with boolean values (e.g., { license: true, security: true, secrets: true }).
|
|
201
|
+
See https://github.com/dipen-code/preship for config docs.`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
const m = config.modules;
|
|
205
|
+
for (const key of ["license", "security", "secrets"]) {
|
|
206
|
+
if (m[key] !== void 0 && typeof m[key] !== "boolean") {
|
|
207
|
+
throw new Error(
|
|
208
|
+
`Invalid preship-config at ${filePath}:
|
|
209
|
+
'modules.${key}' must be a boolean, got ${typeof m[key]}.
|
|
210
|
+
See https://github.com/dipen-code/preship for config docs.`
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (config.security !== void 0) {
|
|
216
|
+
if (typeof config.security !== "object" || config.security === null || Array.isArray(config.security)) {
|
|
217
|
+
throw new Error(
|
|
218
|
+
`Invalid preship-config at ${filePath}:
|
|
219
|
+
'security' must be an object.
|
|
220
|
+
See https://github.com/dipen-code/preship for config docs.`
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
const s = config.security;
|
|
224
|
+
if (s.severity !== void 0 && (typeof s.severity !== "string" || !VALID_SECURITY_SEVERITIES.includes(s.severity))) {
|
|
225
|
+
throw new Error(
|
|
226
|
+
`Invalid preship-config at ${filePath}:
|
|
227
|
+
'security.severity' must be one of: ${VALID_SECURITY_SEVERITIES.join(", ")}, got '${s.severity}'.
|
|
228
|
+
See https://github.com/dipen-code/preship for config docs.`
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
if (s.failOn !== void 0 && (typeof s.failOn !== "string" || !VALID_SECURITY_FAIL_ON.includes(s.failOn))) {
|
|
232
|
+
throw new Error(
|
|
233
|
+
`Invalid preship-config at ${filePath}:
|
|
234
|
+
'security.failOn' must be one of: ${VALID_SECURITY_FAIL_ON.join(", ")}, got '${s.failOn}'.
|
|
235
|
+
See https://github.com/dipen-code/preship for config docs.`
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
for (const boolField of ["checkOutdated", "checkDeprecated", "checkUnmaintained"]) {
|
|
239
|
+
if (s[boolField] !== void 0 && typeof s[boolField] !== "boolean") {
|
|
240
|
+
throw new Error(
|
|
241
|
+
`Invalid preship-config at ${filePath}:
|
|
242
|
+
'security.${boolField}' must be a boolean, got ${typeof s[boolField]}.
|
|
243
|
+
See https://github.com/dipen-code/preship for config docs.`
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
for (const numField of ["outdatedMajorThreshold", "unmaintainedYears"]) {
|
|
248
|
+
if (s[numField] !== void 0 && (typeof s[numField] !== "number" || s[numField] <= 0)) {
|
|
249
|
+
throw new Error(
|
|
250
|
+
`Invalid preship-config at ${filePath}:
|
|
251
|
+
'security.${numField}' must be a positive number, got '${s[numField]}'.
|
|
252
|
+
See https://github.com/dipen-code/preship for config docs.`
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (config.secrets !== void 0) {
|
|
258
|
+
if (typeof config.secrets !== "object" || config.secrets === null || Array.isArray(config.secrets)) {
|
|
259
|
+
throw new Error(
|
|
260
|
+
`Invalid preship-config at ${filePath}:
|
|
261
|
+
'secrets' must be an object.
|
|
262
|
+
See https://github.com/dipen-code/preship for config docs.`
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
const sec = config.secrets;
|
|
266
|
+
for (const arrField of ["scanPaths", "allowPaths", "allowRules"]) {
|
|
267
|
+
if (sec[arrField] !== void 0) {
|
|
268
|
+
if (!Array.isArray(sec[arrField])) {
|
|
269
|
+
throw new Error(
|
|
270
|
+
`Invalid preship-config at ${filePath}:
|
|
271
|
+
'secrets.${arrField}' must be an array of strings.
|
|
272
|
+
See https://github.com/dipen-code/preship for config docs.`
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
for (const item of sec[arrField]) {
|
|
276
|
+
if (typeof item !== "string") {
|
|
277
|
+
throw new Error(
|
|
278
|
+
`Invalid preship-config at ${filePath}:
|
|
279
|
+
'secrets.${arrField}' must contain only strings, found ${typeof item}.
|
|
280
|
+
See https://github.com/dipen-code/preship for config docs.`
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
193
287
|
return config;
|
|
194
288
|
}
|
|
195
289
|
function getDefaultConfig() {
|
|
@@ -205,8 +299,27 @@ function getDefaultConfig() {
|
|
|
205
299
|
cache: true,
|
|
206
300
|
cacheTTL: 604800,
|
|
207
301
|
// 7 days in seconds
|
|
208
|
-
scanTimeout: 6e4
|
|
302
|
+
scanTimeout: 6e4,
|
|
209
303
|
// 60 seconds in ms (0 = disabled)
|
|
304
|
+
modules: {
|
|
305
|
+
license: true,
|
|
306
|
+
security: true,
|
|
307
|
+
secrets: true
|
|
308
|
+
},
|
|
309
|
+
security: {
|
|
310
|
+
severity: "default",
|
|
311
|
+
failOn: "high",
|
|
312
|
+
checkOutdated: true,
|
|
313
|
+
checkDeprecated: true,
|
|
314
|
+
checkUnmaintained: true,
|
|
315
|
+
outdatedMajorThreshold: 3,
|
|
316
|
+
unmaintainedYears: 2
|
|
317
|
+
},
|
|
318
|
+
secrets: {
|
|
319
|
+
scanPaths: [],
|
|
320
|
+
allowPaths: [],
|
|
321
|
+
allowRules: []
|
|
322
|
+
}
|
|
210
323
|
};
|
|
211
324
|
}
|
|
212
325
|
function loadConfig(projectPath) {
|
|
@@ -244,7 +357,19 @@ function loadConfig(projectPath) {
|
|
|
244
357
|
return {
|
|
245
358
|
...defaults,
|
|
246
359
|
...validated,
|
|
247
|
-
exceptions: validated.exceptions ?? defaults.exceptions
|
|
360
|
+
exceptions: validated.exceptions ?? defaults.exceptions,
|
|
361
|
+
modules: {
|
|
362
|
+
...defaults.modules,
|
|
363
|
+
...validated.modules ?? {}
|
|
364
|
+
},
|
|
365
|
+
security: {
|
|
366
|
+
...defaults.security,
|
|
367
|
+
...validated.security ?? {}
|
|
368
|
+
},
|
|
369
|
+
secrets: {
|
|
370
|
+
...defaults.secrets,
|
|
371
|
+
...validated.secrets ?? {}
|
|
372
|
+
}
|
|
248
373
|
};
|
|
249
374
|
}
|
|
250
375
|
return getDefaultConfig();
|
|
@@ -901,6 +1026,7 @@ function createScanTimeoutController(timeout) {
|
|
|
901
1026
|
createScanTimeoutController,
|
|
902
1027
|
detectProjects,
|
|
903
1028
|
getCacheEntry,
|
|
1029
|
+
getDefaultConfig,
|
|
904
1030
|
getOrCreateKey,
|
|
905
1031
|
loadCache,
|
|
906
1032
|
loadConfig,
|
package/package.json
CHANGED