OpenAPI3 version value escapes `emitterOutputDir` and overwrites YAML/JSON outside the output tree

Published September 8, 2026 GHSA-2q42-4q24-7rgv

TypeSpec is Microsoft's tool for describing APIs, and its OpenAPI3 output feature has a bug. A booby-trapped TypeSpec project file can trick it into overwriting other files on the developer's own machine, outside the folder it should be limited.

Severity
HighCVSS 7.1
Affected versions
1.15.0 or older; 1.15.0 or older
Affects
@typespec/openapi3+1 more

How it works

  • A TypeSpec project can mark an API with version labels using a @versioned feature.
  • TypeSpec copies whatever text is in that version label straight into the name of the output file it writes.
  • It does not strip out slashes, backslashes, or folder-traversal sequences from that text.
  • When the compiler runs and writes the finished OpenAPI file, it never checks that the final file path actually stays inside the output folder it was told to use.
  • That lets a crafted version label point the write somewhere else entirely, subject to whatever file permissions the compiler process has.

What to do

Check which version of the compiler and OpenAPI3 package your project uses. The confirmed vulnerable build is 1.15.0 and the advisory does not identify any fixed release number yet. The malicious content has to be inside the.tsp source file. If you only compile your own team's reviewed TypeSpec files, exposure is low even on 1.15.0.

Run this in the application environment you want to check:

npm ls @typespec/openapi3 @typespec/compiler

Until that fix ships in a published npm release, avoid compiling TypeSpec files from sources you have not reviewed, and watch the @typespec/openapi3 and @typespec/compiler npm pages or the GitHub advisory for the release that includes this fix.

Technical details

Affected software: @typespec/openapi3, @typespec/compiler

The openapi3 emitter reads the value of a @versioned enum member and drops it into the {version} token of its output filename template via interpolatePath, then hands the completed path to the compiler's emitFile. emitFile creates any missing parent directories and writes the file without checking that the resolved path is still inside emitterOutputDir. Because the version string is never sanitized for path separators or traversal sequences, a crafted TypeSpec.tsp file can redirect that write to another writable location, creating or overwriting an OpenAPI-formatted YAML or JSON file there. Microsoft's fix adds a sanitizePathSegment helper and strict path containment to close this off.

References