Skip to content

Security: fix Javadoc injection in li-avro-codegen and class instantiation bypass in fast-serde - #604

Merged
leiykpt merged 3 commits into
linkedin:masterfrom
SrilakshmiBharadwaj:fix/cve-security-patches
Jul 14, 2026
Merged

Security: fix Javadoc injection in li-avro-codegen and class instantiation bypass in fast-serde#604
leiykpt merged 3 commits into
linkedin:masterfrom
SrilakshmiBharadwaj:fix/cve-security-patches

Conversation

@SrilakshmiBharadwaj

@SrilakshmiBharadwaj SrilakshmiBharadwaj commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR is a prerequisite for LinkedIn's Avro 1.10.2 CVE fork patch work. Before rolling out the patched Avro fork (org.apache.avro:avro:1.10.2-li-N) to ~600 internal multiproducts, these two gaps in avro-util must be closed — otherwise the core CVE fixes in Avro are incomplete: fast-serde and li-avro-codegen carry their own vulnerable logic that bypasses the protections added to Avro core.

Closes two security gaps in avro-util that bypass CVE fixes shipped in Apache Avro core:

1. li-avro-codegen — Javadoc injection (CVE-2024-47561 analog)

File: avro-codegen/src/main/java/com/linkedin/avroutil1/codegen/SpecificRecordClassGenerator.java

Avro's SpecificCompiler (Velocity-based) escapes schema doc strings before embedding them in generated code to fix CVE-2024-47561. li-avro-codegen uses JavaPoet instead of Velocity but had the same gap: schema doc strings were added to Javadoc blocks without sanitization.

Attack vector: A malicious schema with "doc": "something */ public class Evil { static { Runtime.exec(...); } } //" would close the Javadoc block comment early and inject arbitrary Java code into the generated source.

Fix: Add sanitizeDocForJavadoc() that applies two escaping steps:

  • $$$ — prevents JavaPoet from treating the string as a format specifier
  • */* / — prevents premature Javadoc block comment termination

Applied uniformly to enum, fixed, record, and field doc strings. Previously enum and fixed had zero escaping; record and field only escaped $.


2. fast-serde — Class instantiation bypass (CVE-2023-39410 analog)

Files: fastserde/avro-fastserde/src/main/java/com/linkedin/avro/fastserde/SchemaAssistant.java, FastSerdeBase.java

Avro core fixed CVE-2023-39410 by adding a SERIALIZABLE_CLASSES allowlist to SpecificData.newInstance(). fast-serde bypasses this entirely: it generates Janino/javac source code that directly instantiates classes derived from schema fullName fields, never going through the allowlist check.

Attack vector: An attacker-controlled schema with "name": "com.malicious.RCEClass" causes fast-serde to generate code like new com.malicious.RCEClass(). If that class is on the classpath, it gets instantiated at deserialization time — no allowlist check applied.

Fix: Add validatedSpecificClassRef() in SchemaAssistant that loads the class referenced by getSchemaFullName(schema) and asserts it implements the expected Avro interface (SpecificRecord for RECORD, Enum for ENUM, SpecificFixed for FIXED) before emitting a codeModel.ref(). If the class is not found on the classloader (schema-evolution scenario), the check is skipped to preserve existing behaviour.

Thread classLoader from FastSerdeBase into SchemaAssistant; backward-compat no-arg constructor preserved.


Testing

  • ./gradlew :fastserde:avro-fastserde-tests111:test :avro-codegen:test — all tests pass
  • Both modules compile cleanly with no new warnings

Related

  • CVE-2023-39410 (Avro core fix: SERIALIZABLE_CLASSES in SpecificData)
  • CVE-2024-47561 (Avro core fix: escapeForJavadoc in SpecificCompiler)
  • LinkedIn Avro fork security project (Avro 1.10.2 CVE backports)

SrilakshmiBharadwaj and others added 3 commits February 28, 2025 14:14
…9410 bypass in fast-serde

li-avro-codegen (SpecificRecordClassGenerator):
- Add sanitizeDocForJavadoc() that escapes both JavaPoet format specifiers ($->$$)
  and Javadoc block-comment terminators (*/->'* /') before embedding schema doc strings
  in generated Javadoc. The '*/'-escaping closes the same injection vector that
  CVE-2024-47561 exploited in Avro's Velocity-based SpecificCompiler.
- Apply the new sanitizer to enum, fixed, record, and field doc strings uniformly.
  Previously enum and fixed docs had no escaping at all; record and field docs only
  escaped '$' but not '*/'.

fast-serde (SchemaAssistant):
- Add validatedSpecificClassRef() which, before emitting a codeModel.ref() from a
  schema full name, loads the class and asserts it implements the expected Avro
  interface (SpecificRecord for RECORD, Enum for ENUM, SpecificFixed for FIXED).
  This prevents an attacker-controlled schema from causing fast-serde to generate
  code that instantiates an arbitrary class on the classpath -- the path that
  bypassed the SERIALIZABLE_CLASSES allowlist added to Avro core for CVE-2023-39410.
- If the class is not found on the classloader (schema-evolution / compile-time
  absence), the check is skipped to preserve existing behaviour.
- Thread classLoader from FastSerdeBase into SchemaAssistant; add backward-compat
  no-classLoader constructor.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@SrilakshmiBharadwaj
SrilakshmiBharadwaj marked this pull request as ready for review July 14, 2026 17:43

@leiykpt leiykpt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@leiykpt
leiykpt merged commit 3ed1779 into linkedin:master Jul 14, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants