verdaccio-security-filter 1.3.0 → 1.3.2

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.
@@ -36,34 +36,29 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.MetricsCollector = void 0;
37
37
  const fs = __importStar(require("fs"));
38
38
  const path = __importStar(require("path"));
39
- /**
40
- * Metrics collector for tracking security events
41
- */
42
39
  class MetricsCollector {
43
40
  constructor(config) {
44
41
  this.metricsBuffer = [];
45
42
  this.bufferSize = 100;
43
+ this.maxBufferSize = 500;
46
44
  this.config = {
47
45
  enabled: (config === null || config === void 0 ? void 0 : config.enabled) || false,
48
46
  output: (config === null || config === void 0 ? void 0 : config.output) || 'stdout',
49
47
  filePath: (config === null || config === void 0 ? void 0 : config.filePath) || './security-metrics.json',
50
48
  };
51
49
  }
52
- /**
53
- * Record a security event
54
- */
55
50
  record(event) {
56
51
  if (!this.config.enabled) {
57
52
  return;
58
53
  }
54
+ if (this.metricsBuffer.length >= this.maxBufferSize) {
55
+ this.flush();
56
+ }
59
57
  this.metricsBuffer.push(event);
60
58
  if (this.metricsBuffer.length >= this.bufferSize) {
61
59
  this.flush();
62
60
  }
63
61
  }
64
- /**
65
- * Record a block event
66
- */
67
62
  recordBlock(packageName, version, reason, metadata) {
68
63
  this.record({
69
64
  timestamp: new Date().toISOString(),
@@ -74,9 +69,6 @@ class MetricsCollector {
74
69
  metadata,
75
70
  });
76
71
  }
77
- /**
78
- * Record a fallback event
79
- */
80
72
  recordFallback(packageName, fromVersion, toVersion, reason) {
81
73
  this.record({
82
74
  timestamp: new Date().toISOString(),
@@ -87,9 +79,6 @@ class MetricsCollector {
87
79
  metadata: { toVersion },
88
80
  });
89
81
  }
90
- /**
91
- * Record a publish rejection
92
- */
93
82
  recordPublishRejected(packageName, version, reason) {
94
83
  this.record({
95
84
  timestamp: new Date().toISOString(),
@@ -99,9 +88,6 @@ class MetricsCollector {
99
88
  reason,
100
89
  });
101
90
  }
102
- /**
103
- * Record a CVE detection
104
- */
105
91
  recordCVE(packageName, version, cveId, severity) {
106
92
  this.record({
107
93
  timestamp: new Date().toISOString(),
@@ -112,9 +98,6 @@ class MetricsCollector {
112
98
  metadata: { cveId, severity },
113
99
  });
114
100
  }
115
- /**
116
- * Record a license block
117
- */
118
101
  recordLicenseBlock(packageName, version, license, reason) {
119
102
  this.record({
120
103
  timestamp: new Date().toISOString(),
@@ -125,9 +108,6 @@ class MetricsCollector {
125
108
  metadata: { license },
126
109
  });
127
110
  }
128
- /**
129
- * Record a package-too-new event
130
- */
131
111
  recordPackageTooNew(packageName, version, reason, metadata) {
132
112
  this.record({
133
113
  timestamp: new Date().toISOString(),
@@ -138,9 +118,6 @@ class MetricsCollector {
138
118
  metadata,
139
119
  });
140
120
  }
141
- /**
142
- * Flush metrics buffer to output
143
- */
144
121
  flush() {
145
122
  if (this.metricsBuffer.length === 0) {
146
123
  return;
@@ -155,18 +132,13 @@ class MetricsCollector {
155
132
  }
156
133
  this.metricsBuffer = [];
157
134
  }
158
- /**
159
- * Write metrics to file
160
- */
161
135
  writeToFile(metrics) {
162
136
  try {
163
137
  const filePath = this.config.filePath;
164
138
  const dir = path.dirname(filePath);
165
- // Ensure directory exists
166
139
  if (!fs.existsSync(dir)) {
167
140
  fs.mkdirSync(dir, { recursive: true });
168
141
  }
169
- // Append to file
170
142
  const content = metrics.map(m => JSON.stringify(m)).join('\n') + '\n';
171
143
  fs.appendFileSync(filePath, content, 'utf8');
172
144
  }
@@ -175,9 +147,6 @@ class MetricsCollector {
175
147
  console.error('[Security Filter] Failed to write metrics:', message);
176
148
  }
177
149
  }
178
- /**
179
- * Get metrics summary
180
- */
181
150
  getSummary() {
182
151
  const summary = {
183
152
  block: 0,
@@ -193,9 +162,6 @@ class MetricsCollector {
193
162
  });
194
163
  return summary;
195
164
  }
196
- /**
197
- * Cleanup - flush remaining metrics
198
- */
199
165
  cleanup() {
200
166
  this.flush();
201
167
  }
@@ -1,45 +1,23 @@
1
1
  import { PackageAgeConfig } from '../types';
2
2
  import { Package } from '@verdaccio/types';
3
- /**
4
- * Package age checker to protect against newly created malicious packages
5
- */
6
3
  export declare class PackageAgeChecker {
7
4
  private config;
8
5
  constructor(config?: PackageAgeConfig);
9
- /**
10
- * Check if a package is old enough to be trusted
11
- */
12
6
  checkPackageAge(packageData: Package): {
13
7
  allowed: boolean;
14
8
  reason?: string;
15
9
  ageDays?: number;
16
10
  warnOnly?: boolean;
17
11
  };
18
- /**
19
- * Check if a specific version is old enough to be trusted
20
- */
21
12
  checkVersionAge(packageData: Package, version: string): {
22
13
  allowed: boolean;
23
14
  reason?: string;
24
15
  ageDays?: number;
25
16
  warnOnly?: boolean;
26
17
  };
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
18
  private getPackageCreationDate;
32
- /**
33
- * Get version publish date from time field
34
- */
35
19
  private getVersionPublishDate;
36
- /**
37
- * Calculate age in days from a date
38
- */
39
20
  private calculateAgeDays;
40
- /**
41
- * Get summary of configuration
42
- */
43
21
  getSummary(): {
44
22
  enabled: boolean;
45
23
  minPackageAgeDays: number;
@@ -1,9 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PackageAgeChecker = void 0;
4
- /**
5
- * Package age checker to protect against newly created malicious packages
6
- */
7
4
  class PackageAgeChecker {
8
5
  constructor(config) {
9
6
  var _a, _b, _c;
@@ -14,17 +11,12 @@ class PackageAgeChecker {
14
11
  warnOnly: (_c = config === null || config === void 0 ? void 0 : config.warnOnly) !== null && _c !== void 0 ? _c : false,
15
12
  };
16
13
  }
17
- /**
18
- * Check if a package is old enough to be trusted
19
- */
20
14
  checkPackageAge(packageData) {
21
15
  if (!this.config.enabled) {
22
16
  return { allowed: true };
23
17
  }
24
- // Get package creation date from time field
25
18
  const createdDate = this.getPackageCreationDate(packageData);
26
19
  if (!createdDate) {
27
- // If we can't determine creation date, allow but warn
28
20
  return {
29
21
  allowed: true,
30
22
  reason: 'Cannot determine package creation date',
@@ -42,17 +34,12 @@ class PackageAgeChecker {
42
34
  }
43
35
  return { allowed: true, ageDays };
44
36
  }
45
- /**
46
- * Check if a specific version is old enough to be trusted
47
- */
48
37
  checkVersionAge(packageData, version) {
49
38
  if (!this.config.enabled || !this.config.minVersionAgeDays) {
50
39
  return { allowed: true };
51
40
  }
52
- // Get version publish date from time field
53
41
  const versionDate = this.getVersionPublishDate(packageData, version);
54
42
  if (!versionDate) {
55
- // If we can't determine version date, allow but warn
56
43
  return {
57
44
  allowed: true,
58
45
  reason: `Cannot determine version ${version} publish date`,
@@ -70,22 +57,16 @@ class PackageAgeChecker {
70
57
  }
71
58
  return { allowed: true, ageDays };
72
59
  }
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
60
  getPackageCreationDate(packageData) {
78
61
  if (!packageData.time) {
79
62
  return null;
80
63
  }
81
- // Try to get 'created' field first
82
64
  if ('created' in packageData.time) {
83
65
  const created = packageData.time.created;
84
66
  if (typeof created === 'string') {
85
67
  return new Date(created);
86
68
  }
87
69
  }
88
- // Fallback: find the oldest version
89
70
  const versions = Object.keys(packageData.time).filter(key => key !== 'modified' && key !== 'created');
90
71
  if (versions.length === 0) {
91
72
  return null;
@@ -99,12 +80,8 @@ class PackageAgeChecker {
99
80
  if (dates.length === 0) {
100
81
  return null;
101
82
  }
102
- // Return the oldest date
103
83
  return new Date(Math.min(...dates.map(d => d.getTime())));
104
84
  }
105
- /**
106
- * Get version publish date from time field
107
- */
108
85
  getVersionPublishDate(packageData, version) {
109
86
  if (!packageData.time || !(version in packageData.time)) {
110
87
  return null;
@@ -115,17 +92,11 @@ class PackageAgeChecker {
115
92
  }
116
93
  return null;
117
94
  }
118
- /**
119
- * Calculate age in days from a date
120
- */
121
95
  calculateAgeDays(date) {
122
96
  const now = new Date();
123
97
  const diffMs = now.getTime() - date.getTime();
124
98
  return Math.floor(diffMs / (1000 * 60 * 60 * 24));
125
99
  }
126
- /**
127
- * Get summary of configuration
128
- */
129
100
  getSummary() {
130
101
  return {
131
102
  enabled: this.config.enabled,
@@ -1,45 +1,19 @@
1
1
  import { WhitelistConfig } from '../types';
2
- /**
3
- * Whitelist checker for package validation
4
- */
5
2
  export declare class WhitelistChecker {
6
3
  private config;
7
4
  constructor(config?: WhitelistConfig);
8
- /**
9
- * Check if a package is whitelisted
10
- */
11
5
  isWhitelisted(packageName: string, version?: string): {
12
6
  allowed: boolean;
13
7
  reason?: string;
14
8
  };
15
- /**
16
- * Check if package name matches any whitelist pattern
17
- */
18
9
  private matchesPattern;
19
- /**
20
- * Add package to whitelist
21
- */
22
10
  addPackage(packageName: string, versionRange?: string): void;
23
- /**
24
- * Remove package from whitelist
25
- */
26
11
  removePackage(packageName: string): void;
27
- /**
28
- * Add pattern to whitelist
29
- */
30
12
  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
13
  meetsAutoApproveCriteria(_packageName: string): Promise<{
37
14
  approved: boolean;
38
15
  reason?: string;
39
16
  }>;
40
- /**
41
- * Get whitelist summary
42
- */
43
17
  getSummary(): {
44
18
  totalPackages: number;
45
19
  totalPatterns: number;
@@ -44,9 +44,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
44
44
  Object.defineProperty(exports, "__esModule", { value: true });
45
45
  exports.WhitelistChecker = void 0;
46
46
  const semver = __importStar(require("semver"));
47
- /**
48
- * Whitelist checker for package validation
49
- */
50
47
  class WhitelistChecker {
51
48
  constructor(config) {
52
49
  this.config = {
@@ -56,13 +53,8 @@ class WhitelistChecker {
56
53
  autoApprove: config === null || config === void 0 ? void 0 : config.autoApprove,
57
54
  };
58
55
  }
59
- /**
60
- * Check if a package is whitelisted
61
- */
62
56
  isWhitelisted(packageName, version) {
63
- // Check exact package name match
64
57
  if (this.config.packages.includes(packageName)) {
65
- // If version is specified, check version constraint
66
58
  if (version && this.config.versions && packageName in this.config.versions) {
67
59
  const versionRange = this.config.versions[packageName];
68
60
  if (!semver.satisfies(version, versionRange)) {
@@ -74,19 +66,14 @@ class WhitelistChecker {
74
66
  }
75
67
  return { allowed: true };
76
68
  }
77
- // Check pattern match
78
69
  if (this.matchesPattern(packageName)) {
79
70
  return { allowed: true };
80
71
  }
81
- // Not in whitelist
82
72
  return {
83
73
  allowed: false,
84
74
  reason: 'Package is not in whitelist',
85
75
  };
86
76
  }
87
- /**
88
- * Check if package name matches any whitelist pattern
89
- */
90
77
  matchesPattern(packageName) {
91
78
  return this.config.patterns.some(pattern => {
92
79
  try {
@@ -99,9 +86,6 @@ class WhitelistChecker {
99
86
  }
100
87
  });
101
88
  }
102
- /**
103
- * Add package to whitelist
104
- */
105
89
  addPackage(packageName, versionRange) {
106
90
  if (!this.config.packages.includes(packageName)) {
107
91
  this.config.packages.push(packageName);
@@ -111,9 +95,6 @@ class WhitelistChecker {
111
95
  this.config.versions[packageName] = versionRange;
112
96
  }
113
97
  }
114
- /**
115
- * Remove package from whitelist
116
- */
117
98
  removePackage(packageName) {
118
99
  const index = this.config.packages.indexOf(packageName);
119
100
  if (index > -1) {
@@ -123,40 +104,22 @@ class WhitelistChecker {
123
104
  delete this.config.versions[packageName];
124
105
  }
125
106
  }
126
- /**
127
- * Add pattern to whitelist
128
- */
129
107
  addPattern(pattern) {
130
108
  if (!this.config.patterns.includes(pattern)) {
131
109
  this.config.patterns.push(pattern);
132
110
  }
133
111
  }
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
112
  meetsAutoApproveCriteria(_packageName) {
141
113
  return __awaiter(this, void 0, void 0, function* () {
142
114
  if (!this.config.autoApprove) {
143
115
  return { approved: false, reason: 'Auto-approve not configured' };
144
116
  }
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
117
  return {
152
118
  approved: false,
153
119
  reason: 'Auto-approve requires npm registry API integration (not implemented)',
154
120
  };
155
121
  });
156
122
  }
157
- /**
158
- * Get whitelist summary
159
- */
160
123
  getSummary() {
161
124
  return {
162
125
  totalPackages: this.config.packages.length,
package/build/types.d.ts CHANGED
@@ -90,11 +90,8 @@ export interface SecurityRules {
90
90
  versionRangeRules: VersionRangeRule[];
91
91
  }
92
92
  export interface VersionData extends Version {
93
- /** Internal flag for fallback versions */
94
93
  _fallback?: boolean;
95
- /** Original version this is falling back from */
96
94
  _fallbackFrom?: string;
97
- /** Reason for fallback */
98
95
  _fallbackReason?: string;
99
96
  }
100
97
  export interface FilterResult {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "verdaccio-security-filter",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
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",
@@ -67,7 +67,9 @@
67
67
  },
68
68
  "homepage": "https://github.com/ponomarenko/verdaccio-security-filter#readme",
69
69
  "files": [
70
- "build/",
71
- "README.md"
70
+ "build/**/*.js",
71
+ "build/**/*.d.ts",
72
+ "README.md",
73
+ "LICENSE"
72
74
  ]
73
75
  }