@redocly/cli 0.0.0-snapshot.1782483365 → 0.0.0-snapshot.1782825774
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.
|
@@ -34,6 +34,33 @@ describe('#split', () => {
|
|
|
34
34
|
and all related files are saved to the directory: ${(0, colorette_1.blue)(openapiDir)} \n`);
|
|
35
35
|
expect(process.stderr.write.mock.calls[1][0]).toContain(`${filePath}: split processed in <test>ms`);
|
|
36
36
|
});
|
|
37
|
+
it('aborts instead of writing a component file outside the output directory', async () => {
|
|
38
|
+
const filePath = 'packages/cli/src/commands/split/__tests__/fixtures/path-traversal.json';
|
|
39
|
+
jest.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
40
|
+
await expect((0, index_1.handleSplit)({
|
|
41
|
+
argv: {
|
|
42
|
+
api: filePath,
|
|
43
|
+
outDir: openapiDir,
|
|
44
|
+
separator: '_',
|
|
45
|
+
},
|
|
46
|
+
config: (0, miscellaneous_1.loadConfigAndHandleErrors)(),
|
|
47
|
+
version: 'cli-version',
|
|
48
|
+
})).rejects.toThrow(utils.HandledError);
|
|
49
|
+
expect(utils.writeToFileByExtension).not.toHaveBeenCalled();
|
|
50
|
+
});
|
|
51
|
+
it('aborts instead of writing a path file outside the output directory', async () => {
|
|
52
|
+
const filePath = 'packages/cli/src/commands/split/__tests__/fixtures/path-traversal-paths.json';
|
|
53
|
+
jest.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
54
|
+
await expect((0, index_1.handleSplit)({
|
|
55
|
+
argv: {
|
|
56
|
+
api: filePath,
|
|
57
|
+
outDir: openapiDir,
|
|
58
|
+
separator: '/',
|
|
59
|
+
},
|
|
60
|
+
config: (0, miscellaneous_1.loadConfigAndHandleErrors)(),
|
|
61
|
+
version: 'cli-version',
|
|
62
|
+
})).rejects.toThrow(utils.HandledError);
|
|
63
|
+
});
|
|
37
64
|
it('should use the correct separator', async () => {
|
|
38
65
|
const filePath = 'packages/cli/src/commands/split/__tests__/fixtures/spec.json';
|
|
39
66
|
jest.spyOn(utils, 'pathToFilename').mockImplementation(() => 'newFilePath');
|
|
@@ -172,6 +172,13 @@ function extractFileNameFromPath(filename) {
|
|
|
172
172
|
function getFileNamePath(componentDirPath, componentName, ext) {
|
|
173
173
|
return path.join(componentDirPath, componentName) + `.${ext}`;
|
|
174
174
|
}
|
|
175
|
+
function assertWithinDir(baseDir, targetPath, subject) {
|
|
176
|
+
const base = path.resolve(baseDir);
|
|
177
|
+
const target = path.resolve(targetPath);
|
|
178
|
+
if (target !== base && !target.startsWith(base + path.sep)) {
|
|
179
|
+
(0, miscellaneous_1.exitWithError)(`Refusing to write "${subject}" outside the output directory.`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
175
182
|
function gatherComponentsFiles(components, componentsFiles, componentType, componentName, filename) {
|
|
176
183
|
let inherits = [];
|
|
177
184
|
if (componentType === types_1.OPENAPI3_COMPONENT.Schemas) {
|
|
@@ -191,6 +198,7 @@ function iteratePathItems(pathItems, openapiDir, outDir, componentsFiles, pathSe
|
|
|
191
198
|
const pathData = pathItems[pathName];
|
|
192
199
|
if ((0, openapi_core_1.isRef)(pathData))
|
|
193
200
|
continue;
|
|
201
|
+
assertWithinDir(openapiDir, pathFile, pathName);
|
|
194
202
|
for (const method of types_1.OPENAPI3_METHOD_NAMES) {
|
|
195
203
|
const methodData = pathData[method];
|
|
196
204
|
const methodDataXCode = methodData?.['x-code-samples'] || methodData?.['x-codeSamples'];
|
|
@@ -201,6 +209,7 @@ function iteratePathItems(pathItems, openapiDir, outDir, componentsFiles, pathSe
|
|
|
201
209
|
if (sample.source && sample.source.$ref)
|
|
202
210
|
continue;
|
|
203
211
|
const sampleFileName = path.join(openapiDir, 'code_samples', (0, miscellaneous_1.escapeLanguageName)(sample.lang), codeSamplesPathPrefix + (0, miscellaneous_1.pathToFilename)(pathName, pathSeparator), method + (0, miscellaneous_1.langToExt)(sample.lang));
|
|
212
|
+
assertWithinDir(openapiDir, sampleFileName, sample.lang);
|
|
204
213
|
fs.mkdirSync(path.dirname(sampleFileName), { recursive: true });
|
|
205
214
|
fs.writeFileSync(sampleFileName, sample.source);
|
|
206
215
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
@@ -230,6 +239,7 @@ function iterateComponents(openapi, openapiDir, componentsFiles, ext) {
|
|
|
230
239
|
const componentDirPath = path.join(componentsDir, componentType);
|
|
231
240
|
for (const componentName of Object.keys(components?.[componentType] || {})) {
|
|
232
241
|
const filename = getFileNamePath(componentDirPath, componentName, ext);
|
|
242
|
+
assertWithinDir(openapiDir, filename, componentName);
|
|
233
243
|
gatherComponentsFiles(components, componentsFiles, componentType, componentName, filename);
|
|
234
244
|
}
|
|
235
245
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/cli",
|
|
3
|
-
"version": "0.0.0-snapshot.
|
|
3
|
+
"version": "0.0.0-snapshot.1782825774",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@redocly/config": "0.22.0",
|
|
41
|
-
"@redocly/openapi-core": "0.0.0-snapshot.
|
|
42
|
-
"@redocly/respect-core": "0.0.0-snapshot.
|
|
41
|
+
"@redocly/openapi-core": "0.0.0-snapshot.1782825774",
|
|
42
|
+
"@redocly/respect-core": "0.0.0-snapshot.1782825774",
|
|
43
43
|
"abort-controller": "3.0.0",
|
|
44
44
|
"chokidar": "3.5.3",
|
|
45
45
|
"colorette": "1.4.0",
|