VYPR
Moderate severityNVD Advisory· Published Jun 3, 2021· Updated Aug 3, 2024

TechDocs mkdocs.yml path traversal

CVE-2021-32662

Description

Backstage is an open platform for building developer portals, and techdocs-common contains common functionalities for Backstage's TechDocs. In @backstage/techdocs-common versions prior to 0.6.3, a malicious actor could read sensitive files from the environment where TechDocs documentation is built and published by setting a particular path for docs_dir in mkdocs.yml. These files would then be available over the TechDocs backend API. This vulnerability is mitigated by the fact that an attacker would need access to modify the mkdocs.yml in the documentation source code, and would also need access to the TechDocs backend API. The vulnerability is patched in the 0.6.3 release of @backstage/techdocs-common.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
@backstage/techdocs-commonnpm
< 0.6.30.6.3

Affected products

1

Patches

1
8cefadca04cb

Add validation to prevent docs_dir from being an absolute path

https://github.com/backstage/backstageJussi HallilaMay 20, 2021via ghsa
5 files changed · +66 1
  • .changeset/gold-kings-jog.md+5 0 added
    @@ -0,0 +1,5 @@
    +---
    +'@backstage/techdocs-common': patch
    +---
    +
    +Adding validation to mkdocs.yml parsing to prevent directory tree traversing
    
  • packages/techdocs-common/src/stages/generate/__fixtures__/mkdocs_invalid_doc_dir.yml+3 0 added
    @@ -0,0 +1,3 @@
    +site_name: Test site name
    +site_description: Test site description
    +docs_dir: /etc
    
  • packages/techdocs-common/src/stages/generate/helpers.test.ts+28 0 modified
    @@ -27,6 +27,7 @@ import {
       isValidRepoUrlForMkdocs,
       patchMkdocsYmlPreBuild,
       storeEtagMetadata,
    +  validateMkdocsYaml,
     } from './helpers';
     
     const mockEntity = {
    @@ -43,6 +44,9 @@ const mkdocsYml = fs.readFileSync(
     const mkdocsYmlWithRepoUrl = fs.readFileSync(
       resolvePath(__filename, '../__fixtures__/mkdocs_with_repo_url.yml'),
     );
    +const mkdocsYmlWithInvalidDocDir = fs.readFileSync(
    +  resolvePath(__filename, '../__fixtures__/mkdocs_invalid_doc_dir.yml'),
    +);
     const mockLogger = getVoidLogger();
     const rootDir = os.platform() === 'win32' ? 'C:\\rootDir' : '/rootDir';
     
    @@ -300,4 +304,28 @@ describe('helpers', () => {
           expect(json.etag).toBe('etag123abc');
         });
       });
    +
    +  describe('validateMkdocsYaml', () => {
    +    beforeEach(() => {
    +      mockFs({
    +        '/mkdocs.yml': mkdocsYml,
    +        '/mkdocs_with_repo_url.yml': mkdocsYmlWithRepoUrl,
    +        '/mkdocs_invalid_doc_dir.yml': mkdocsYmlWithInvalidDocDir,
    +      });
    +    });
    +
    +    afterEach(() => {
    +      mockFs.restore();
    +    });
    +
    +    it('should return true on when no docs_dir present', async () => {
    +      await expect(validateMkdocsYaml('/mkdocs.yml')).resolves.toBeUndefined();
    +    });
    +
    +    it('should return false on absolute doc_dir path', async () => {
    +      await expect(
    +        validateMkdocsYaml('/mkdocs_invalid_doc_dir.yml'),
    +      ).rejects.toThrow();
    +    });
    +  });
     });
    
  • packages/techdocs-common/src/stages/generate/helpers.ts+25 0 modified
    @@ -16,6 +16,7 @@
     
     import { Entity } from '@backstage/catalog-model';
     import { spawn } from 'child_process';
    +import { isAbsolute, normalize } from 'path';
     import fs from 'fs-extra';
     import yaml from 'js-yaml';
     import { PassThrough, Writable } from 'stream';
    @@ -138,6 +139,30 @@ export const getRepoUrlFromLocationAnnotation = (
       return undefined;
     };
     
    +/**
    + * Validating mkdocs config file for incorrect/insecure values
    + * Throws on invalid configs
    + *
    + * @param {string} mkdocsYmlPath Absolute path to mkdocs.yml or equivalent of a docs site
    + */
    +export const validateMkdocsYaml = async (mkdocsYmlPath: string) => {
    +  let mkdocsYmlFileString;
    +  try {
    +    mkdocsYmlFileString = await fs.readFile(mkdocsYmlPath, 'utf8');
    +  } catch (error) {
    +    throw new Error(
    +      `Could not read MkDocs YAML config file ${mkdocsYmlPath} before for validation: ${error.message}`,
    +    );
    +  }
    +
    +  const mkdocsYml: any = yaml.load(mkdocsYmlFileString);
    +  if (mkdocsYml.docs_dir && isAbsolute(normalize(mkdocsYml.docs_dir))) {
    +    throw new Error(
    +      "docs_dir configuration value in mkdocs can't be an absolute directory path for security reasons. Use relative paths instead which are resolved relative to your mkdocs.yml file location.",
    +    );
    +  }
    +};
    +
     /**
      * Update the mkdocs.yml file before TechDocs generator uses it to generate docs site.
      *
    
  • packages/techdocs-common/src/stages/generate/techdocs.ts+5 1 modified
    @@ -24,6 +24,7 @@ import {
       patchMkdocsYmlPreBuild,
       runCommand,
       storeEtagMetadata,
    +  validateMkdocsYaml,
     } from './helpers';
     import { GeneratorBase, GeneratorRunOptions } from './types';
     
    @@ -79,14 +80,17 @@ export class TechdocsGenerator implements GeneratorBase {
         // TODO: In future mkdocs.yml can be mkdocs.yaml. So, use a config variable here to find out
         // the correct file name.
         // Do some updates to mkdocs.yml before generating docs e.g. adding repo_url
    +    const mkdocsYmlPath = path.join(inputDir, 'mkdocs.yml');
         if (parsedLocationAnnotation) {
           await patchMkdocsYmlPreBuild(
    -        path.join(inputDir, 'mkdocs.yml'),
    +        mkdocsYmlPath,
             this.logger,
             parsedLocationAnnotation,
           );
         }
     
    +    await validateMkdocsYaml(mkdocsYmlPath);
    +
         // Directories to bind on container
         const mountDirs = {
           [inputDir]: '/input',
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.