confluence-cli 1.33.0 → 1.33.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.
- package/bin/index.js +1 -1
- package/lib/config.js +5 -3
- package/lib/confluence-client.js +45 -0
- package/npm-shrinkwrap.json +4 -5
- package/package.json +3 -4
package/bin/index.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
// Make sure we're using a supported Node.js version
|
|
14
14
|
const nodeVersion = process.version;
|
|
15
|
-
const requiredVersion = '
|
|
15
|
+
const requiredVersion = '18.0.0';
|
|
16
16
|
|
|
17
17
|
if (!nodeVersion.startsWith('v') ||
|
|
18
18
|
parseInt(nodeVersion.slice(1).split('.')[0]) < parseInt(requiredVersion.split('.')[0])) {
|
package/lib/config.js
CHANGED
|
@@ -235,7 +235,9 @@ function readConfigFile() {
|
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
return raw;
|
|
238
|
-
} catch {
|
|
238
|
+
} catch (error) {
|
|
239
|
+
console.error(chalk.yellow(`⚠ Failed to parse config file at ${CONFIG_FILE}: ${error.message}`));
|
|
240
|
+
console.error(chalk.yellow(' Run "confluence init" to recreate it.'));
|
|
239
241
|
return null;
|
|
240
242
|
}
|
|
241
243
|
}
|
|
@@ -259,7 +261,7 @@ const validateCliOptions = (options) => {
|
|
|
259
261
|
errors.push('--domain cannot be empty');
|
|
260
262
|
}
|
|
261
263
|
|
|
262
|
-
if (options.token !== undefined && !options.token.trim()) {
|
|
264
|
+
if (options.token !== undefined && (typeof options.token !== 'string' || !options.token.trim())) {
|
|
263
265
|
errors.push('--token cannot be empty');
|
|
264
266
|
}
|
|
265
267
|
|
|
@@ -304,7 +306,7 @@ const validateCliOptions = (options) => {
|
|
|
304
306
|
}
|
|
305
307
|
}
|
|
306
308
|
|
|
307
|
-
if (normAuthType === 'cookie' && options.cookie !== undefined && !options.cookie.trim()) {
|
|
309
|
+
if (normAuthType === 'cookie' && options.cookie !== undefined && (typeof options.cookie !== 'string' || !options.cookie.trim())) {
|
|
308
310
|
errors.push('--cookie cannot be empty when using cookie authentication');
|
|
309
311
|
}
|
|
310
312
|
|
package/lib/confluence-client.js
CHANGED
|
@@ -996,6 +996,12 @@ class ConfluenceClient {
|
|
|
996
996
|
throw new Error('Unable to determine download URL for attachment');
|
|
997
997
|
}
|
|
998
998
|
|
|
999
|
+
// Refuse to send credentials to an unexpected origin. The download URL is
|
|
1000
|
+
// derived from a server-supplied _links.download value, so a tampered or
|
|
1001
|
+
// misconfigured response could otherwise exfiltrate the bearer/basic token,
|
|
1002
|
+
// including via an http:// downgrade against an https-configured client.
|
|
1003
|
+
this.assertSameOrigin(downloadUrl);
|
|
1004
|
+
|
|
999
1005
|
// Download directly using axios with the same auth headers
|
|
1000
1006
|
const downloadRequestConfig = {
|
|
1001
1007
|
responseType: options.responseType || 'stream',
|
|
@@ -1780,6 +1786,45 @@ class ConfluenceClient {
|
|
|
1780
1786
|
return `${this.protocol}://${this.domain}${normalized}`;
|
|
1781
1787
|
}
|
|
1782
1788
|
|
|
1789
|
+
configuredOrigin() {
|
|
1790
|
+
if (!this.domain) {
|
|
1791
|
+
return null;
|
|
1792
|
+
}
|
|
1793
|
+
try {
|
|
1794
|
+
return new URL(`${this.protocol}://${this.domain}`).origin;
|
|
1795
|
+
} catch {
|
|
1796
|
+
return null;
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
isSameOriginAsConfigured(url) {
|
|
1801
|
+
const expected = this.configuredOrigin();
|
|
1802
|
+
if (!url || !expected) {
|
|
1803
|
+
return false;
|
|
1804
|
+
}
|
|
1805
|
+
try {
|
|
1806
|
+
return new URL(url).origin === expected;
|
|
1807
|
+
} catch {
|
|
1808
|
+
return false;
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
assertSameOrigin(url) {
|
|
1813
|
+
if (this.isSameOriginAsConfigured(url)) {
|
|
1814
|
+
return;
|
|
1815
|
+
}
|
|
1816
|
+
let actualOrigin;
|
|
1817
|
+
try {
|
|
1818
|
+
actualOrigin = new URL(url).origin;
|
|
1819
|
+
} catch {
|
|
1820
|
+
actualOrigin = String(url);
|
|
1821
|
+
}
|
|
1822
|
+
const expectedOrigin = this.configuredOrigin() ?? `${this.protocol}://${this.domain}`;
|
|
1823
|
+
throw new Error(
|
|
1824
|
+
`Refusing to send credentials to "${actualOrigin}": origin does not match the configured Confluence origin "${expectedOrigin}". This may indicate a tampered or misconfigured API response, or an http downgrade against an https-configured client.`
|
|
1825
|
+
);
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1783
1828
|
joinBaseUrl(baseUrl, path) {
|
|
1784
1829
|
if (!baseUrl) {
|
|
1785
1830
|
return null;
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "confluence-cli",
|
|
3
|
-
"version": "1.33.
|
|
3
|
+
"version": "1.33.2",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "confluence-cli",
|
|
9
|
-
"version": "1.33.
|
|
9
|
+
"version": "1.33.2",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"axios": "^1.15.0",
|
|
@@ -15,15 +15,14 @@
|
|
|
15
15
|
"form-data": "^4.0.5",
|
|
16
16
|
"html-to-text": "^9.0.5",
|
|
17
17
|
"inquirer": "^8.2.6",
|
|
18
|
-
"markdown-it": "^14.1.0"
|
|
19
|
-
"ora": "^5.4.1"
|
|
18
|
+
"markdown-it": "^14.1.0"
|
|
20
19
|
},
|
|
21
20
|
"bin": {
|
|
22
21
|
"confluence": "bin/index.js",
|
|
23
22
|
"confluence-cli": "bin/index.js"
|
|
24
23
|
},
|
|
25
24
|
"engines": {
|
|
26
|
-
"node": ">=
|
|
25
|
+
"node": ">=18.0.0"
|
|
27
26
|
}
|
|
28
27
|
},
|
|
29
28
|
"node_modules/@inquirer/external-editor": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "confluence-cli",
|
|
3
|
-
"version": "1.33.
|
|
3
|
+
"version": "1.33.2",
|
|
4
4
|
"description": "A command-line interface for Atlassian Confluence with page creation and editing capabilities",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -29,8 +29,7 @@
|
|
|
29
29
|
"form-data": "^4.0.5",
|
|
30
30
|
"html-to-text": "^9.0.5",
|
|
31
31
|
"inquirer": "^8.2.6",
|
|
32
|
-
"markdown-it": "^14.1.0"
|
|
33
|
-
"ora": "^5.4.1"
|
|
32
|
+
"markdown-it": "^14.1.0"
|
|
34
33
|
},
|
|
35
34
|
"devDependencies": {
|
|
36
35
|
"@types/node": "^20.10.0",
|
|
@@ -45,7 +44,7 @@
|
|
|
45
44
|
}
|
|
46
45
|
},
|
|
47
46
|
"engines": {
|
|
48
|
-
"node": ">=
|
|
47
|
+
"node": ">=18.0.0"
|
|
49
48
|
},
|
|
50
49
|
"repository": {
|
|
51
50
|
"type": "git",
|