Commit e015939
Fix code injection via unsanitized names in openapi-codegen (GHSA-gpcc-36pq-8qxr) (#5395)
## Summary
The OpenAPI code generator (`tapir-openapi-codegen-core`, used by the
sbt plugin and CLI) builds Scala source by string interpolation and
emitted many names/values taken from the **input OpenAPI document**
without encoding them. Because that document may be attacker-controlled
(e.g. generating a client from a third-party spec), a crafted document
could inject arbitrary Scala into the generated source — for example a
property name turned into a case-class field with a code-running default
(code execution at model construction / JSON decoding time), or a
query-parameter name breaking out of its string literal.
This is a **build/codegen-time** issue: it affects anyone generating
code from an untrusted OpenAPI document. It is not exploitable against a
running tapir server.
Reported privately as **GHSA-gpcc-36pq-8qxr** (credit: @Gal3m,
@mrostamipoor).
## Fix
Two encoding disciplines, applied consistently across the generator:
- **Identifier positions — reject unsafe names.** `safeVariableName` and
a shared enum-member helper now reject backticks and control characters
(a backtick-quoted Scala identifier cannot contain either, so these
previously allowed a break-out). A new `NameValidation` pass rejects, at
ingestion, schema names, `$ref` targets, object property names, and
(when used for object names) tags that fall outside the
OpenAPI-permitted `[A-Za-z0-9._-]` character set.
- **String-literal positions — escape values.** Parameter/path/XML
names, descriptions, discriminator property names and mapping values,
default values, spec-extension values, OAuth URLs, apiKey names and
media-type strings are now escaped via `JavaEscape.escapeString` (Circe,
Zio and Jsoniter serde generators).
- **Special cases.** `param.in` and apiKey `in` are validated against
the allowed locations (emitted as raw method names); server URLs are
validated (they feed both an identifier and a `uri"..."` interpolator);
and a `*/` in a server description can no longer close the emitted block
comment early.
Values that legitimately contain special characters (URLs, descriptions,
wire-level parameter names) are escaped rather than rejected, so valid
specifications continue to generate.
## Tests
Adds `InjectionSecuritySpec` covering the reported and adjacent vectors
(schema-name, property-name and enum-value rejection; parameter-name
escaping; `in`-location rejection). Full codegen-core suites pass on
Scala 2.12 (81) and Scala 3 (87) with no regressions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: hughsimpson <hsimpson@rzsoftware.com>1 parent c2caf57 commit e015939
24 files changed
Lines changed: 700 additions & 89 deletions
File tree
- openapi-codegen/core/src
- main/scala/sttp/tapir/codegen
- endpoints
- json
- openapi/models
- security
- util
- validation
- xml
- test/scala/sttp/tapir/codegen
Lines changed: 3 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
| 12 | + | |
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| |||
87 | 87 | | |
88 | 88 | | |
89 | 89 | | |
| 90 | + | |
90 | 91 | | |
91 | 92 | | |
92 | 93 | | |
| |||
463 | 464 | | |
464 | 465 | | |
465 | 466 | | |
466 | | - | |
| 467 | + | |
467 | 468 | | |
468 | 469 | | |
469 | 470 | | |
| |||
Lines changed: 6 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
10 | 11 | | |
| 12 | + | |
11 | 13 | | |
12 | 14 | | |
13 | 15 | | |
| |||
37 | 39 | | |
38 | 40 | | |
39 | 41 | | |
| 42 | + | |
40 | 43 | | |
41 | 44 | | |
42 | 45 | | |
| |||
253 | 256 | | |
254 | 257 | | |
255 | 258 | | |
256 | | - | |
257 | | - | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
258 | 262 | | |
259 | 263 | | |
260 | 264 | | |
| |||
Lines changed: 4 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| 9 | + | |
9 | 10 | | |
10 | 11 | | |
11 | 12 | | |
| |||
334 | 335 | | |
335 | 336 | | |
336 | 337 | | |
337 | | - | |
| 338 | + | |
| 339 | + | |
338 | 340 | | |
339 | 341 | | |
340 | 342 | | |
341 | 343 | | |
342 | 344 | | |
343 | 345 | | |
344 | | - | |
| 346 | + | |
345 | 347 | | |
346 | 348 | | |
347 | 349 | | |
| |||
Lines changed: 19 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
8 | 9 | | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
9 | 19 | | |
10 | 20 | | |
11 | 21 | | |
| |||
20 | 30 | | |
21 | 31 | | |
22 | 32 | | |
| 33 | + | |
23 | 34 | | |
24 | 35 | | |
25 | 36 | | |
| |||
31 | 42 | | |
32 | 43 | | |
33 | 44 | | |
34 | | - | |
| 45 | + | |
35 | 46 | | |
36 | 47 | | |
37 | 48 | | |
| |||
79 | 90 | | |
80 | 91 | | |
81 | 92 | | |
82 | | - | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
83 | 100 | | |
84 | 101 | | |
Lines changed: 3 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
308 | 308 | | |
309 | 309 | | |
310 | 310 | | |
311 | | - | |
312 | | - | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
313 | 314 | | |
314 | 315 | | |
315 | 316 | | |
| |||
Lines changed: 4 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
3 | 4 | | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
8 | | - | |
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
24 | 23 | | |
25 | 24 | | |
26 | 25 | | |
| |||
Lines changed: 9 additions & 8 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | | - | |
| 27 | + | |
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| |||
170 | 170 | | |
171 | 171 | | |
172 | 172 | | |
173 | | - | |
174 | | - | |
175 | | - | |
176 | | - | |
177 | | - | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
178 | 177 | | |
179 | 178 | | |
180 | 179 | | |
| |||
193 | 192 | | |
194 | 193 | | |
195 | 194 | | |
196 | | - | |
| 195 | + | |
197 | 196 | | |
198 | 197 | | |
199 | 198 | | |
| |||
236 | 235 | | |
237 | 236 | | |
238 | 237 | | |
239 | | - | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
240 | 241 | | |
241 | 242 | | |
242 | 243 | | |
| |||
Lines changed: 7 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
142 | 142 | | |
143 | 143 | | |
144 | 144 | | |
145 | | - | |
| 145 | + | |
| 146 | + | |
146 | 147 | | |
147 | 148 | | |
148 | 149 | | |
| |||
152 | 153 | | |
153 | 154 | | |
154 | 155 | | |
155 | | - | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
156 | 159 | | |
157 | 160 | | |
158 | 161 | | |
| |||
179 | 182 | | |
180 | 183 | | |
181 | 184 | | |
182 | | - | |
183 | | - | |
| 185 | + | |
| 186 | + | |
184 | 187 | | |
185 | 188 | | |
186 | 189 | | |
| |||
Lines changed: 17 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
14 | 24 | | |
15 | 25 | | |
16 | 26 | | |
| |||
26 | 36 | | |
27 | 37 | | |
28 | 38 | | |
| 39 | + | |
29 | 40 | | |
30 | 41 | | |
31 | 42 | | |
| |||
51 | 62 | | |
52 | 63 | | |
53 | 64 | | |
54 | | - | |
| 65 | + | |
55 | 66 | | |
56 | 67 | | |
57 | 68 | | |
| |||
62 | 73 | | |
63 | 74 | | |
64 | 75 | | |
65 | | - | |
| 76 | + | |
| 77 | + | |
66 | 78 | | |
67 | 79 | | |
68 | 80 | | |
69 | 81 | | |
70 | 82 | | |
71 | 83 | | |
72 | 84 | | |
73 | | - | |
| 85 | + | |
74 | 86 | | |
75 | 87 | | |
76 | 88 | | |
| |||
84 | 96 | | |
85 | 97 | | |
86 | 98 | | |
87 | | - | |
| 99 | + | |
88 | 100 | | |
89 | 101 | | |
90 | 102 | | |
| |||
95 | 107 | | |
96 | 108 | | |
97 | 109 | | |
| 110 | + | |
98 | 111 | | |
Lines changed: 8 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
| |||
35 | 36 | | |
36 | 37 | | |
37 | 38 | | |
38 | | - | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
39 | 46 | | |
40 | 47 | | |
41 | 48 | | |
| |||
0 commit comments