apache / apache/iceberg

Avoid Class.forName on Avro record names from untrusted writer schemas

Open
#17,802 6 comments 0 reactions 0 assignees View on GitHub
Security
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.