Skip to content

Harden IsSafeFileReference against NUL, deep-encoding, and Unicode homoglyph traversal#7913

Merged
gavinbarron merged 4 commits into
mainfrom
harden/static-template-file-reference-encoding
Jul 7, 2026
Merged

Harden IsSafeFileReference against NUL, deep-encoding, and Unicode homoglyph traversal#7913
gavinbarron merged 4 commits into
mainfrom
harden/static-template-file-reference-encoding

Conversation

@gavinbarron

Copy link
Copy Markdown
Contributor

Fixes #7912

Summary

Security-audit follow-up to #7910. Auditing the percent-encoding path-traversal fix against a broader payload matrix surfaced three residual bypasses in ExtensionResponseSemanticsStaticTemplate.IsSafeFileReference, all confirmed by exercising the real method:

  1. Embedded NUL (%00)card%00.json and safe.json%00%2e%2e%2fetc%2fpasswd were accepted. The NUL was not rejected and, when fused with the preceding path segment, defeated the exact-match .. segment check.
  2. Decode-budget fail-open — traversal encoded deeper than the 5-pass decode budget (e.g. %25252525252e..., 6×+) left %XX residue that was accepted verbatim; a consumer decoding further resolves the traversal.
  3. Unicode full-width homoglyph%EF%BC%8E%EF%BC%8E/card.json (→ ../card.json) was accepted because full-width is not literal ..

Fix

After the bounded percent-decode loop, IsSafeFileReference now:

  • Fails closed if percent-encoding still remains (residual %XX after the budget) instead of accepting it.
  • NFKC-folds the value (validation only — the original reference is still emitted verbatim) so full-width / compatibility homoglyphs normalize before the checks.
  • Rejects control characters (including NUL), closing the truncation / segment-evasion vector.

Tests

Extended the StaticTemplateIsSafeFileReferenceValidatesPaths [Theory] with regression cases for NUL, deep-encoding, and full-width (literal + percent-encoded UTF-8) payloads.

dotnet test --filter "FullyQualifiedName~OpenApiAiCapabilitiesExtensionTest"38 passed, 0 failed.

Out of scope (audited, not vulnerable)

AllowedExternalOriginsStreamLoader (#7888): path allow-entries canonicalize encoded .. before matching, so percent-encoding does not bypass them.

gavinbarron and others added 2 commits July 7, 2026 09:50
IsSafeFileReference validated the raw file reference, so percent-encoded traversal payloads (e.g. %2e%2e, %2f, %3a) and double-encoded variants bypassed the absolute-URI, rooted-path, drive-path and '..'-segment checks and were treated as safe. This allowed a malicious static_template.file to resolve outside the manifest package (CWE-22/CWE-829).

Percent-decode the reference in a bounded loop until stable before validating, defeating single and multi-level encoding. Adds regression tests for the reported payloads plus mixed-case, encoded-backslash, encoded-URI and double-encoded variants.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…trol chars, and Unicode homoglyphs

Security audit of the percent-encoding path-traversal fix surfaced three residual bypasses in IsSafeFileReference: (1) an embedded NUL from %00 was accepted and defeated the '..' segment check; (2) traversal encoded deeper than the decode budget left %XX residue that was accepted (fail-open); (3) Unicode full-width homoglyphs (e.g. %EF%BC%8E) were not treated as '..'.

Fail closed when percent-encoding remains after the decode budget, reject control characters, and fold Unicode compatibility forms (NFKC) before validation. Adds regression tests for each vector.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@gavinbarron
gavinbarron requested a review from a team as a code owner July 7, 2026 20:46
gavinbarron and others added 2 commits July 7, 2026 14:02
…e-file-reference-encoding

# Conflicts:
#	src/Kiota.Builder/OpenApiExtensions/OpenApiAiCapabilitiesExtension.cs
#	tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiAiCapabilitiesExtensionTests.cs
Addresses PR review feedback: replace the manual foreach filter loop with a predicate-based Any check for clearer intent. Behavior unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-code-quality

Copy link
Copy Markdown

Code Coverage Overview

Languages: C#

C# / code-coverage/dotnet

The overall coverage in the harden/static-templa... branch is 72%. Coverage data for the main branch is not yet available.

Show a code coverage summary of the most covered files.
File main harden/static-templa... 48a284f +/-
/home/runner/wo...guageRefiner.cs 98%
/home/runner/wo...criptRefiner.cs 98%
/home/runner/wo...MethodWriter.cs 97%
/home/runner/wo...MethodWriter.cs 96%
/home/runner/wo...MethodWriter.cs 96%
/home/runner/wo...MethodWriter.cs 95%
/home/runner/wo...rs/GoRefiner.cs 93%
/home/runner/wo...KiotaBuilder.cs 90%
/home/runner/wo...ationService.cs 89%
/home/runner/wo...xGenerator.g.cs 75%

Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@gavinbarron
gavinbarron enabled auto-merge (squash) July 7, 2026 22:24
@gavinbarron
gavinbarron merged commit 430008e into main Jul 7, 2026
334 of 337 checks passed
@gavinbarron
gavinbarron deleted the harden/static-template-file-reference-encoding branch July 7, 2026 22:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IsSafeFileReference residual bypasses: NUL byte, decode-budget fail-open, and Unicode homoglyphs

2 participants