fix(java/feign): handle binary response types in ApiResponseDecoder#22939
Merged
wing328 merged 3 commits intoOpenAPITools:masterfrom Feb 11, 2026
Merged
Conversation
The Feign library's ApiResponseDecoder routes all responses through JacksonDecoder, including binary ones (File, byte[], InputStream). This causes JsonParseException when an endpoint returns non-JSON content (e.g. PDF, ZIP, images). Add binary type detection and handling before delegating to JacksonDecoder. This applies to both direct return types and ApiResponse<T> wrappers. Consistent with the native library fix in OpenAPITools#21346. Closes OpenAPITools#2486 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
9 issues found across 4 files
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="modules/openapi-generator/src/main/resources/Java/libraries/feign/ApiResponseDecoder.mustache">
<violation number="1" location="modules/openapi-generator/src/main/resources/Java/libraries/feign/ApiResponseDecoder.mustache:62">
P2: NullPointerException risk: decodeBinary calls response.body().asInputStream() without guarding against null bodies (e.g., 204/205 responses return null body in Feign).</violation>
<violation number="2" location="modules/openapi-generator/src/main/resources/Java/libraries/feign/ApiResponseDecoder.mustache:75">
P1: Unvalidated filename from Content-Disposition is resolved directly, allowing path traversal/absolute paths to create files outside the temp directory</violation>
</file>
<file name="samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/ApiResponseDecoder.java">
<violation number="1" location="samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/ApiResponseDecoder.java:86">
P2: Untrusted filename from Content-Disposition is used directly in tempDir.resolve(...), allowing path traversal to create files outside the intended temp directory.</violation>
</file>
<file name="samples/client/petstore/java/feign-hc5/src/main/java/org/openapitools/client/ApiResponseDecoder.java">
<violation number="1" location="samples/client/petstore/java/feign-hc5/src/main/java/org/openapitools/client/ApiResponseDecoder.java:39">
P2: Filename regex excludes whitespace, causing Content-Disposition filenames containing spaces to be truncated or not captured.</violation>
<violation number="2" location="samples/client/petstore/java/feign-hc5/src/main/java/org/openapitools/client/ApiResponseDecoder.java:73">
P2: NullPointerException risk: decodeBinary dereferences response.body() without null check; Feign returns null body for 204 responses.</violation>
<violation number="3" location="samples/client/petstore/java/feign-hc5/src/main/java/org/openapitools/client/ApiResponseDecoder.java:86">
P1: Unsanitized Content-Disposition filename allows path traversal when resolving tempDir; a filename like "../evil.sh" can escape the temp directory and create arbitrary files.</violation>
</file>
<file name="samples/client/petstore/java/feign/src/main/java/org/openapitools/client/ApiResponseDecoder.java">
<violation number="1" location="samples/client/petstore/java/feign/src/main/java/org/openapitools/client/ApiResponseDecoder.java:39">
P2: Filename extraction regex disallows spaces, truncating filenames like `"my invoice.pdf"` to `"my"` when parsing Content-Disposition.</violation>
<violation number="2" location="samples/client/petstore/java/feign/src/main/java/org/openapitools/client/ApiResponseDecoder.java:73">
P2: Binary decoder dereferences a potentially null response body, causing NPE on empty responses.</violation>
<violation number="3" location="samples/client/petstore/java/feign/src/main/java/org/openapitools/client/ApiResponseDecoder.java:86">
P1: Untrusted filename from Content-Disposition is resolved directly, allowing path traversal and arbitrary file write outside the temp directory.</violation>
</file>
Since this is your first cubic review, here's how it works:
- cubic automatically reviews your code and comments on bugs and improvements
- Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
- Add one-off context when rerunning by tagging
@cubic-dev-aiwith guidance or docs links (includingllms.txt) - Ask questions if you need clarification on any suggestion
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
modules/openapi-generator/src/main/resources/Java/libraries/feign/ApiResponseDecoder.mustache
Outdated
Show resolved
Hide resolved
...client/petstore/java/feign-hc5/src/main/java/org/openapitools/client/ApiResponseDecoder.java
Outdated
Show resolved
Hide resolved
...les/client/petstore/java/feign/src/main/java/org/openapitools/client/ApiResponseDecoder.java
Outdated
Show resolved
Hide resolved
modules/openapi-generator/src/main/resources/Java/libraries/feign/ApiResponseDecoder.mustache
Show resolved
Hide resolved
...etstore/java/feign-no-nullable/src/main/java/org/openapitools/client/ApiResponseDecoder.java
Outdated
Show resolved
Hide resolved
...client/petstore/java/feign-hc5/src/main/java/org/openapitools/client/ApiResponseDecoder.java
Outdated
Show resolved
Hide resolved
...client/petstore/java/feign-hc5/src/main/java/org/openapitools/client/ApiResponseDecoder.java
Show resolved
Hide resolved
...les/client/petstore/java/feign/src/main/java/org/openapitools/client/ApiResponseDecoder.java
Show resolved
Hide resolved
...les/client/petstore/java/feign/src/main/java/org/openapitools/client/ApiResponseDecoder.java
Outdated
Show resolved
Hide resolved
- Sanitize Content-Disposition filename to prevent path traversal (Paths.get(filename).getFileName() strips directory components) - Add null check for response.body() to handle 204/205 empty responses - Fix regex to support quoted filenames with spaces (e.g. filename="my invoice.pdf")
The feign-hc5 sample was missed during the second commit's regeneration
because setTemplateDir("feign") overrides the filesystem templateDir
from the config, causing the generator to use embedded JAR resources.
After rebuilding the JAR with the updated mustache template, the
feign-hc5 sample now matches feign and feign-no-nullable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Member
|
thanks for the PR, which has been merged. a minor suggestion is to add docstrings for newly-added functions so as to make the code more readable for humans/AI coding agent. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
The Feign library's
ApiResponseDecoderroutes all responses throughJacksonDecoder, including binary ones (File,byte[],InputStream). This causesJsonParseExceptionwhen an endpoint returns non-JSON content (e.g. PDF, ZIP, images):(
%is the first byte of%PDF-1.4)This is the Feign equivalent of the issue fixed for the
nativelibrary in #21346.Changes
Modified
ApiResponseDecoder.mustacheto detect binary return types before delegating toJacksonDecoder:File→ stream response body to a temp file (filename extracted fromContent-Dispositionheader when available, consistent with native library'sprepareDownloadFile)byte[]→response.body().asInputStream().readAllBytes()InputStream→response.body().asInputStream()(no transformation — the caller chose this type intentionally)This applies to both direct return types and
ApiResponse<T>wrappers. TheApiResponse<File>case was also broken becauseApiResponseDecoderunwraps the inner type and callssuper.decode()(JacksonDecoder), bypassing any subclass override due to Java's static dispatch.Non-binary responses are completely unaffected — they follow the existing
JacksonDecoderpath.Design decisions
Content-Dispositionparsing,deleteOnExit()ApiResponseDecoderRelated issues
application/octet-stream#17801 (native client incorrect generation for application/octet-stream)How to reproduce
type: string, format: binary(e.g. PDF download)library=feignJsonParseExceptionon first byte of binary contentHow tested
Tested against a real API returning
application/pdfresponses. Verified that:Filereturn type works (PDF streamed to temp file)byte[]return type worksPR checklist
generate-samples.shfor alljava-feign*configs. Committed all changed filesmasterbranch@bbdouglas @sreeshas @jfiala @lukoyanov @cbornet @jeff9finger @karismann @Zomzog @lwlee2608 @martin-mfg
Summary by cubic
Fixes Feign ApiResponseDecoder to handle binary responses (File, byte[], InputStream) without Jackson, avoiding JsonParseException on PDFs, ZIPs, and images. Adds safer filename parsing and path sanitization, and handles empty bodies; JSON decoding is unchanged.
Written for commit cb7ed8e. Summary will update on new commits.