Skip to content

Core: Restrict GenericAvroReader class resolution to an explicit allowlist - #17852

Open
damansingh1313 wants to merge 1 commit into
apache:mainfrom
damansingh1313:fix/gh-17802-avro-record-class-allowlist
Open

Core: Restrict GenericAvroReader class resolution to an explicit allowlist#17852
damansingh1313 wants to merge 1 commit into
apache:mainfrom
damansingh1313:fix/gh-17802-avro-record-class-allowlist

Conversation

@damansingh1313

Copy link
Copy Markdown

GenericAvroReader.recordReader used an Avro schema's record name directly as a Java class name, loading and constructing it via reflection with no restriction. Two production paths feed this untrusted bytes/schemas: ManifestFiles.decode and Kafka Connect's AvroUtil.decode. If a schema named a class that happened to already be on the classpath and implement IndexedRecord, that class would be constructed regardless of whether it was ever intended to be reconstructed this way.

This adds a hardcoded allowlist (ALLOWED_RECORD_CLASSES) inside GenericAvroReader and only attempts class resolution for names on that list; anything else now falls back to the existing generic record reader. Kafka Connect's classes are listed by name rather than Class literal since iceberg-core cannot depend on iceberg-kafka-connect-events; a comment cross-references that module's FIELD_ID_TO_CLASS to keep the two from drifting apart.

This keeps the change self-contained to GenericAvroReader, with no changes to AvroEncoderUtil, ManifestFiles, or AvroUtil's method signatures or call sites.

Closes #17802

…wlist

GenericAvroReader.recordReader used an Avro schema's record name directly
as a Java class name, loading and constructing it via reflection with no
restriction. Two production paths feed this untrusted bytes/schemas:
ManifestFiles.decode and Kafka Connect's AvroUtil.decode. If a schema
named a class that happened to already be on the classpath and implement
IndexedRecord, that class would be constructed regardless of whether it
was ever intended to be reconstructed this way.

This adds a hardcoded allowlist (ALLOWED_RECORD_CLASSES) inside
GenericAvroReader and only attempts class resolution for names on that
list; anything else now falls back to the existing generic record
reader. Kafka Connect's classes are listed by name rather than Class
literal since iceberg-core cannot depend on iceberg-kafka-connect-events;
a comment cross-references that module's FIELD_ID_TO_CLASS to keep the
two from drifting apart.

This keeps the change self-contained to GenericAvroReader, with no
changes to AvroEncoderUtil, ManifestFiles, or AvroUtil's method
signatures or call sites.

AI assistance disclosure: Claude Code was used to research the
vulnerable code paths, draft this fix and its tests, and verify the
build/test suite locally, per the project's AI-assisted contribution
guidelines. The design (hardcoded allowlist inside the reader, no new
parameters) was proposed after discussion with a maintainer on the
issue; the approach and all code were reviewed and understood before
submission.

Closes apache#17802
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

1 participant