diff --git a/.changeset/cyan-facts-doubt.md b/.changeset/cyan-facts-doubt.md new file mode 100644 index 0000000000..7597a39c6d --- /dev/null +++ b/.changeset/cyan-facts-doubt.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-node': patch +--- + +Removed `INHERIT` from the `ALLOWED_MKDOCS_KEYS` set to address a security concern with MkDocs configuration inheritance. diff --git a/plugins/techdocs-node/src/stages/generate/helpers.test.ts b/plugins/techdocs-node/src/stages/generate/helpers.test.ts index eb3c32a464..1f198b43e9 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.test.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.test.ts @@ -885,6 +885,32 @@ another_unknown: true ); }); + it('should remove the INHERIT key to prevent loading unsanitized parent configs', async () => { + const mkdocsWithInherit = `INHERIT: ../parent.yml +site_name: Test +`; + mockDir.setContent({ + 'mkdocs_inherit.yml': mkdocsWithInherit, + }); + + await sanitizeMkdocsYml( + mockDir.resolve('mkdocs_inherit.yml'), + mockLogger, + ); + + const updatedMkdocsYml = await fs.readFile( + mockDir.resolve('mkdocs_inherit.yml'), + ); + const parsedYml = yaml.load(updatedMkdocsYml.toString()) as Record< + string, + unknown + >; + + expect(parsedYml.INHERIT).toBeUndefined(); + expect(parsedYml.site_name).toBe('Test'); + expect(warn).toHaveBeenCalledWith(expect.stringContaining('INHERIT')); + }); + it('should remove hooks with duplicate merge keys and top-level anchors', async () => { mockDir.setContent({ 'mkdocs_duplicate_merge.yml': mkdocsYmlWithDuplicateMergeHooks, diff --git a/plugins/techdocs-node/src/stages/generate/helpers.ts b/plugins/techdocs-node/src/stages/generate/helpers.ts index 1b0813f18d..caecb47524 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.ts @@ -309,7 +309,6 @@ export const ALLOWED_MKDOCS_KEYS = new Set([ 'validation', // Deprecated 'google_analytics', - 'INHERIT', ]); /**