Introduction
A logic gap in Apache Polaris's storage location validation lets a user with table settings privileges redirect metadata writes to an arbitrary storage location and then receive temporary cloud storage credentials scoped to that location. For organizations running multi-tenant data lakehouses on shared cloud storage, this CVSS 9.9 vulnerability turns a routine ALTER TABLE property change into a path to cross-table or cross-bucket data exposure and corruption.
Apache Polaris is an open-source metadata and catalog service purpose-built for Apache Iceberg tables in data lakehouse architectures. It was donated to the Apache Software Foundation as an incubating project and recently graduated to top-level Apache status. Organizations use it as the catalog layer for large-scale analytical data across cloud storage. Polaris also handles credential vending and storage access control, so flaws in its validation logic are especially serious.
Technical Information
Root Cause: Missing Property in Location Change Detection
In Apache Iceberg, metadata files are control files that tell readers which data files belong to a table and which table version to read. The write.metadata.path property is an optional table setting that tells Polaris where to write those metadata files.
The vulnerability is in the doCommit() method of IcebergCatalog.java. This method has a conditional branch that decides whether the requested table locations have changed. When it detects a change, Polaris runs a set of validations: location allowlist checks, overlap checks, and metadata-file-in-table-directory checks. The old code compared only two values to decide whether locations had changed:
- The table's base
location() - The
USER_SPECIFIED_WRITE_DATA_LOCATION_KEYproperty
It did not check whether USER_SPECIFIED_WRITE_METADATA_LOCATION_KEY (write.metadata.path) had changed. Because this property was missing from the comparison, changing it through an ALTER TABLE-style settings change skipped the entire validation branch. Polaris would then write new table metadata to the attacker-specified location before any location validation ran.
A second issue made this worse. loadFileIOForTableLike(), which refreshes storage credentials, ran before the location validation checks, so Polaris would issue storage credentials for potentially malicious locations before it had evaluated them.
Attack Flow
Exploitation proceeds in these steps:
-
The attacker finds a Polaris-managed catalog where they have permission to change table settings through an ALTER TABLE-style operation. They need no row-level INSERT, SELECT, UPDATE, or DELETE permissions.
-
The attacker issues a property change that sets
write.metadata.pathto a storage location they want to access. This could be another table's prefix, a broader storage prefix, or even a bucket root. -
Because
doCommit()does not includewrite.metadata.pathin its location change detection, Polaris skips the entire validation branch. It writes new table metadata to the attacker-specified location without checking it against the allowlist or running overlap validation. -
If the catalog is configured with
polaris.config.allow.unstructured.table.location=trueandallowedLocationsis broad enough to include the attacker's target, the laterupdateTableLike(...)validation also accepts the location. Polaris persists the resulting poisoned metadata path into stored table state. -
From then on, table load and credential APIs vend temporary cloud storage credentials for the attacker-chosen location without revalidating it. The attacker can read, and potentially write to, any data and metadata Polaris can reach at that storage prefix.
Configuration-Dependent Impact
Severity depends on catalog configuration:
| Configuration State | Risk Level |
|---|---|
allow.unstructured.table.location=true with broad allowedLocations | Critical. Polaris persists the attacker-chosen path and vends credentials for it. |
allow.unstructured.table.location=true with narrow allowedLocations | Reduced. The attacker-chosen target must fall within the restricted allowlist. |
allow.unstructured.table.location=false | Moderate. Polaris still skips the pre-write check and writes the metadata, but later validation usually rejects persistence. |
Public project materials confirm that polaris.config.allow.unstructured.table.location=true is a real, supported compatibility and layout mode, so this prerequisite is realistic outside a lab.
Scope of Exposure
The attacker-chosen area is not limited to the poisoned table's own files. If it is a broader storage prefix, another table's prefix, or even a bucket or container root, the disclosure or corruption extends to any data and metadata Polaris can reach there. Polaris itself writes the metadata to the unchecked location before any credentials are vended. The core defect is therefore the skipped pre-write location check, which does damage even without the later credential issuance.
Patch Information
Apache Polaris 1.4.1 ships the fix for CVE-2026-42812. It arrived in pull request #4330 ("Improve locations handling"), authored by Robert Stupp and merged on May 1, 2026 into the release/1.4.x branch. The merge commit is d6bbcc3. It touched two files, the core catalog implementation and its test suite, with 144 additions and 30 deletions.
The patch makes five tightly coupled changes.
1. New requestedTableLocationsChanged() Method
The patch extracts the sprawling inline comparison into a dedicated helper that checks three properties instead of two:
private boolean requestedTableLocationsChanged(TableMetadata base, TableMetadata metadata) { return !metadata.location().equals(base.location()) || !Objects.equal( base.properties().get(IcebergTableLikeEntity.USER_SPECIFIED_WRITE_DATA_LOCATION_KEY), metadata.properties().get(IcebergTableLikeEntity.USER_SPECIFIED_WRITE_DATA_LOCATION_KEY)) || !Objects.equal( base.properties().get(IcebergTableLikeEntity.USER_SPECIFIED_WRITE_METADATA_LOCATION_KEY), metadata.properties().get(IcebergTableLikeEntity.USER_SPECIFIED_WRITE_METADATA_LOCATION_KEY)); }
The new USER_SPECIFIED_WRITE_METADATA_LOCATION_KEY comparison is the core of the fix. Changes to write.metadata.path now trigger the full location validation branch, the same checks as any other storage path change, which closes the bypass.
2. Credential Refresh Moved After Validation
Before the patch, loadFileIOForTableLike(), which refreshes storage credentials, ran before the location validation checks. The patch reorders the flow so loadFileIOForTableLike() now runs only after all location validations pass. As a defense-in-depth change, this means Polaris never vends credentials for an unapproved path.
3. Unconditional Metadata File Location Validation
The old code ran validateMetadataFileInTableDir() only when metadata.metadataFileLocation() != null, so the check never ran when that value was null. The patch adds a nextMetadataFileLocation() helper:
private String nextMetadataFileLocation(TableMetadata metadata) { return metadata.metadataFileLocation() != null ? metadata.metadataFileLocation() : metadataFileLocation(metadata, "metadata.json"); }
The helper always computes the next metadata file path, even when no explicit metadata file location has been set yet. The validation call therefore always runs with a concrete path, and the null-based skip is gone.
4. Refactored Validation Overload
A new overload of validateMetadataFileInTableDir() accepts explicit tableLocation and metadataLocation strings instead of extracting them from a TableMetadata object. The method can now validate the prospective write target, not only the currently stored value, which makes it more useful for pre-write validation.
5. Test Coverage
The patch adds two tests to AbstractIcebergCatalogTest.java:
testUpdatePropertiesRejectsOutOfTableWriteMetadataLocation()verifies that settingWRITE_METADATA_LOCATIONto a path outside the table directory is rejected with aBadRequestExceptionand that no metadata files are written to the attacker-chosen location.testUpdatePropertiesAcceptsInTableWriteMetadataLocation()confirms that settingWRITE_METADATA_LOCATIONto a path within the table's own directory structure succeeds, that the metadata file is written to the correct location, and that the property is persisted.
Affected Systems and Versions
Apache Polaris versions prior to 1.4.1 are affected. The vulnerability is present in any deployment where users have permission to modify table properties.
Severity and exploitability depend on catalog configuration:
- Deployments with
polaris.config.allow.unstructured.table.location=trueand broadallowedLocationsare at the highest risk, because the full variant, with path persistence and credential vending, is exploitable. - Deployments with
polaris.config.allow.unstructured.table.location=falsestill contain the underlying defect (the skipped pre-write location check), but the laterupdateTableLike(...)validation usually prevents Polaris from persisting out-of-tree metadata locations.
Organizations should upgrade to Apache Polaris 1.4.1. It is available from the official Polaris downloads page, Maven Central under the org.apache.polaris group, and Docker Hub under the apache/polaris and apache/polaris admin tool tags.
Vendor Security History
Apache Polaris 1.4.1 fixes four distinct security vulnerabilities. Together they point to a broader pattern of storage access control and credential scoping weaknesses in the platform:
| CVE Identifier | Description |
|---|---|
| CVE-2026-42809 | Authenticated low-privileged users can abuse staged table creation to mint broad temporary storage credentials for an attacker-chosen location. |
| CVE-2026-42810 | Polaris accepts literal star characters in namespace and table names, and reuses them unescaped in S3 IAM resource patterns and prefix conditions. |
| CVE-2026-42811 | Crafted namespace or table names can make short-lived GCS credentials work across the entire configured bucket instead of a single table. |
| CVE-2026-42812 | Missing protection on write.metadata.path leads to a metadata write bypass and credential vending. |
Four such issues in a single release show that the credential vending and storage location validation subsystems had not had a thorough adversarial review before this cycle. The fast turnaround on the 1.4.1 release does reflect a responsive security posture in the Apache Polaris community.
References
- NVD: CVE-2026-42812
- Apache Mailing List Advisory: CVE-2026-42812
- OpenWall OSS Security Notice
- Apache Polaris 1.4.1 Release Announcement
- GitHub Pull Request #4330: Improve locations handling
- Merge Commit d6bbcc3
- What is Apache Polaris? Unifying the Iceberg Ecosystem
- The Impact of Apache Polaris Graduating to Top Level Apache Project
- The Release of Apache Polaris 1.3.0 (Incubating)



