Avoid Class.forName on Avro record names from untrusted writer schemas
- Dominant language
- Java
- Stars
- 9.2k
- Forks
- 3.5k
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 132
Description
> After review, this is not considered a serious vulnerability that needs to be kept private. It is the same class as #16469 (`Class.forName` / constructor load of a name already on the classpath; no new bytecode). Filed publicly as optional hardening.
# Summary
`GenericAvroReader` uses Avro record full names as Java class names (`Class.forName` with initialize true). If the class implements `IndexedRecord`, Iceberg then constructs it and populates fields. Those names come from schema JSON, including `AvroEncoderUtil.decode`, which embeds a writer schema in the blob (`0xC2 0x01` + schema string). Kafka Connect control-topic messages and `ManifestFiles.decode` use that decoder.
This is not an intended SPI (unlike `write.location-provider.impl` in #16469). Decode can use `GenericData.Record` or the allowlist already used on encode (`org.apache.iceberg.connect.events.AvroUtil.FIELD_ID_TO_CLASS`) instead of loading arbitrary classpath names.
# Affected Maven coordinates
* primary shipped client artifact: `org.apache.iceberg:iceberg-core`
* also: `org.apache.iceberg:iceberg-kafka-connect` (control events via `AvroEncoderUtil`)
# Attacker prerequisites
* ability to supply Avro schema JSON that Iceberg will parse with `GenericAvroReader` (e.g. produce to a Kafka Connect control topic, or an Avro file the process will read)
* a gadget class already on that process classpath with a dangerous static initializer, or an `IndexedRecord` with a dangerous constructor
# Impact
* Triggers class initialization (and, for `IndexedRecord`, construction) of an already-loaded classpath type
* Does not load new bytecode from the network
* Practical severity matches #16469 unless a suitable gadget is present
# Proof status
Source review only. The issue is visible directly from source.
# Key source references
* `org.apache.iceberg.avro.GenericAvroReader` (`recordReader`, `DynClasses`)
* `org.apache.iceberg.avro.AvroEncoderUtil` (`decode`)
* `org.apache.iceberg.connect.events.AvroUtil`
# Related
* #16469 — metadata-driven class names (`LocationProviders`, catalog impl properties); closed as not a vulnerability
Contributor guide
Research direction
Start with org.apache.iceberg.avro.GenericAvroReader, especially recordReader and DynClasses, then trace org.apache.iceberg.avro.AvroEncoderUtil.decode and org.apache.iceberg.connect.events.AvroUtil. Check how Kafka Connect control events and ManifestFiles.decode consume writer schemas. Done means decoding no longer initializes or constructs arbitrary classes named by untrusted schemas while supported record decoding remains intact.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, kafka
- Domain
- security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100