v0.6.0 Alpha Security release

An Open Iceberg REST Catalog in Rust

Pangolin is an MIT-licensed lakehouse catalog written in Rust. It implements the core of the Apache Iceberg REST specification and adds multi-tenancy, Git-style branching and merging, catalog federation, credential vending and a business metadata layer.

Pangolin is alpha software. 0.6.0 is a security and correctness hardening release, and it closes a lot of real ground — but there are limitations we name plainly rather than bury. Read the production readiness status before you point anything important at it.

Passion project by Alex Merced. Contributions welcome.

Pangolin Dashboard Interface

⚠️ 0.6.0 is a security release — upgrade from anything earlier

If you are running 0.5.x or earlier, upgrade and rotate your credentials. 0.6.0 fixes issues that were exploitable in earlier builds:

  • OAuth account takeover (A-8). The callback appended the freshly minted session JWT to a redirect URL taken from the unsigned state parameter, with no allowlist. An authorize link could deliver a valid token for the victim straight to an attacker's access log. state is now HMAC-SHA256 signed with an expiry, redirect targets are allowlisted by exact match, and the token is no longer placed in a URL at all — the callback returns a single-use code redeemed at POST /api/v1/oauth/exchange.
  • OAuth login CSRF (A-9). The state nonce was generated and never stored or verified. Nonces are now registered server-side, consumed exactly once, and bound to the issuing provider.
  • A working default signing secret (A-10). PANGOLIN_JWT_SECRET fell back to a value published in the repository, so anyone could forge a Root token. The Helm chart shipped working placeholder passwords. All are gone; the server refuses to start without a strong secret.
  • Authentication bypass via path suffix (A-11). The whitelist matched any path ending in /config, so a namespace or table named config was reachable unauthenticated — including its DELETE route. Matching is now structural per route segment.
  • Unauthenticated denial of service (A-12). API-key auth ran bcrypt::verify against every service user in every tenant. Keys now carry a public key ID (pgl_<key-id>_<secret>), making authentication one lookup plus at most one verification.
  • Token revocation now fails closed (A-13) and credentials are compared in constant time (A-14).

Read the full advisory and hardening checklist in SECURITY.md →

Iceberg correctness fixes in the same release

  • Commit requirements are enforced (A-1). Only assert-current-schema-id and assert-table-uuid were implemented; the rest were discarded. The important one is assert-ref-snapshot-id — without it, a writer that lost a compare-and-swap would retry against the winner's metadata and blindly re-apply its own snapshot, producing forked snapshot lineage and orphaned data files with no error ever surfaced.
  • Commit updates are applied or refused, never silently dropped (A-2). Eleven update types were discarded while the handler returned 200 OK. All are implemented; an unrecognised update now returns 501.
  • last_sequence_number is a monotonic counter again (A-3). It was being assigned the snapshot ID, a random 64-bit value — which can produce incorrect query results on merge-on-read tables.
  • GET /v1/{prefix}/config returns per-warehouse configuration (A-4) instead of process-wide environment defaults, and no longer exposes credential-bearing warehouse properties.
  • Errors on /v1/* use the Iceberg error envelope (A-6), so engines can tell NoSuchTableException from CommitFailedException and retry correctly.

Breaking changes you need to action

  • PANGOLIN_JWT_SECRET is required. Generate one with openssl rand -base64 48. Setting it ends every existing session, which is intended.
  • OAuth clients must move to the code-exchange flow, and redirect targets must be allowlisted via PANGOLIN_OAUTH_REDIRECT_URIS.
  • Service-user API keys should be rotated. Legacy keys work only with PANGOLIN_ALLOW_LEGACY_API_KEYS=true.
  • Seeding an admin requires PANGOLIN_ADMIN_PASSWORD; there is no default. POST /api/v1/users/login no longer has default root credentials.
  • Health probes should move to /health/live and /health/ready.
  • Unsupported Iceberg commit operations now return 501 where they previously returned 200 OK and did nothing — a client that appeared to work may now surface a real error.

Full 0.6.0 changelog →

What Pangolin Does

🧊

Iceberg REST Catalog

Implements the core of the Iceberg REST spec — namespace and table CRUD, commits with full requirement enforcement, and credential vending. Not the whole spec yet; see the coverage list.

🚀

Written in Rust

A single static binary with a low resource footprint and no runtime to install. unsafe_code = "forbid" across the workspace. No published benchmark figures yet.

🔒

Multi-Tenancy

Tenant scope is a required parameter throughout. Isolation is verified by tests running against the production auth middleware, not a test-only wrapper.

🌿

Git-Like Branching

Branch, tag and merge catalogs for safe experimentation, with 3-way merge and conflict detection. Merge direction and branch-asset tracking were fixed in 0.6.0.

☁️

Multi-Cloud Storage

Native support for AWS S3, Azure Blob Storage and Google Cloud Storage, configured per warehouse rather than per process.

🔑

Credential Vending

Vends scoped, temporary credentials to compute engines — AWS STS, Azure SAS and GCP downscoped tokens — so engines never hold long-lived keys.

💾

Pluggable Backends

PostgreSQL (recommended), SQLite, MongoDB (beta) or in-memory. Feature parity varies by backend.

🛡️

RBAC & Service Users

Role- and tag-based access control, plus API-key service users for CI/CD and ETL. Keys carry a key ID, so authentication is a single bcrypt verification.

📋

Audit Logging

40+ actions across 19 resource types, plus authentication events from 0.6.0. Writes are best-effort and records are not yet tamper-evident.

📈

Observability

New in 0.6.0 Prometheus metrics at /metrics, request correlation IDs, a working RUST_LOG, JSON logs, and real liveness/readiness endpoints.

🔗

Federated Catalogs

Connect external Iceberg REST catalogs and proxy them transparently, so one endpoint fronts several sources.

🖥️

UI, CLIs and Python SDK

A SvelteKit management UI, pangolin-admin and pangolin-user CLIs, and the PyPangolin client on PyPI — all versioned together at 0.6.0.

Where Pangolin Actually Stands

The honest version. Pangolin is pre-1.0 software under active hardening — a capable catalog that we would not yet tell you to put in front of a production data lake without reading this.

✅ Ready to rely on today

  • Iceberg table commits. Compare-and-swap with every commit requirement enforced, including assert-ref-snapshot-id. This is the one path that is genuinely safe under concurrent writers.
  • Tenant isolation. Enforced throughout and tested against the production middleware.
  • PostgreSQL as the metadata backend. The recommended choice; fresh-database provisioning was repaired in 0.6.0.
  • Authentication and RBAC. No default secrets, no default credentials, constant-time comparison, fail-closed revocation.
  • Operating the thing. Prometheus metrics, structured logs, request IDs, real health probes, graceful shutdown, request limits.
  • Kubernetes deployment. A chart that renders — three referenced templates simply did not exist before 0.6.0 — with hardened pod defaults and CI linting.
  • A test suite that runs. 334 tests passing, with CI on every push and pull request — cargo test --workspace previously executed zero.

⏳ Not there yet

  • No rate limiting. There are global concurrency and body limits and a request timeout, but no per-IP or per-account throttle — the login endpoint is brute-forceable.
  • Admin operations are only partly transactional. PostgreSQL wraps catalog deletes, branch deletes and merges; branch creation by copy is still a sequence of independent statements. Take a backup first.
  • OAuth is not full OIDC. No PKCE, no id_token validation, no JWKS, no discovery, no email_verified check.
  • Warehouse cloud credentials are stored unencrypted in the catalog database. Envelope encryption at rest is not implemented.
  • Backup, restore and DR are undocumented and untested. There is no published RPO or RTO.
  • MongoDB is beta. No index management, no transactions, four known-failing tests.
  • Multiple replicas work but are unproven. Token cleanup runs uncoordinated in every replica and the OAuth nonce store is in-process.
  • Missing Iceberg endpoints. loadNamespaceMetadata, namespaceExists, registerTable, commitTransaction and most of the view API.

See the full maturity table →

Pangolin in Five Short Videos

Silent, 36–40 second explainers covering what Pangolin is, how it is built, what changed in 0.6.0, and how ready it really is.

Overview

What is Pangolin?

An open Iceberg REST catalog written in Rust — what it is, who it is for, and what it is not.

Architecture

Architecture & Features

One Rust binary, a pluggable metadata backend, multi-cloud warehouses, branching and credential vending.

Release

What's New in 0.6.0

The security release: OAuth takeover, default secrets, an auth bypass, a DoS primitive, and forked snapshot lineage — all fixed.

Status

Production Readiness

The maturity table without the marketing: what is solid, what is beta, and what is simply missing.

Deploy

Getting Started

From cargo run to Docker Compose to a Helm chart — and the four environment variables 0.6.0 now requires.

These videos have no audio track. Play them muted, on loop, or with the controls — whichever you prefer.

PyPangolin — Official Python Client

A Python library for Pangolin with PyIceberg integration, multi-format support and secure database connection management.
Available on PyPI: pip install pypangolin

🐍 Complete Python Integration

PyPangolin provides a Python interface to Pangolin's catalog, governance and Git-style operations, plus support for common table formats and database connections.

View on PyPI → Documentation →

Table Format Support

🧊

Apache Iceberg

PyIceberg integration with read/write operations

✅ Tested
🔺

Delta Lake

Read/write Delta tables with automatic registration

✅ Tested
🏛️

Apache Hudi

Register and manage Hudi tables

Supported
🎯

Apache Paimon

Register and track Paimon tables

Supported
📊

Parquet

Read/write Parquet files with metadata

✅ Tested
📄

CSV & JSON

Read/write structured files

✅ Tested
🎯

Lance

Read/write vector database format

✅ Tested
🌀

Vortex

High-performance columnar format

Supported

Database Connection Management

Store and manage database credentials with Fernet encryption

🐘

PostgreSQL

Encrypted credential storage

✅ Tested
🐬

MySQL

Secure connection sharing

✅ Tested
🍃

MongoDB

NoSQL database connections

✅ Tested
❄️

Snowflake

Cloud data warehouse

⚠️ Untested
🔴

Redshift

AWS data warehouse

⚠️ Untested
☁️

BigQuery

Google Cloud analytics

⚠️ Untested
🔷

Azure Synapse

Microsoft analytics service

⚠️ Untested

Dremio

Arrow Flight connections

✅ Tested

Additional Features

Governance & Security

RBAC, permissions, service users, and business metadata

Admin & System

Audit logging, search, token management, and system config

Federated Catalogs

Connect to remote Iceberg catalogs and create SQL views

Git Operations

Branching, merging, tagging with conflict resolution

Need Something Production-Proven Today?

Pangolin is alpha, and being honest about that means pointing you elsewhere when that is the right answer. If you need a catalog you can put in front of a production lakehouse right now, start with these.

Apache Polaris

The production-grade, community-run lakehouse catalog. Best for large-scale open source deployments.

Visit Polaris →

Dremio Cloud

A managed version of Polaris with a built-in semantic layer, federated queries, and AI-powered autonomous optimization.

Try Dremio Cloud →

Join the Community

Discuss Pangolin, Iceframe, and Dremioframe in the #pangolin-catalog channel on the Data Lakehouse Hub Slack.

Join Slack