@wppconnect/server-cli 1.3.61 → 1.3.63

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/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## [1.3.63](https://github.com/wppconnect-team/server-cli/compare/v1.3.62...v1.3.63) (2026-11-05)
2
+
3
+ ### Bug Fixes
4
+
5
+ - **deps:** bump @wppconnect/server to 2.10.75 for CVE-2026-121557 ([#887](https://github.com/wppconnect-team/server-cli/issues/887)) ([d021d0c](https://github.com/wppconnect-team/server-cli/commit/d021d0c258b7fc6d92b9bc1c2e5ba35c998c9afc))
6
+ - **deps:** keep nested legacy rimraf glob compatibility ([e3a5d55](https://github.com/wppconnect-team/server-cli/commit/e3a5d55103c7d9ccb3b74281bfa4f24ed2a460c1))
7
+
8
+ ## [1.3.62](https://github.com/wppconnect-team/server-cli/compare/v1.3.61...v1.3.62) (2026-11-02)
9
+
1
10
  ## [1.3.61](https://github.com/wppconnect-team/server-cli/compare/v1.3.60...v1.3.61) (2026-11-02)
2
11
 
3
12
  ## [1.3.60](https://github.com/wppconnect-team/server-cli/compare/v1.3.59...v1.3.60) (2026-11-01)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wppconnect/server-cli",
3
- "version": "1.3.61",
3
+ "version": "1.3.63",
4
4
  "description": "Servidor de WPPConnect com frontend para ser executado a partir de uma linha de comando",
5
5
  "repository": {
6
6
  "type": "git",
@@ -35,13 +35,13 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@babel/runtime": "^8.0.10",
38
- "@wppconnect/server": "2.10.68",
38
+ "@wppconnect/server": "2.10.75",
39
39
  "commander": "^14.0.3",
40
40
  "merge-deep": "^3.0.3",
41
41
  "prom-client": "^15.1.3"
42
42
  },
43
43
  "devDependencies": {
44
- "@aws-sdk/client-s3": "^3.1156.0",
44
+ "@aws-sdk/client-s3": "^3.1161.0",
45
45
  "@babel/cli": "^8.0.6",
46
46
  "@babel/core": "^8.0.10",
47
47
  "@babel/node": "^8.0.6",
@@ -96,18 +96,20 @@
96
96
  "**/package-json/got": "11.8.6",
97
97
  "**/sharp": "0.35.5",
98
98
  "@wppconnect-team/wppconnect/**/ws": "8.22.0",
99
- "@types/minimatch/**/minimatch": "10.2.5",
100
- "**/archiver-utils/**/minimatch": "9.0.9",
101
- "nodemon/**/minimatch": "10.2.5",
99
+ "@types/minimatch/**/minimatch": "11.0.4",
100
+ "**/archiver-utils/**/minimatch": "11.0.4",
101
+ "**/archiver-utils/**/glob": "14.0.2",
102
+ "nodemon/**/minimatch": "11.0.4",
102
103
  "pretty-quick/**/picomatch": "3.0.2",
103
- "readdir-glob/**/minimatch": "5.1.9",
104
- "**/rimraf/**/minimatch": "9.0.9",
104
+ "**/readdir-glob/**/minimatch": "11.0.4",
105
+ "rimraf/**/minimatch": "11.0.4",
106
+ "rimraf/glob": "14.0.2",
105
107
  "**/nodemon/**/brace-expansion": "5.0.12",
106
108
  "**/readdir-glob/**/brace-expansion": "2.1.7",
107
109
  "puppeteer": "25.13.0",
108
110
  "http-cache-semantics": "4.3.0",
109
111
  "browserslist": "4.28.9",
110
- "baseline-browser-mapping": "2.11.34",
112
+ "baseline-browser-mapping": "2.11.35",
111
113
  "**/lodash": "4.18.1",
112
114
  "tar": "7.5.22",
113
115
  "tmp": "0.2.7",
@@ -21,10 +21,12 @@ const os = require('node:os');
21
21
  const path = require('node:path');
22
22
  const { test } = require('node:test');
23
23
 
24
+ const normalizePaths = (values) => values.map((value) => value.split(path.sep).join('/')).sort();
25
+
24
26
  test('rimraf ESM executable loads brace expansion and removes its target', () => {
25
27
  const owner = createRequire(require.resolve('rimraf'));
26
28
  const globOwner = createRequire(owner.resolve('glob'));
27
- assert.equal(globOwner('minimatch/package.json').version, '9.0.9');
29
+ assert.equal(globOwner('minimatch/package.json').version, '11.0.4');
28
30
  const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'wppcli-rimraf-'));
29
31
  try {
30
32
  const target = path.join(directory, 'output');
@@ -43,7 +45,7 @@ test('rimraf ESM executable loads brace expansion and removes its target', () =>
43
45
  test('archiver glob expands braces and exclusions through its own minimatch', () => {
44
46
  const owner = createRequire(require.resolve('archiver-utils'));
45
47
  const globOwner = createRequire(owner.resolve('glob'));
46
- assert.equal(globOwner('minimatch/package.json').version, '9.0.9');
48
+ assert.equal(globOwner('minimatch/package.json').version, '11.0.4');
47
49
  const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'wppcli-glob-'));
48
50
  try {
49
51
  for (const name of ['first.txt', 'second.txt', 'ignored.txt']) {
@@ -60,10 +62,24 @@ test('archiver glob expands braces and exclusions through its own minimatch', ()
60
62
  });
61
63
 
62
64
  test('legacy glob retains its callable minimatch and brace expansion APIs', () => {
63
- const owner = createRequire(require.resolve('glob'));
65
+ const licenseOwner = createRequire(require.resolve('license-check-and-add/package.json'));
66
+ const globbyOwner = createRequire(licenseOwner.resolve('globby'));
67
+ const owner = createRequire(globbyOwner.resolve('glob'));
64
68
  const minimatch = owner('minimatch');
65
69
  assert.equal(minimatch('first.txt', '{first,second}.txt'), true);
66
70
  assert.equal(minimatch('third.txt', '{first,second}.txt'), false);
71
+ const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'wppcli-legacy-glob-'));
72
+ try {
73
+ fs.mkdirSync(path.join(directory, 'nested'));
74
+ fs.writeFileSync(path.join(directory, 'nested', 'fixture.txt'), 'fixture');
75
+ const globby = licenseOwner('globby');
76
+ assert.deepEqual(normalizePaths(globby.sync(['**/*.txt'], { cwd: directory })), ['nested/fixture.txt']);
77
+ } finally {
78
+ const resolved = fs.realpathSync(directory);
79
+ assert.equal(path.dirname(resolved), fs.realpathSync(os.tmpdir()));
80
+ assert.ok(path.basename(resolved).startsWith('wppcli-legacy-glob-'));
81
+ fs.rmSync(resolved, { recursive: true, force: true, maxRetries: 3 });
82
+ }
67
83
  });
68
84
 
69
85
  test('nodemon retains its named minimatch API for watched file patterns', () => {
@@ -72,3 +88,123 @@ test('nodemon retains its named minimatch API for watched file patterns', () =>
72
88
  assert.equal(minimatch('src/index.js', 'src/{index,config}.js'), true);
73
89
  assert.equal(minimatch('src/ignored.js', 'src/{index,config}.js'), false);
74
90
  });
91
+
92
+ test('actual Archiver ZIP traversal keeps brace, dotfile and exclusion semantics', async () => {
93
+ const archiver = require('archiver');
94
+ const unzipper = require('unzipper');
95
+ const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'wppcli-archive-'));
96
+ try {
97
+ fs.mkdirSync(path.join(directory, 'nested'));
98
+ for (const name of ['a.txt', 'b.bin', 'ignore.txt', '.hidden.txt'])
99
+ fs.writeFileSync(path.join(directory, 'nested', name), 'fixture');
100
+ const archiveOwner = createRequire(require.resolve('archiver'));
101
+ const traversalOwner = createRequire(archiveOwner.resolve('readdir-glob'));
102
+ assert.equal(traversalOwner('minimatch/package.json').version, '11.0.4');
103
+ const zip = archiver('zip');
104
+ const chunks = [];
105
+ const ended = new Promise((resolve, reject) => {
106
+ zip.on('data', (chunk) => chunks.push(chunk));
107
+ zip.once('end', resolve);
108
+ zip.once('error', reject);
109
+ });
110
+ zip.glob('**/*.{txt,bin}', { cwd: directory, dot: true, ignore: '**/ignore.txt' });
111
+ await zip.finalize();
112
+ await ended;
113
+ const result = await unzipper.Open.buffer(Buffer.concat(chunks));
114
+ assert.deepEqual(result.files.map((file) => file.path).sort(), [
115
+ 'nested/.hidden.txt',
116
+ 'nested/a.txt',
117
+ 'nested/b.bin',
118
+ ]);
119
+ } finally {
120
+ const resolved = fs.realpathSync(directory);
121
+ assert.equal(path.dirname(resolved), fs.realpathSync(os.tmpdir()));
122
+ assert.ok(path.basename(resolved).startsWith('wppcli-archive-'));
123
+ fs.rmSync(resolved, { recursive: true, force: true, maxRetries: 3 });
124
+ }
125
+ });
126
+
127
+ test('the actual modern matching engine bounds first-phase pattern amplification', () => {
128
+ const owner = createRequire(require.resolve('archiver-utils'));
129
+ const globOwner = createRequire(owner.resolve('glob'));
130
+ const modulePath = globOwner.resolve('minimatch');
131
+ const code = `
132
+ const assert = require('node:assert/strict');
133
+ const { Minimatch } = require(${JSON.stringify(modulePath)});
134
+ let peak = 0;
135
+ class Probe extends Minimatch {
136
+ firstPhasePreProcess(parts) {
137
+ const result = super.firstPhasePreProcess(parts);
138
+ peak = result.length;
139
+ return result;
140
+ }
141
+ }
142
+ new Probe(Array.from({length:12}, (_, i) => 'p'+i+'/**/../q'+i).join('/'),
143
+ { optimizationLevel: 2, braceExpandMax: 64 });
144
+ assert(peak > 1 && peak <= 64, 'pattern budget exceeded: '+peak);
145
+ `;
146
+ execFileSync(process.execPath, ['--max-old-space-size=192', '-e', code], {
147
+ encoding: 'utf8',
148
+ timeout: 3000,
149
+ });
150
+ });
151
+
152
+ test('modern glob owners traverse recursive wildcards with their installed matcher', () => {
153
+ const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'wppcli-owner-globs-'));
154
+ try {
155
+ fs.mkdirSync(path.join(directory, 'nested'));
156
+ for (const name of ['a.txt', 'b.bin', 'ignore.txt', '.hidden.txt']) {
157
+ fs.writeFileSync(path.join(directory, 'nested', name), 'fixture');
158
+ }
159
+ for (const name of ['archiver-utils', 'rimraf']) {
160
+ const owner = createRequire(require.resolve(name));
161
+ const glob = owner('glob');
162
+ assert.deepEqual(
163
+ normalizePaths(glob.sync('**/*.txt', { cwd: directory })),
164
+ ['nested/a.txt', 'nested/ignore.txt'],
165
+ name
166
+ );
167
+ assert.deepEqual(
168
+ normalizePaths(glob.sync('**/*.{txt,bin}', { cwd: directory, dot: true, ignore: '**/ignore.txt' })),
169
+ ['nested/.hidden.txt', 'nested/a.txt', 'nested/b.bin'],
170
+ name
171
+ );
172
+ }
173
+ assert.deepEqual(normalizePaths(require('archiver-utils/file').expand({ cwd: directory }, ['**/*.txt'])), [
174
+ 'nested/a.txt',
175
+ 'nested/ignore.txt',
176
+ ]);
177
+ const manifest = require.resolve('rimraf/package.json');
178
+ const executable = path.resolve(path.dirname(manifest), require(manifest).bin);
179
+ execFileSync(process.execPath, [executable, '--glob', 'nested/*.bin'], { cwd: directory, encoding: 'utf8' });
180
+ assert.equal(fs.existsSync(path.join(directory, 'nested', 'b.bin')), false);
181
+ assert.equal(fs.existsSync(path.join(directory, 'nested', 'a.txt')), true);
182
+ } finally {
183
+ const resolved = fs.realpathSync(directory);
184
+ assert.equal(path.dirname(resolved), fs.realpathSync(os.tmpdir()));
185
+ assert.ok(path.basename(resolved).startsWith('wppcli-owner-globs-'));
186
+ fs.rmSync(resolved, { recursive: true, force: true, maxRetries: 3 });
187
+ }
188
+ });
189
+
190
+ test('nested legacy rimraf preserves callback and wildcard deletion contracts', async () => {
191
+ const plugin = createRequire(require.resolve('puppeteer-extra-plugin-user-data-dir'));
192
+ const owner = createRequire(plugin.resolve('rimraf'));
193
+ const rimraf = plugin('rimraf');
194
+ assert.equal(typeof rimraf, 'function');
195
+ assert.equal(typeof owner('glob'), 'function');
196
+ const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'wppcli-legacy-rimraf-'));
197
+ try {
198
+ fs.writeFileSync(path.join(directory, 'remove.txt'), 'fixture');
199
+ fs.writeFileSync(path.join(directory, 'keep.bin'), 'fixture');
200
+ const pattern = directory.split(path.sep).join('/') + '/*.txt';
201
+ await new Promise((resolve, reject) => rimraf(pattern, (error) => (error ? reject(error) : resolve())));
202
+ assert.equal(fs.existsSync(path.join(directory, 'remove.txt')), false);
203
+ assert.equal(fs.existsSync(path.join(directory, 'keep.bin')), true);
204
+ } finally {
205
+ const resolved = fs.realpathSync(directory);
206
+ assert.equal(path.dirname(resolved), fs.realpathSync(os.tmpdir()));
207
+ assert.ok(path.basename(resolved).startsWith('wppcli-legacy-rimraf-'));
208
+ fs.rmSync(resolved, { recursive: true, force: true, maxRetries: 3 });
209
+ }
210
+ });
@@ -14,6 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  const assert = require('node:assert/strict');
17
+ const fs = require('node:fs');
17
18
  const path = require('node:path');
18
19
  const { createRequire } = require('node:module');
19
20
 
@@ -25,8 +26,19 @@ const server = createRequire(project.resolve('@wppconnect/server'));
25
26
  const core = createRequire(server.resolve('@wppconnect-team/wppconnect'));
26
27
  const extra = createRequire(core.resolve('puppeteer-extra'));
27
28
  const merge = extra('deepmerge');
28
- const privateRuntime = path.join(root, 'vendor', 'deepmerge', 'index.cjs');
29
- assert.equal(merge, project(privateRuntime));
29
+ const cliRuntime = path.join(root, 'vendor', 'deepmerge', 'index.cjs');
30
+ let privateRuntime = cliRuntime;
31
+ if (merge !== project(cliRuntime)) {
32
+ // The server also protects registry installs. Its later hook can supply its
33
+ // own copy, but accept it only when both reviewed runtime files are identical.
34
+ const serverRoot = path.dirname(project.resolve('@wppconnect/server/package.json'));
35
+ privateRuntime = path.join(serverRoot, 'vendor', 'deepmerge', 'index.cjs');
36
+ for (const file of ['index.cjs', 'is-mergeable-object.cjs']) {
37
+ const source = (runtime) => fs.readFileSync(path.join(path.dirname(runtime), file), 'utf8').replace(/\r\n/g, '\n');
38
+ assert.equal(source(privateRuntime), source(cliRuntime), `Unreviewed server merger runtime: ${file}`);
39
+ }
40
+ assert.equal(merge, server(privateRuntime));
41
+ }
30
42
  const payload = JSON.parse('{"__proto__":{"isAdmin":true}}');
31
43
  for (const result of [
32
44
  merge(Object.create(null), payload),
@@ -38,11 +50,14 @@ for (const result of [
38
50
  }
39
51
  assert.deepEqual(merge.all([{ args: ['a'] }, { args: ['b'] }]), { args: ['a', 'b'] });
40
52
  assert.equal({}.isAdmin, undefined);
41
- console.log(
53
+ // The imported server owns background timers; finish after these synchronous
54
+ // assertions and flush the result before terminating this fixture process.
55
+ process.stdout.write(
42
56
  JSON.stringify({
43
57
  publicEntryLoaded: true,
44
58
  privateRuntime,
45
59
  dependencyMetadataVersion: extra('deepmerge/package.json').version,
46
60
  prototypeCasesPassed: 3,
47
- })
61
+ }) + '\n',
62
+ () => process.exit(0)
48
63
  );
@@ -18,6 +18,7 @@ const assert = require('node:assert/strict');
18
18
  const fs = require('node:fs');
19
19
  const os = require('node:os');
20
20
  const path = require('node:path');
21
+ const { createRequire } = require('node:module');
21
22
  const { spawnSync } = require('node:child_process');
22
23
 
23
24
  const root = path.resolve(__dirname, '..');
@@ -66,6 +67,27 @@ try {
66
67
  '@wppconnect/server-cli'
67
68
  );
68
69
  process.stdout.write(run([helper, installed], prefix));
70
+ // A separate server-owned copy is accepted only while its source matches
71
+ // the reviewed CLI backport. Do not let this exception trust arbitrary code.
72
+ const consumer = createRequire(path.join(installed, 'package.json'));
73
+ const serverRoot = path.dirname(consumer.resolve('@wppconnect/server/package.json'));
74
+ for (const file of ['index.cjs', 'is-mergeable-object.cjs']) {
75
+ const runtime = path.join(serverRoot, 'vendor', 'deepmerge', file);
76
+ const original = fs.readFileSync(runtime);
77
+ try {
78
+ fs.appendFileSync(runtime, '\n// Unreviewed fixture change.\n');
79
+ const rejected = spawnSync(process.execPath, [helper, installed], {
80
+ cwd: prefix,
81
+ env,
82
+ encoding: 'utf8',
83
+ timeout: 30000,
84
+ });
85
+ assert.notEqual(rejected.status, 0);
86
+ assert.match(rejected.stderr, /Unreviewed server merger runtime:/);
87
+ } finally {
88
+ fs.writeFileSync(runtime, original);
89
+ }
90
+ }
69
91
  const help = run([path.join(installed, 'bin', 'wppserver.js'), '--help'], prefix);
70
92
  assert.match(help, /Usage:/);
71
93
  }