{"id":"GO-2026-6016","revision":null,"records":[{"revision":"d84a80f3ed4a40d79613d96f9c35ff9a","observedAt":"2026-10-30T03:48:59.922+00:00","statement":{"source":"osv","id":"GHSA-rjwr-m7qx-3fjr","aliases":["GO-2026-6016"],"title":"oapi-codegen: OpenAPI Server Description Escapes Generated Go Comment and Injects Executable Code","description":"## Summary\n\nThe vulnerability in oapi-codegen seems to be similar with CVE-2026-22785,  which is a generated-code injection issue where untrusted OpenAPI `summary` text is embedded into generated TypeScript MCP server source without proper escaping. `oapi-codegen` has a similar vulnerability in its server URL generator: untrusted OpenAPI `servers[].description` text is inserted into a generated Go line comment without normalizing embedded newlines. A crafted description can break out of the comment, add imports through `goimports`, and emit executable Go declarations into the generated package.\n\n> [!NOTE]\n> A vulnerability like this requires that it is missed in code review **and** that you then call the malicious method.\n> \n> Using an `init()` function could be enough to not require a direct call to the code, and instead rely on you importing the package, but either way, code review should be performed before any `oapi-codegen` generated code is executed.\n> \n> We **strongly recommend** all users to be reviewing changes to their generated code before they execute anything within it, to protect against supply chain attacks or malicious injected code.\n>\n> This is also why we recommend `oapi-codegen` generated code is committed to source control.\n\n## Details\nThe vulnerable sink is in `pkg/codegen/templates/server-urls.tmpl`.\n\n```gotemplate\n// {{ .GoName }} defines the Server URL for {{ if len .OAPISchema.Description }}{{ .OAPISchema.Description }}{{ else }}{{ .OAPISchema.URL }}{{ end }}\nconst {{ .GoName}} = \"{{ .OAPISchema.URL }}\"\n```\n\nThis template assumes the OpenAPI server description remains inside a single Go line comment. However, OpenAPI descriptions are attacker-controlled strings and may contain newlines. Once a newline is present, the next line is no longer part of the comment.\n\nThe same raw description is also used in the function form of server URL generation:\n\n```gotemplate\n// New{{ .GoName }} constructs the Server URL for {{ .OAPISchema.Description }}, with the provided variables.\nfunc New{{ .GoName }}({{ .NewServerFunctionParams }}) (string, error) {\n```\n\nIdentifier generation does not protect this sink. In `pkg/codegen/server_urls.go`, the description is normalized only for the generated Go identifier:\n\n```go\nsuffix := server.Description\nif suffix == \"\" {\n\tsuffix = nameNormalizer(server.URL)\n}\nname = serverURLPrefix + UppercaseFirstCharacter(suffix)\nname = nameNormalizer(name)\n```\n\nThe identifier is sanitized, but the raw `server.Description` is still rendered in the comment template. This leaves the code-generation context vulnerable.\n\nThe generated file is then formatted with `goimports` in `pkg/codegen/codegen.go`:\n\n```go\ngoCode := SanitizeCode(buf.String())\n\noutBytes, err := imports.Process(opts.PackageName+\".go\", []byte(goCode), nil)\n```\n\n`SanitizeCode` only removes byte-order marks:\n\n```go\nfunc SanitizeCode(goCode string) string {\n\treturn strings.ReplaceAll(goCode, \"\\uFEFF\", \"\")\n}\n```\n\nIt does not escape comments, replace newlines, or otherwise serialize untrusted text for a Go source-code context. As a result, attacker-controlled source can be preserved and formatted as valid Go.\n\n### How to Reproduce\nThe attacker-controlled input is an OpenAPI document whose `servers[].description` contains a newline followed by Go declarations:\n\n```yaml\nopenapi: \"3.0.0\"\ninfo:\n  title: oapi-codegen server URL description injection\n  version: \"1.0.0\"\nservers:\n  - url: https://api.example.com\n    description: |\n      benign\n      var _ = func() int {\n          panic(\"oapi-codegen generated-code execution\")\n          return 0\n      }()\n      //\npaths: {}\n```\n\nGenerate Go source with server URL generation enabled. No special local path or helper file is required for the vulnerability; the malicious description is copied into the generated source-code context.\n\nThe generated source contains attacker-controlled executable code:\n\n```go\n// ServerUrlBenignvarFuncIntPanicOapiCodegenGeneratedCodeExecutionReturn0 defines the Server URL for benign\nvar _ = func() int {\n\tpanic(\"oapi-codegen generated-code execution\")\n\treturn 0\n}()\n\n//\n\nconst ServerUrlBenignvarFuncIntPanicOapiCodegenGeneratedCodeExecutionReturn0 = \"https://api.example.com\"\n```\n\n## Impact\n\nAn attacker who can supply or influence an OpenAPI document consumed by `oapi-codegen` can inject arbitrary Go source into the generated package. In common API-client/server generation workflows, this can lead to build-time or runtime code execution in developer machines, CI systems, or downstream applications that trust generated code.","state":0,"publishedAt":"2026-07-17T18:50:17+00:00","modifiedAt":"2026-10-30T02:57:05.3066853+00:00","affected":[{"ecosystem":"Go","name":"github.com/oapi-codegen/oapi-codegen/v2","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"2.7.1"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"LOW"}],"references":["https://github.com/oapi-codegen/oapi-codegen/security/advisories/GHSA-rjwr-m7qx-3fjr","https://github.com/oapi-codegen/oapi-codegen/commit/19c6282e9a6fb84b51aa92b12fad1f0b7e5f5ef6","https://github.com/oapi-codegen/oapi-codegen","https://github.com/oapi-codegen/oapi-codegen/releases/tag/v2.7.1"],"sourceUrl":"https://github.com/advisories/GHSA-rjwr-m7qx-3fjr","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-rjwr-m7qx-3fjr","identifiers":["GHSA-rjwr-m7qx-3fjr","GO-2026-6016"]},"retained":false,"historicalAffected":[]},{"revision":"9c8cfae7256c482bbbd7bfa8ade286f9","observedAt":"2026-10-24T13:19:41.952+00:00","statement":{"source":"osv","id":"GO-2026-6016","aliases":["GHSA-rjwr-m7qx-3fjr"],"title":"oapi-codegen: OpenAPI Server Description Escapes Generated Go Comment and Injects Executable Code in github.com/oapi-codegen/oapi-codegen","description":"oapi-codegen: OpenAPI Server Description Escapes Generated Go Comment and Injects Executable Code in github.com/oapi-codegen/oapi-codegen","state":0,"publishedAt":"2026-07-22T20:36:35+00:00","modifiedAt":"2026-07-25T03:29:37.7434736+00:00","affected":[{"ecosystem":"Go","name":"github.com/oapi-codegen/oapi-codegen","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"}]}],"versions":[],"rawVersionEvidence":null},{"ecosystem":"Go","name":"github.com/oapi-codegen/oapi-codegen/v2","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"2.7.1"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[],"references":["https://github.com/oapi-codegen/oapi-codegen/security/advisories/GHSA-rjwr-m7qx-3fjr","https://github.com/oapi-codegen/oapi-codegen/commit/19c6282e9a6fb84b51aa92b12fad1f0b7e5f5ef6","https://github.com/oapi-codegen/oapi-codegen/releases/tag/v2.7.1"],"sourceUrl":"https://osv.dev/vulnerability/GO-2026-6016","license":"OSV · upstream source license applies","key":"osv:GO-2026-6016","identifiers":["GO-2026-6016","GHSA-rjwr-m7qx-3fjr"]},"retained":false,"historicalAffected":[]}],"coverage":[{"source":"cisa-kev:global","scope":"Complete CISA KEV catalog; all vendors. Missing entries do not establish absence of exploitation.","generation":"2026-11-07T01:26:54.7341767+00:00","complete":true,"records":1769,"lastAttemptAt":"2026-11-07T01:26:54.7341767+00:00","lastSuccessAt":"2026-11-07T01:26:54.8876863+00:00","error":null,"lastVerifiedAt":"2026-11-07T01:26:54.8876872+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"cve-program","scope":"Official CVE Program baseline and cumulative hourly delta; all vendors, published and rejected records","generation":"cve-e3f76855f3f449c8c0427e4ebd06d00838fa519af10fe158fc0ca4a62af0718a-340a45d9017d4f9de046b855ad9d1afbc5c699f0e6a7003981ff3a54ebedd5b3","complete":true,"records":420470,"lastAttemptAt":"2026-11-07T01:26:54.2134599+00:00","lastSuccessAt":"2026-11-06T23:27:15.9170833+00:00","error":"InvalidOperationException","lastVerifiedAt":"2026-11-07T00:26:54.2874398+00:00","snapshotPublishedAt":"2026-11-06T23:24:11+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"euvd","scope":"Rolling EUVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global EUVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-3aa95a40804b4641b03e520a2e0f5685","complete":false,"records":13623,"lastAttemptAt":"2026-11-07T01:30:32.4521524+00:00","lastSuccessAt":"2026-11-07T01:30:32.5113111+00:00","error":null,"lastVerifiedAt":"2026-11-07T01:30:32.5113111+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"first-epss:nuget","scope":"FIRST EPSS for explicit CVE aliases in the collected public NuGet archive. Not a global EPSS backfill.","generation":"2026-11-07T01:26:54.7341767+00:00","complete":true,"records":1096,"lastAttemptAt":"2026-11-07T01:26:54.7341767+00:00","lastSuccessAt":"2026-11-07T01:26:54.8884513+00:00","error":null,"lastVerifiedAt":"2026-11-07T01:26:54.8884516+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"nvd","scope":"Rolling NVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global NVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-34343b4ea57e47c5a482c8fcf20a381e","complete":true,"records":13645,"lastAttemptAt":"2026-11-07T01:26:55.9490879+00:00","lastSuccessAt":"2026-11-07T01:26:55.938+00:00","error":null,"lastVerifiedAt":"2026-11-07T01:26:55.938+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13685,"expectedIdentifiers":13685,"failedIdentifiers":0},{"source":"osv:Go","scope":"Complete OSV Go ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"go-0eb4d6dde62dffacd040ad992d4fd5a65cd7d0dc5f5f4cfa8b41967fc6f9ca5f","complete":true,"records":9914,"lastAttemptAt":"2026-11-07T01:26:54.5768376+00:00","lastSuccessAt":"2026-11-06T20:10:36.6450506+00:00","error":null,"lastVerifiedAt":"2026-11-07T01:26:54.5768376+00:00","snapshotPublishedAt":"2026-11-06T20:02:57+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:NuGet","scope":"Complete OSV NuGet ecosystem archive, including GitHub Advisory Database records; NuGet version matching only","generation":"nuget-fde804134ecdda0ddd5ff5c26ee1fff5a6fa659311f7ef2e51c6ad54964db0e2","complete":true,"records":1971,"lastAttemptAt":"2026-11-07T01:26:54.3688172+00:00","lastSuccessAt":"2026-11-06T19:03:17.0399903+00:00","error":null,"lastVerifiedAt":"2026-11-07T01:26:54.3688172+00:00","snapshotPublishedAt":"2026-11-06T18:17:57+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:crates.io","scope":"Complete OSV crates.io ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"crates.io-335633e78a15c9cde10a6025895b5617717087fb945489ae7e15d377bacf34a9","complete":true,"records":3055,"lastAttemptAt":"2026-11-07T01:26:54.6823337+00:00","lastSuccessAt":"2026-11-06T16:03:00.7615789+00:00","error":null,"lastVerifiedAt":"2026-11-07T01:26:54.6823337+00:00","snapshotPublishedAt":"2026-11-06T16:02:48+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:npm","scope":"Complete OSV npm ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"npm-a0b728bc1c5526b5429930c00621636eba8655069c176697c3080f8377619ad7","complete":true,"records":231291,"lastAttemptAt":"2026-11-07T01:26:54.4691469+00:00","lastSuccessAt":"2026-11-07T00:28:51.1983528+00:00","error":null,"lastVerifiedAt":"2026-11-07T01:26:54.4691469+00:00","snapshotPublishedAt":"2026-11-06T23:33:08+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null}]}