From 2c1012b9ec78b859ac19255c15381ac1e5b898bf Mon Sep 17 00:00:00 2001 From: Endi Date: Mon, 21 Oct 2019 00:58:22 +0700 Subject: [PATCH] fix(v2): do not show plugin data path (#1861) * fix(v2): do not show plugin data path * test fix * nits --- CHANGELOG-2.x.md | 1 + .../src/__tests__/index.test.ts | 10 ++++--- .../src/index.ts | 27 +++++++++++++------ .../src/__tests__/index.test.ts | 2 ++ .../src/index.ts | 15 +++++++++-- packages/docusaurus-types/src/index.d.ts | 2 +- .../src/client/exports/ComponentCreator.js | 2 +- .../__snapshots__/routes.test.ts.snap | 24 ++++++++--------- packages/docusaurus/src/server/index.ts | 2 +- packages/docusaurus/src/server/routes.ts | 4 +-- 10 files changed, 58 insertions(+), 31 deletions(-) diff --git a/CHANGELOG-2.x.md b/CHANGELOG-2.x.md index c8fd2b7766..fd554c9bb0 100644 --- a/CHANGELOG-2.x.md +++ b/CHANGELOG-2.x.md @@ -8,6 +8,7 @@ - Fix `swizzle` command not being able to swizzle single js file. - Fix logo URL in footer to be appended with baseUrl automatically. - Add the option `--no-open` for `start` command. +- Fix potential security vulnerability because we're exposing the directory structure of the host machine. ## 2.0.0-alpha.27 diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts index 756d2a5ebc..7a4b606db4 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts @@ -8,22 +8,24 @@ import fs from 'fs-extra'; import path from 'path'; import pluginContentBlog from '../index'; -import {DocusaurusConfig} from '@docusaurus/types'; +import {DocusaurusConfig, LoadContext} from '@docusaurus/types'; describe('loadBlog', () => { test('simple website', async () => { const siteDir = path.join(__dirname, '__fixtures__', 'website'); - const siteConfig: DocusaurusConfig = { + const generatedFilesDir: string = path.resolve(siteDir, '.docusaurus'); + const siteConfig = { title: 'Hello', baseUrl: '/', url: 'https://docusaurus.io', - }; + } as DocusaurusConfig; const pluginPath = 'blog'; const plugin = pluginContentBlog( { siteDir, siteConfig, - }, + generatedFilesDir, + } as LoadContext, { path: 'blog', }, diff --git a/packages/docusaurus-plugin-content-blog/src/index.ts b/packages/docusaurus-plugin-content-blog/src/index.ts index 5ed86e0fa5..c8f7dce0b7 100644 --- a/packages/docusaurus-plugin-content-blog/src/index.ts +++ b/packages/docusaurus-plugin-content-blog/src/index.ts @@ -59,6 +59,10 @@ export default function pluginContentBlog( ) { const options: PluginOptions = {...DEFAULT_OPTIONS, ...opts}; const contentPath = path.resolve(context.siteDir, options.path); + const dataDir = path.join( + context.generatedFilesDir, + 'docusaurus-plugin-content-blog', + ); return { name: 'docusaurus-plugin-content-blog', @@ -233,6 +237,8 @@ export default function pluginContentBlog( blogTagsPostsComponent, } = options; + const aliasedSource = (source: string) => + `@docusaurus-plugin-content-blog/${path.relative(dataDir, source)}`; const {addRoute, createData} = actions; const { blogPosts, @@ -274,9 +280,9 @@ export default function pluginContentBlog( exact: true, modules: { content: source, - metadata: metadataPath, - prevItem: prevItem && prevItem.metadataPath, - nextItem: nextItem && nextItem.metadataPath, + metadata: aliasedSource(metadataPath), + prevItem: prevItem && aliasedSource(prevItem.metadataPath), + nextItem: nextItem && aliasedSource(nextItem.metadataPath), } as RouteModule, }); }); @@ -310,10 +316,10 @@ export default function pluginContentBlog( truncated: true, }, }, - metadata: metadataPath, + metadata: aliasedSource(metadataPath), }; }), - metadata: pageMetadataPath, + metadata: aliasedSource(pageMetadataPath), }, }); }), @@ -357,10 +363,10 @@ export default function pluginContentBlog( truncated: true, }, }, - metadata: metadataPath, + metadata: aliasedSource(metadataPath), }; }), - metadata: tagsMetadataPath, + metadata: aliasedSource(tagsMetadataPath), }, }); }), @@ -378,7 +384,7 @@ export default function pluginContentBlog( component: blogTagsListComponent, exact: true, modules: { - tags: tagsListPath, + tags: aliasedSource(tagsListPath), }, }); } @@ -391,6 +397,11 @@ export default function pluginContentBlog( ) { const {rehypePlugins, remarkPlugins, truncateMarker} = options; return { + resolve: { + alias: { + '@docusaurus-plugin-content-blog': dataDir, + }, + }, module: { rules: [ { diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts index a4439a7cb6..a338bed2aa 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts @@ -13,6 +13,7 @@ import {LoadContext} from '@docusaurus/types'; describe('loadDocs', () => { test('simple website', async () => { const siteDir = path.join(__dirname, '__fixtures__', 'website'); + const generatedFilesDir: string = path.resolve(siteDir, '.docusaurus'); const siteConfig = { title: 'Hello', baseUrl: '/', @@ -21,6 +22,7 @@ describe('loadDocs', () => { const context = { siteDir, siteConfig, + generatedFilesDir, } as LoadContext; const sidebarPath = path.join(siteDir, 'sidebars.json'); const pluginPath = 'docs'; diff --git a/packages/docusaurus-plugin-content-docs/src/index.ts b/packages/docusaurus-plugin-content-docs/src/index.ts index df3d710fa4..c408521538 100644 --- a/packages/docusaurus-plugin-content-docs/src/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/index.ts @@ -53,6 +53,10 @@ export default function pluginContentDocs( const options = {...DEFAULT_OPTIONS, ...opts}; const contentPath = path.resolve(context.siteDir, options.path); let sourceToPermalink: SourceToPermalink = {}; + const dataDir = path.join( + context.generatedFilesDir, + 'docusaurus-plugin-content-docs', + ); return { name: 'docusaurus-plugin-content-docs', @@ -210,6 +214,8 @@ export default function pluginContentDocs( const {docLayoutComponent, docItemComponent, routeBasePath} = options; const {addRoute, createData} = actions; + const aliasedSource = (source: string) => + `@docusaurus-plugin-content-docs/${path.relative(dataDir, source)}`; const routes = await Promise.all( Object.values(content.docsMetadata).map(async metadataItem => { @@ -223,7 +229,7 @@ export default function pluginContentDocs( exact: true, modules: { content: metadataItem.source, - metadata: metadataPath, + metadata: aliasedSource(metadataPath), }, }; }), @@ -248,7 +254,7 @@ export default function pluginContentDocs( component: docLayoutComponent, routes, modules: { - docsMetadata: docsBaseMetadataPath, + docsMetadata: aliasedSource(docsBaseMetadataPath), }, }); }, @@ -257,6 +263,11 @@ export default function pluginContentDocs( const {getBabelLoader, getCacheLoader} = utils; const {rehypePlugins, remarkPlugins} = options; return { + resolve: { + alias: { + '@docusaurus-plugin-content-docs': dataDir, + }, + }, module: { rules: [ { diff --git a/packages/docusaurus-types/src/index.d.ts b/packages/docusaurus-types/src/index.d.ts index e66dd7da6e..6793615bb3 100644 --- a/packages/docusaurus-types/src/index.d.ts +++ b/packages/docusaurus-types/src/index.d.ts @@ -100,7 +100,7 @@ export interface Plugin { export type PluginConfig = [string, Object] | [string] | string; export interface ChunkRegistry { - importStatement: string; + loader: string; modulePath: string; } diff --git a/packages/docusaurus/src/client/exports/ComponentCreator.js b/packages/docusaurus/src/client/exports/ComponentCreator.js index 882f816de1..46ab1b15dc 100644 --- a/packages/docusaurus/src/client/exports/ComponentCreator.js +++ b/packages/docusaurus/src/client/exports/ComponentCreator.js @@ -56,7 +56,7 @@ function ComponentCreator(path) { } const chunkRegistry = registry[target] || {}; - optsLoader[keys.join('.')] = chunkRegistry.importStatement; + optsLoader[keys.join('.')] = chunkRegistry.loader; optsModules.push(chunkRegistry.module); optsWebpack.push(chunkRegistry.webpack); } diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/routes.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/routes.test.ts.snap index c69b21579b..8b3cb04aa8 100644 --- a/packages/docusaurus/src/server/__tests__/__snapshots__/routes.test.ts.snap +++ b/packages/docusaurus/src/server/__tests__/__snapshots__/routes.test.ts.snap @@ -4,19 +4,19 @@ exports[`loadRoutes flat route config 1`] = ` Object { "registry": Object { "component---theme-blog-list-pagea-6-a-7ba": Object { - "importStatement": "() => import(/* webpackChunkName: 'component---theme-blog-list-pagea-6-a-7ba' */ \\"@theme/BlogListPage\\")", + "loader": "() => import(/* webpackChunkName: 'component---theme-blog-list-pagea-6-a-7ba' */ \\"@theme/BlogListPage\\")", "modulePath": "@theme/BlogListPage", }, "content---blog-0-b-4-09e": Object { - "importStatement": "() => import(/* webpackChunkName: 'content---blog-0-b-4-09e' */ \\"blog/2018-12-14-Happy-First-Birthday-Slash.md?truncated=true\\")", + "loader": "() => import(/* webpackChunkName: 'content---blog-0-b-4-09e' */ \\"blog/2018-12-14-Happy-First-Birthday-Slash.md?truncated=true\\")", "modulePath": "blog/2018-12-14-Happy-First-Birthday-Slash.md?truncated=true", }, "content---blog-7-b-8-fd9": Object { - "importStatement": "() => import(/* webpackChunkName: 'content---blog-7-b-8-fd9' */ \\"blog/2018-12-14-Happy-First-Birthday-Slash.md\\")", + "loader": "() => import(/* webpackChunkName: 'content---blog-7-b-8-fd9' */ \\"blog/2018-12-14-Happy-First-Birthday-Slash.md\\")", "modulePath": "blog/2018-12-14-Happy-First-Birthday-Slash.md", }, "metadata---blog-0-b-6-74c": Object { - "importStatement": "() => import(/* webpackChunkName: 'metadata---blog-0-b-6-74c' */ \\"blog-2018-12-14-happy-first-birthday-slash-d2c.json\\")", + "loader": "() => import(/* webpackChunkName: 'metadata---blog-0-b-6-74c' */ \\"blog-2018-12-14-happy-first-birthday-slash-d2c.json\\")", "modulePath": "blog-2018-12-14-happy-first-birthday-slash-d2c.json", }, }, @@ -65,31 +65,31 @@ exports[`loadRoutes nested route config 1`] = ` Object { "registry": Object { "component---theme-doc-item-178-a40": Object { - "importStatement": "() => import(/* webpackChunkName: 'component---theme-doc-item-178-a40' */ \\"@theme/DocItem\\")", + "loader": "() => import(/* webpackChunkName: 'component---theme-doc-item-178-a40' */ \\"@theme/DocItem\\")", "modulePath": "@theme/DocItem", }, "component---theme-doc-page-1-be-9be": Object { - "importStatement": "() => import(/* webpackChunkName: 'component---theme-doc-page-1-be-9be' */ \\"@theme/DocPage\\")", + "loader": "() => import(/* webpackChunkName: 'component---theme-doc-page-1-be-9be' */ \\"@theme/DocPage\\")", "modulePath": "@theme/DocPage", }, "content---docs-foo-baz-8-ce-61e": Object { - "importStatement": "() => import(/* webpackChunkName: 'content---docs-foo-baz-8-ce-61e' */ \\"docs/foo/baz.md\\")", + "loader": "() => import(/* webpackChunkName: 'content---docs-foo-baz-8-ce-61e' */ \\"docs/foo/baz.md\\")", "modulePath": "docs/foo/baz.md", }, "content---docs-helloaff-811": Object { - "importStatement": "() => import(/* webpackChunkName: 'content---docs-helloaff-811' */ \\"docs/hello.md\\")", + "loader": "() => import(/* webpackChunkName: 'content---docs-helloaff-811' */ \\"docs/hello.md\\")", "modulePath": "docs/hello.md", }, "docsMetadata---docsf-34-2ab": Object { - "importStatement": "() => import(/* webpackChunkName: 'docsMetadata---docsf-34-2ab' */ \\"docs-b5f.json\\")", + "loader": "() => import(/* webpackChunkName: 'docsMetadata---docsf-34-2ab' */ \\"docs-b5f.json\\")", "modulePath": "docs-b5f.json", }, "metadata---docs-foo-baz-2-cf-fa7": Object { - "importStatement": "() => import(/* webpackChunkName: 'metadata---docs-foo-baz-2-cf-fa7' */ \\"docs-foo-baz-dd9.json\\")", + "loader": "() => import(/* webpackChunkName: 'metadata---docs-foo-baz-2-cf-fa7' */ \\"docs-foo-baz-dd9.json\\")", "modulePath": "docs-foo-baz-dd9.json", }, "metadata---docs-hello-956-741": Object { - "importStatement": "() => import(/* webpackChunkName: 'metadata---docs-hello-956-741' */ \\"docs-hello-da2.json\\")", + "loader": "() => import(/* webpackChunkName: 'metadata---docs-hello-956-741' */ \\"docs-hello-da2.json\\")", "modulePath": "docs-hello-da2.json", }, }, @@ -152,7 +152,7 @@ exports[`loadRoutes route config with empty (but valid) path string 1`] = ` Object { "registry": Object { "component---hello-world-jse-0-f-b6c": Object { - "importStatement": "() => import(/* webpackChunkName: 'component---hello-world-jse-0-f-b6c' */ \\"hello/world.js\\")", + "loader": "() => import(/* webpackChunkName: 'component---hello-world-jse-0-f-b6c' */ \\"hello/world.js\\")", "modulePath": "hello/world.js", }, }, diff --git a/packages/docusaurus/src/server/index.ts b/packages/docusaurus/src/server/index.ts index ebf127b375..0b9270e4ac 100644 --- a/packages/docusaurus/src/server/index.ts +++ b/packages/docusaurus/src/server/index.ts @@ -118,7 +118,7 @@ export async function load(siteDir: string): Promise { ${Object.keys(registry) .map( key => ` '${key}': { - 'importStatement': ${registry[key].importStatement}, + 'loader': ${registry[key].loader}, 'module': ${JSON.stringify(registry[key].modulePath)}, 'webpack': require.resolveWeak(${JSON.stringify(registry[key].modulePath)}), },`, diff --git a/packages/docusaurus/src/server/routes.ts b/packages/docusaurus/src/server/routes.ts index f9bf0ce090..520f22a9e0 100644 --- a/packages/docusaurus/src/server/routes.ts +++ b/packages/docusaurus/src/server/routes.ts @@ -83,12 +83,12 @@ export async function loadRoutes(pluginsRouteConfigs: RouteConfig[]) { const modulePath = getModulePath(value as Module); const chunkName = genChunkName(modulePath, prefix, name); - const importStatement = `() => import(/* webpackChunkName: '${chunkName}' */ ${JSON.stringify( + const loader = `() => import(/* webpackChunkName: '${chunkName}' */ ${JSON.stringify( modulePath, )})`; registry[chunkName] = { - importStatement, + loader, modulePath, }; return chunkName;