Skip to content

Fix RCE via unescaped OpenAPI path/header in Refit attributes (GHSA-3fhm-p725-h3g3)#1175

Closed
christianhelle wants to merge 16 commits into
mainfrom
fix-ghsa-3fhm-p725-h3g3-rce-attribute-injection
Closed

Fix RCE via unescaped OpenAPI path/header in Refit attributes (GHSA-3fhm-p725-h3g3)#1175
christianhelle wants to merge 16 commits into
mainfrom
fix-ghsa-3fhm-p725-h3g3-rce-attribute-injection

Conversation

@christianhelle

@christianhelle christianhelle commented Jun 29, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes GHSA-3fhm-p725-h3g3. Refitter emitted each OpenAPI path key and header name verbatim into Refit [Get("…")] / [Header("…")] attributes. A crafted single-line path closes the attribute string, the interface, and the namespace, injects a top-level file class with a [ModuleInitializer], then reopens a namespace/interface — yielding RCE at assembly load in any app that compiles the generated client. Verified reproducible on the current build with no --skip-validation.

Changes

  • Escape all spec-derived attribute strings (always-on, even with --skip-validation):
    • [Get/Post/...] path — InterfaceGenerator
    • [Header(name)] parameter & security-scheme names — HeaderParameterExtractor
    • [Headers("Accept:"/"Content-Type:")] media types — MethodAttributeGenerator
  • Reject breakout characters (", \, control/newlines) in paths and header names during validation; errors out unless --skip-validation (AttributeStringValidator).
  • Regression tests proving injected payloads stay inert and compile, and that validation rejects them.

Verification

  • Reproduced original RCE; confirmed escaped output compiles and is inert (no module-initializer execution).
  • Malicious spec now rejected by default; --skip-validation still produces safe, escaped code.
  • Full build green; 2117 unit tests pass; security suite (incl. compile checks) passes.

Summary by CodeRabbit

  • Bug Fixes

    • Improved escaping in generated Refit attributes to safely handle special characters in API paths, header names, and Accept/Content-Type header literals.
  • Security Validation

    • Strengthened OpenAPI validation to reject unsafe characters (quotes, backslashes, control characters) in path keys, header parameter names, and header-based API-key security scheme names.
  • Tests

    • Added regression coverage for injection attempts across OpenAPI 3.0 and Swagger 2.0, including C# compile checks and validation failure assertions, plus dedicated validator tests.

@christianhelle christianhelle added the enhancement New feature, bug fix, or request label Jun 29, 2026
@christianhelle christianhelle self-assigned this Jun 29, 2026
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Escapes OpenAPI-derived strings in generated Refit attributes, validates unsafe path/header/security-scheme inputs, and adds regression coverage for OpenAPI 3.0.0 and Swagger 2.0 injection cases.

Changes

Attribute String Injection Fix

Layer / File(s) Summary
Escape generated attribute strings
src/Refitter.Core/Generation/InterfaceGenerator.cs, src/Refitter.Core/Generation/MethodAttributeGenerator.cs, src/Refitter.Core/ParameterExtraction/HeaderParameterExtractor.cs
Path, content-type, header-name, and API-key security-scheme values are escaped before being embedded in generated Refit attributes.
Validate unsafe attribute strings
src/Refitter.Core/Validation/AttributeStringValidator.cs, src/Refitter.Core/Validation/OpenApiValidator.cs
Unsafe path keys, header parameters, and header-based API-key security schemes are reported during OpenAPI validation before results are returned.
Regression tests for injection cases
src/Refitter.Tests/Scenarios/SecurityAttributeInjectionTests.cs, src/Refitter.Tests/OpenApi/AttributeStringValidatorTests.cs
OpenAPI 3.0.0 and Swagger 2.0 tests cover path, header, and security-scheme injection, assert inert generated code, and verify validation rejects unsafe specs.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

bug

Poem

🐇 I hopped through paths both tricky and sly,
With headers and quotes I learned not to rely.
EscapeString guards the generated gate,
So sneaky little snippets cannot infiltrate.
The validator bops unsafe strings away—
Safe code for the burrow, hooray, hooray!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.23% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: fixing RCE from unescaped OpenAPI paths and headers in generated Refit attributes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-ghsa-3fhm-p725-h3g3-rce-attribute-injection

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Refitter.Core/Validation/AttributeStringValidator.cs`:
- Around line 18-50: Validate header-style API key security scheme names in
AttributeStringValidator as well as operation header parameters, since
HeaderParameterExtractor now uses securityScheme.Name for [Header("...")].
Update Validate to inspect document.SecurityDefinitions and reject API-key
schemes with HeaderLocation names containing unsafe characters, adding an
OpenApiError with the scheme name and a clear message consistent with the
existing path/parameter checks. Also add a regression test around
AttributeStringValidator covering a malicious header-based security scheme name
so the bypass no longer occurs without --skip-validation.

In `@src/Refitter.Tests/Scenarios/SecurityAttributeInjectionTests.cs`:
- Around line 18-49: Add OpenAPI 2.0 coverage to the
SecurityAttributeInjectionTests regression cases by parameterizing the malicious
path and header inputs across both dialects instead of only using the 3.0 YAML
snippets. Update the existing PathInjectionSpec and HeaderInjectionSpec-style
test setup so the same injection payloads are exercised through both the 2.0 and
3.0 parsing/generation paths, keeping the escaping and validation assertions
centralized in the relevant test methods.
🪄 Autofix (Beta)

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: be84eaa1-7c35-4364-a06c-165893214e05

📥 Commits

Reviewing files that changed from the base of the PR and between e9b9593 and ced3426.

📒 Files selected for processing (6)
  • src/Refitter.Core/Generation/InterfaceGenerator.cs
  • src/Refitter.Core/Generation/MethodAttributeGenerator.cs
  • src/Refitter.Core/ParameterExtraction/HeaderParameterExtractor.cs
  • src/Refitter.Core/Validation/AttributeStringValidator.cs
  • src/Refitter.Core/Validation/OpenApiValidator.cs
  • src/Refitter.Tests/Scenarios/SecurityAttributeInjectionTests.cs

Comment thread src/Refitter.Core/Validation/AttributeStringValidator.cs
Comment thread src/Refitter.Tests/Scenarios/SecurityAttributeInjectionTests.cs
@codecov

codecov Bot commented Jun 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.45283% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.78%. Comparing base (fe42089) to head (83f3ad2).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
...fitter.Core/Validation/AttributeStringValidator.cs 91.30% 1 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1175      +/-   ##
==========================================
- Coverage   94.82%   94.78%   -0.05%     
==========================================
  Files          80       81       +1     
  Lines        3557     3604      +47     
==========================================
+ Hits         3373     3416      +43     
- Misses         75       76       +1     
- Partials      109      112       +3     
Flag Coverage Δ
unittests 94.78% <92.45%> (-0.05%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Fixes Applied Successfully

Fixed 3 file(s) based on 2 unresolved review comments.

Files modified:

  • src/Refitter.Core/Validation/AttributeStringValidator.cs
  • src/Refitter.Core/Validation/OpenApiValidator.cs
  • src/Refitter.Tests/Scenarios/SecurityAttributeInjectionTests.cs

Commit: 465350cacd484b434ce8b2194a40b22452629d77

The changes have been pushed to the fix-ghsa-3fhm-p725-h3g3-rce-attribute-injection branch.

Time taken: 5m 4s

Fixed 3 file(s) based on 2 unresolved review comments.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/Refitter.Tests/Scenarios/SecurityAttributeInjectionTests.cs (1)

161-174: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the validator-specific diagnostic, not just IsValid.

These specs are intentionally adversarial, so IsValid == false can stay green if parsing fails for an unrelated reason. Please also assert that result.OpenApiDiagnostic.Errors contains the illegal-character rejection for the path/header/security-scheme value so the tests keep proving AttributeStringValidator is the failure source.

Also applies to: 208-298

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Refitter.Tests/Scenarios/SecurityAttributeInjectionTests.cs` around lines
161 - 174, The test in SecurityAttributeInjectionTests only checks
OpenApiValidator.Validate(...).IsValid, which can pass for the wrong failure
reason. Update the affected tests, including
Validation_Rejects_Path_With_Breakout_Characters and the other adversarial cases
mentioned, to also assert that result.OpenApiDiagnostic.Errors contains the
expected illegal-character rejection coming from AttributeStringValidator for
the path/header/security-scheme value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Refitter.Core/Validation/AttributeStringValidator.cs`:
- Line 3: The import in AttributeStringValidator is using an invalid OpenAPI
namespace that does not exist in the current Microsoft.OpenApi surface. Update
the using at the top of AttributeStringValidator to reference the correct root
Microsoft.OpenApi namespace, or remove the unused import entirely if the file
does not need it, so the build resolves cleanly.

In `@src/Refitter.Tests/Scenarios/SecurityAttributeInjectionTests.cs`:
- Around line 223-236: Add the missing OpenAPI 3.0 header-name validation
regression to `Validation_Rejects_Header_With_Breakout_Characters_V2` by also
exercising `OpenApiValidator.Validate(HeaderInjectionSpec)` alongside the
existing `HeaderInjectionSpecV2` case. Keep the same assert pattern used in this
test method so both OpenAPI 2.0 and 3.0 header-validation paths are covered, and
ensure the new non-_V2 case also verifies `IsValid` is false.

---

Nitpick comments:
In `@src/Refitter.Tests/Scenarios/SecurityAttributeInjectionTests.cs`:
- Around line 161-174: The test in SecurityAttributeInjectionTests only checks
OpenApiValidator.Validate(...).IsValid, which can pass for the wrong failure
reason. Update the affected tests, including
Validation_Rejects_Path_With_Breakout_Characters and the other adversarial cases
mentioned, to also assert that result.OpenApiDiagnostic.Errors contains the
expected illegal-character rejection coming from AttributeStringValidator for
the path/header/security-scheme value.
🪄 Autofix (Beta)

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e0472135-1775-4852-a1c3-4b2c2b10158f

📥 Commits

Reviewing files that changed from the base of the PR and between ced3426 and 465350c.

📒 Files selected for processing (3)
  • src/Refitter.Core/Validation/AttributeStringValidator.cs
  • src/Refitter.Core/Validation/OpenApiValidator.cs
  • src/Refitter.Tests/Scenarios/SecurityAttributeInjectionTests.cs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Refitter.Core/Validation/OpenApiValidator.cs

Comment thread src/Refitter.Core/Validation/AttributeStringValidator.cs Outdated
Comment thread src/Refitter.Tests/Scenarios/SecurityAttributeInjectionTests.cs
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Fixes Applied Successfully

Fixed 2 file(s) based on 2 unresolved review comments.

Files modified:

  • src/Refitter.Core/Validation/AttributeStringValidator.cs
  • src/Refitter.Tests/Scenarios/SecurityAttributeInjectionTests.cs

Commit: a06db08ac5e923970cea6d7e6e0529ad68507aa7

The changes have been pushed to the fix-ghsa-3fhm-p725-h3g3-rce-attribute-injection branch.

Time taken: 2m 41s

Fixed 2 file(s) based on 2 unresolved review comments.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses GHSA-3fhm-p725-h3g3 by preventing OpenAPI-sourced strings (paths, header names, media types) from breaking out of generated Refit attribute string literals, and adds validation + regression tests to ensure injection payloads are rejected or rendered inert.

Changes:

  • Escape spec-derived strings emitted into Refit attributes ([Get("…")], [Header("…")], [Headers("Accept: …")], [Headers("Content-Type: …")]).
  • Add validation (AttributeStringValidator) to reject paths/header names containing breakout characters unless validation is skipped.
  • Add regression tests covering path/header/security-scheme injection attempts (OAS3 + Swagger2).

Reviewed changes

Copilot reviewed 6 out of 9 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/Refitter.Tests/Scenarios/SecurityAttributeInjectionTests.cs Adds regression tests for path/header/security-scheme injection scenarios and validation rejection.
src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreSingleInterfaceWithPolly.g.cs Updates generated snapshot imports placement.
src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreSingleInterfaceWithHttpResilience.g.cs Updates generated snapshot imports placement and method-chain formatting.
src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreMultipleInterfaces.g.cs Updates generated snapshot imports placement and method-chain formatting.
src/Refitter.Core/Validation/OpenApiValidator.cs Wires in AttributeStringValidator during validation.
src/Refitter.Core/Validation/AttributeStringValidator.cs New validator rejecting unsafe path/header strings that could break generated attribute literals.
src/Refitter.Core/ParameterExtraction/HeaderParameterExtractor.cs Escapes header names when generating [Header("…")] attributes.
src/Refitter.Core/Generation/MethodAttributeGenerator.cs Escapes media types used in generated Accept / Content-Type header literals.
src/Refitter.Core/Generation/InterfaceGenerator.cs Escapes OpenAPI paths emitted into Refit HTTP method attributes.

Comment thread src/Refitter.Tests/Scenarios/SecurityAttributeInjectionTests.cs
@christianhelle

Copy link
Copy Markdown
Owner Author

Superseded by a new PR that covers all three related advisories (GHSA-3fhm-p725-h3g3, GHSA-58x9-vjvp-6mx8, GHSA-p32v-8v8j-j534) from the same branch. Closing in favor of the broader fix.

@christianhelle

Copy link
Copy Markdown
Owner Author

Superseded by #1178.

@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature, bug fix, or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants