GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Quote or validate every spec string that reaches generated Go source by mromaszewicz · Pull Request #2625 · oapi-codegen/oapi-codegen

Conversation

@mromaszewicz

@mromaszewicz mromaszewicz commented Oct 23, 2026

Copy link
Copy Markdown
Member

Summary

A survey of every place a string from the OpenAPI document reaches the generated Go source found several sinks that copied the value in without strconv.Quote or an identifier check, so a crafted document could make the generated package carry code of its own choosing. kin-openapi's own validation is never run, so ValidateSpec and the sinks themselves are the only guard. This closes all of them in one change.

Fixes

Sink Before Now
initiator.tmpl request body content type "{{.ContentType}}" toGoString, like the client. MIME parameters with quoted strings also used to produce code that did not compile.
echo-register.tmpl OperationMiddlewares key raw operationId between literal quotes toGoString; ValidateSpec also rejects control characters in an operationId
Non-string enum constants value emitted verbatim, unquoted must be a number or boolean literal, else a clear error naming the value and type
Security scopes (toStringArray) joined with ",", so a scope ending in a backslash escaped the joiner's quote each element strconv.Quoted
Discriminator.literal " + value + " strconv.Quote
Response keys unchecked; copied into type names and rsp.StatusCode == <key> must be a three-digit code, a range such as 2XX, or default
Component names (schemas, parameters, request bodies, responses, headers, callbacks, security schemes) unchecked; reach single-line doc comments verbatim control characters rejected (quotes stay allowed; the names become identifiers only after sanitization)
Response header style unchecked (parameter style was) checked the same way
server-urls: x-go-name, variable names, undeclared {placeholder} names, enum values used as identifiers without sanitizing new ValidateServerURLs, run only when server URLs are generated, requires identifiers (enum values: identifier characters, since they are appended to the type name)

Compatibility

Generated fixtures are unchanged: make generate produces no diff, so every valid value renders byte-for-byte as before. The new validation only rejects documents that already produced code that did not compile, or that produced code the document author had no business producing. ValidateServerURLs is deliberately separate from ValidateSpec so that, for example, a hyphenated server variable name keeps working for everyone who does not generate server URLs.

Testing

Each item has a regression test in pkg/codegen. The end-to-end ones generate from a crafted document and check that the payload stays inside a string literal, or that generation fails with a clear error. go test ./pkg/codegen/ ./cmd/... and lint pass locally.

🤖 Generated with Claude Code

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

greptile-apps[bot] reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
@mromaszewicz @claude
Quote or validate every spec string that reaches generated Go source
775e140
A survey of the template and Go-side sinks found several places where a
value taken from the OpenAPI document was copied into the generated code
without going through strconv.Quote or an identifier check, so that a
crafted document could make the generated package carry code of its own
choosing. kin-openapi's own validation is never run, so ValidateSpec and
the sinks themselves are the only guard. This closes all of them:

- initiator.tmpl emitted the request body's content type as "{{.ContentType}}";
  it now goes through toGoString like the client's does. MIME parameters
  may legitimately contain quoted strings, which also used to produce
  code that did not compile.
- echo-register.tmpl emitted the raw operationId as the OperationMiddlewares
  key inside literal quotes; it now goes through toGoString. ValidateSpec
  additionally rejects control characters in an operationId.
- A non-string enum is emitted unquoted, and its values were whatever the
  spec wrote. GenerateEnums now requires each such value to be a number or
  boolean literal and reports the offending value otherwise.
- toStringArray joined security scopes with `","`: a scope ending in a
  backslash escaped the quote the joiner supplied and the next scope became
  code. Each element is now quoted on its own.
- Discriminator.literal wrapped a string value in quotes by hand; it now
  uses strconv.Quote.
- Response keys are copied into type names and, for the client, into
  `rsp.StatusCode == <key>`; they were never checked. ValidateSpec now
  requires a three-digit code, a range such as 2XX, or default.
- Component names (schemas, parameters, request bodies, responses, headers,
  callbacks, security schemes) reach single-line doc comments verbatim, so
  a newline ended the comment; ValidateSpec rejects control characters in
  them. Quotes stay allowed, since the names become identifiers only after
  sanitization.
- A response header's style is copied into a string literal by the strict
  templates like a parameter's; it is now checked the same way.
- The server-urls generator uses x-go-name, variable names, undeclared
  {placeholder} names and enum values as identifiers without sanitizing
  them. A new ValidateServerURLs, run only when server URLs are generated
  so other specs are unaffected, requires each to be a Go identifier (enum
  values: identifier characters, since they are appended to the type name).

Generated fixtures are unchanged: every valid value renders byte-for-byte
as before. Each item has a regression test; the end-to-end ones generate
from a crafted document and check that the payload stays inside a string
literal or is rejected with a clear error.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
@mromaszewicz
mromaszewicz requested a review from a team as a code owner October 23, 2026 23:45
@mromaszewicz mromaszewicz added the bug Something isn't working label Oct 23, 2026
@greptile-apps

greptile-apps Bot commented Oct 23, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; the latest change fixes the unused-variable rejection without leaving emitted variables unchecked.

Summary

The PR quotes spec strings and checks values before placing them into generated Go code.

  • Generated Go keeps OpenAPI strings inside their string literals.
  • Generation rejects response keys and enum values that do not fit Go source.
  • Generation rejects control characters in names and response header styles.
  • Server URL generation checks names before using them as Go identifiers.

Reviews (2) · Last reviewed commit: "Check only the server variables the URL ..." · Reviewed by Greptile

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

greptile-apps[bot]
greptile-apps Bot reviewed Oct 23, 2026
View reviewed changes
Comment thread pkg/codegen/validate_spec.go Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread pkg/codegen/codegen.go Resolved

Uh oh!

There was an error while loading. Please reload this page.

@mromaszewicz @claude
Check only the server variables the URL uses
d0f08ab
Review feedback on oapi-codegen#2625. ValidateServerURLs checked every declared
variable, but the generator only emits code for variables whose {name}
placeholder appears in the URL, so a server with an unused hyphenated
variable, or an unused enum value such as us-east, was refused although it
generated fine before. Limit the name and enum-value checks to
UsedVariables, keeping the separate check for undeclared placeholders, and
cover the unused case in the test.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
@mromaszewicz
mromaszewicz merged commit 34cae75 into oapi-codegen:main Oct 23, 2026
15 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@mromaszewicz mromaszewicz mentioned this pull request Oct 23, 2026
Quote or validate every spec string that reaches generated Go source (2.8.x backport) #2626
Merged
mromaszewicz added a commit that referenced this pull request Oct 24, 2026
@mromaszewicz @claude
Quote or validate every spec string that reaches generated Go source …
068f1bc
…(2.8.x backport) (#2626)

* Quote or validate every spec string that reaches generated Go source (2.8.x)

Hand port of the main change to the 2.8.x templates and code: the two
initiator templates and both Echo register templates carry the sinks that
main has in one file each, strict-fiber-v3.tmpl has a raw content-type
literal that main's unified Fiber template already quotes, and the
discriminator literal helper does not exist here, so that item is dropped.

- webhook-initiator.tmpl and callback-initiator.tmpl emitted the request
  body's content type as "{{.ContentType}}", and strict-fiber-v3.tmpl did
  the same in its multi-body content-type match; they now go through
  toGoString like the client's does. MIME parameters may legitimately
  contain quoted strings, which also used to produce code that did not
  compile.
- echo/echo-register.tmpl and echo/v5/echo-register.tmpl emitted the raw
  operationId as the OperationMiddlewares key inside literal quotes; they
  now go through toGoString. ValidateSpec additionally rejects control
  characters in an operationId.
- A non-string enum is emitted unquoted, and its values were whatever the
  spec wrote. GenerateEnums now requires each such value to be a number or
  boolean literal and reports the offending value otherwise.
- toStringArray joined security scopes with `","`: a scope ending in a
  backslash escaped the quote the joiner supplied and the next scope became
  code. Each element is now quoted on its own.
- Response keys are copied into type names and, for the client, into
  `rsp.StatusCode == <key>`; they were never checked. ValidateSpec now
  requires a three-digit code, a range such as 2XX, or default.
- Component names (schemas, parameters, request bodies, responses, headers,
  callbacks, security schemes) reach single-line doc comments verbatim, so
  a newline ended the comment; ValidateSpec rejects control characters in
  them. Quotes stay allowed, since the names become identifiers only after
  sanitization.
- A response header's style is copied into a string literal by the strict
  templates like a parameter's; it is now checked the same way.
- The server-urls generator uses x-go-name, variable names, undeclared
  {placeholder} names and enum values as identifiers without sanitizing
  them. A new ValidateServerURLs, run only when server URLs are generated
  so other specs are unaffected, requires each to be a Go identifier (enum
  values: identifier characters, since they are appended to the type name).

Generated fixtures are unchanged: every valid value renders byte-for-byte
as before. Each item has a regression test; the end-to-end ones generate
from a crafted document and check that the payload stays inside a string
literal or is rejected with a clear error.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Check only the server variables the URL uses

Review feedback on #2625. ValidateServerURLs checked every declared
variable, but the generator only emits code for variables whose {name}
placeholder appears in the URL, so a server with an unused hyphenated
variable, or an unused enum value such as us-east, was refused although it
generated fine before. Limit the name and enum-value checks to
UsedVariables, keeping the separate check for undeclared placeholders, and
cover the unused case in the test.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

* Add missing case to validation (#2493)

`checkExtensions` in `validate_spec.go` validated `x-go-name`,
`x-go-type-name`, `x-go-type`, and `x-oapi-codegen-extra-tags`, but
had no case for `x-go-type-import`. This adds validation for both
fields of that extension:

- `name`: must be empty, `"."` (dot-import), or a valid Go identifier;
  handled by a new `checkGoImportName` method
- `path`: must not contain control characters; handled by a new
  `checkGoImportPath` method (the path is emitted with `%q` so control
  characters would be escaped anyway, but we reject obviously malformed
  inputs early)

Also adds `validate_spec_test.go` with tests covering valid inputs,
invalid `name` and `path` values, case-insensitive key matching
(mirroring `ParseGoImportExtension`), and regression coverage for the
pre-existing extension checks.

Co-authored-by: Claude Sonnet 4.6 (1M context) <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@greptile-apps greptile-apps[bot] greptile-apps[bot] left review comments

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

bug Something isn't working

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

1 participant

@mromaszewicz
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.