verdaccio-security-filter 1.3.4 → 1.3.6

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.
Files changed (2) hide show
  1. package/build/index.js +50 -16
  2. package/package.json +3 -2
package/build/index.js CHANGED
@@ -193,7 +193,13 @@ class SecurityFilterPlugin {
193
193
  this.logger.info(`[Middleware] Config mode: ${this.config.mode || 'NOT SET'}`);
194
194
  app.use((req, res, next) => __awaiter(this, void 0, void 0, function* () {
195
195
  try {
196
- const urlMatch = req.url.match(/^\/(@[^/]+\/)?([^/]+)(?:\/-\/([^/]+\.tgz))?/);
196
+ let path = req.url.split('?')[0];
197
+ try {
198
+ path = decodeURIComponent(path);
199
+ }
200
+ catch (_a) {
201
+ }
202
+ const urlMatch = path.match(/^\/(@[^/]+\/)?([^/]+)(?:\/-\/([^/]+\.tgz))?/);
197
203
  if (!urlMatch) {
198
204
  this.logger.debug(`[Middleware] Non-package request: ${req.method} ${req.url}`);
199
205
  return next();
@@ -269,14 +275,15 @@ class SecurityFilterPlugin {
269
275
  filter_metadata(packageInfo) {
270
276
  return __awaiter(this, void 0, void 0, function* () {
271
277
  var _a, _b, _c, _d, _e, _f, _g, _h;
272
- const packageName = packageInfo.name;
278
+ let pkg = packageInfo;
279
+ const packageName = pkg.name;
273
280
  this.logger.info(`[filter_metadata] --> Processing: ${packageName}`);
274
281
  try {
275
282
  const blockResult = yield this._checkPackageBlock(packageName);
276
283
  if (blockResult.blocked) {
277
284
  this.logger.warn(`[filter_metadata] BLOCKED: ${packageName}@* - ${blockResult.reason}`);
278
285
  this.metrics.recordBlock(packageName, '*', blockResult.reason);
279
- return Object.assign(Object.assign({}, packageInfo), { versions: {}, 'dist-tags': {}, security: {
286
+ return Object.assign(Object.assign({}, pkg), { versions: {}, 'dist-tags': {}, security: {
280
287
  blocked: true,
281
288
  reason: blockResult.reason,
282
289
  plugin: {
@@ -289,7 +296,7 @@ class SecurityFilterPlugin {
289
296
  } });
290
297
  }
291
298
  if ((_a = this.config.cveCheck) === null || _a === void 0 ? void 0 : _a.enabled) {
292
- const versions = Object.keys(packageInfo.versions || {});
299
+ const versions = Object.keys(pkg.versions || {});
293
300
  const vulnerableVersions = [];
294
301
  const BATCH_SIZE = 10;
295
302
  for (let i = 0; i < versions.length; i += BATCH_SIZE) {
@@ -310,7 +317,7 @@ class SecurityFilterPlugin {
310
317
  const reason = `Package has ${vulnerableVersions.length} vulnerable version(s)`;
311
318
  this.logger.warn(`[filter_metadata] CVE BLOCKED: ${packageName} - ${reason}`);
312
319
  this.metrics.recordBlock(packageName, '*', reason);
313
- return Object.assign(Object.assign({}, packageInfo), { versions: {}, 'dist-tags': {}, security: {
320
+ return Object.assign(Object.assign({}, pkg), { versions: {}, 'dist-tags': {}, security: {
314
321
  blocked: true,
315
322
  reason,
316
323
  vulnerableVersions,
@@ -323,14 +330,14 @@ class SecurityFilterPlugin {
323
330
  }
324
331
  }
325
332
  if (this.config.licenses && this.config.licenses.allowed && this.config.licenses.allowed.length > 0) {
326
- const latestVersion = (_b = packageInfo['dist-tags']) === null || _b === void 0 ? void 0 : _b.latest;
327
- if (latestVersion && ((_c = packageInfo.versions) === null || _c === void 0 ? void 0 : _c[latestVersion])) {
328
- const versionData = packageInfo.versions[latestVersion];
333
+ const latestVersion = (_b = pkg['dist-tags']) === null || _b === void 0 ? void 0 : _b.latest;
334
+ if (latestVersion && ((_c = pkg.versions) === null || _c === void 0 ? void 0 : _c[latestVersion])) {
335
+ const versionData = pkg.versions[latestVersion];
329
336
  const licenseResult = this.licenseChecker.checkLicense(versionData);
330
337
  if (!licenseResult.allowed) {
331
338
  this.logger.warn(`[filter_metadata] LICENSE BLOCKED: ${packageName} - ${licenseResult.reason}`);
332
339
  this.metrics.recordBlock(packageName, '*', licenseResult.reason || 'License not allowed');
333
- return Object.assign(Object.assign({}, packageInfo), { versions: {}, 'dist-tags': {}, security: {
340
+ return Object.assign(Object.assign({}, pkg), { versions: {}, 'dist-tags': {}, security: {
334
341
  blocked: true,
335
342
  reason: licenseResult.reason || 'License not allowed',
336
343
  license: licenseResult.license,
@@ -344,11 +351,11 @@ class SecurityFilterPlugin {
344
351
  }
345
352
  }
346
353
  if ((_d = this.config.packageAge) === null || _d === void 0 ? void 0 : _d.enabled) {
347
- const ageResult = this.packageAgeChecker.checkPackageAge(packageInfo);
354
+ const ageResult = this.packageAgeChecker.checkPackageAge(pkg);
348
355
  if (!ageResult.allowed && !ageResult.warnOnly) {
349
356
  this.logger.warn(`[filter_metadata] AGE BLOCKED: ${packageName} - ${ageResult.reason}`);
350
357
  this.metrics.recordBlock(packageName, '*', ageResult.reason || 'Package too new');
351
- return Object.assign(Object.assign({}, packageInfo), { versions: {}, 'dist-tags': {}, security: {
358
+ return Object.assign(Object.assign({}, pkg), { versions: {}, 'dist-tags': {}, security: {
352
359
  blocked: true,
353
360
  reason: ageResult.reason || 'Package too new',
354
361
  ageDays: ageResult.ageDays,
@@ -362,11 +369,38 @@ class SecurityFilterPlugin {
362
369
  else if (!ageResult.allowed && ageResult.warnOnly) {
363
370
  this.logger.warn(`[filter_metadata] AGE WARNING: ${packageName} - ${ageResult.reason} (warn-only mode)`);
364
371
  }
372
+ if (this.config.packageAge.minVersionAgeDays) {
373
+ const filteredVersions = Object.assign({}, pkg.versions);
374
+ const removedVersions = [];
375
+ for (const version of Object.keys(filteredVersions)) {
376
+ const versionAgeResult = this.packageAgeChecker.checkVersionAge(pkg, version);
377
+ if (!versionAgeResult.allowed && !versionAgeResult.warnOnly) {
378
+ this.logger.warn(`[filter_metadata] VERSION AGE FILTERED: ${packageName}@${version} - ${versionAgeResult.reason}`);
379
+ this.metrics.recordBlock(packageName, version, versionAgeResult.reason || 'Version too new');
380
+ delete filteredVersions[version];
381
+ removedVersions.push(version);
382
+ }
383
+ else if (!versionAgeResult.allowed && versionAgeResult.warnOnly) {
384
+ this.logger.warn(`[filter_metadata] VERSION AGE WARNING: ${packageName}@${version} - ${versionAgeResult.reason} (warn-only mode)`);
385
+ }
386
+ }
387
+ if (removedVersions.length > 0) {
388
+ this.logger.info(`[filter_metadata] Removed ${removedVersions.length} too-new version(s) from ${packageName}: ${removedVersions.join(', ')}`);
389
+ const filteredDistTags = Object.assign({}, pkg['dist-tags']);
390
+ for (const [tag, tagVersion] of Object.entries(filteredDistTags)) {
391
+ if (removedVersions.includes(tagVersion)) {
392
+ delete filteredDistTags[tag];
393
+ this.logger.debug(`[filter_metadata] Removed dist-tag "${tag}" pointing to filtered version ${tagVersion}`);
394
+ }
395
+ }
396
+ pkg = Object.assign(Object.assign({}, pkg), { versions: filteredVersions, 'dist-tags': filteredDistTags });
397
+ }
398
+ }
365
399
  }
366
400
  if ((_e = this.config.authorFilter) === null || _e === void 0 ? void 0 : _e.enabled) {
367
- const latestVersion = (_f = packageInfo['dist-tags']) === null || _f === void 0 ? void 0 : _f.latest;
368
- if (latestVersion && ((_g = packageInfo.versions) === null || _g === void 0 ? void 0 : _g[latestVersion])) {
369
- const versionData = packageInfo.versions[latestVersion];
401
+ const latestVersion = (_f = pkg['dist-tags']) === null || _f === void 0 ? void 0 : _f.latest;
402
+ if (latestVersion && ((_g = pkg.versions) === null || _g === void 0 ? void 0 : _g[latestVersion])) {
403
+ const versionData = pkg.versions[latestVersion];
370
404
  const authorResult = this.authorChecker.checkAuthor(versionData);
371
405
  if (!authorResult.allowed && !this.config.authorFilter.warnOnly) {
372
406
  this.logger.warn(`[filter_metadata] AUTHOR BLOCKED: ${packageName} - ${authorResult.reason}`);
@@ -381,7 +415,7 @@ class SecurityFilterPlugin {
381
415
  authorInfo: authorResult.authorInfo,
382
416
  },
383
417
  });
384
- return Object.assign(Object.assign({}, packageInfo), { versions: {}, 'dist-tags': {}, security: {
418
+ return Object.assign(Object.assign({}, pkg), { versions: {}, 'dist-tags': {}, security: {
385
419
  blocked: true,
386
420
  reason: authorResult.reason || 'Author not allowed',
387
421
  blockedBy: authorResult.blockedBy,
@@ -399,7 +433,7 @@ class SecurityFilterPlugin {
399
433
  }
400
434
  }
401
435
  this.logger.info(`[filter_metadata] [OK] ALLOWED: ${packageName}`);
402
- return packageInfo;
436
+ return pkg;
403
437
  }
404
438
  catch (error) {
405
439
  this.logger.error(`[filter_metadata] Error processing ${packageName}: ${error.message}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "verdaccio-security-filter",
3
- "version": "1.3.4",
3
+ "version": "1.3.6",
4
4
  "description": "Advanced security filter plugin for Verdaccio with version range blocking and fallback strategies",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -54,7 +54,8 @@
54
54
  "typescript-eslint": "^8.0.0"
55
55
  },
56
56
  "overrides": {
57
- "qs": "6.14.2"
57
+ "qs": "6.14.2",
58
+ "@cypress/request": "latest"
58
59
  },
59
60
  "author": {
60
61
  "name": "Vitaliy Ponomarenko",