Security
Running polign_db means running a closed-source binary inside your VPC with credentials to your bucket. This page is the checklist a security review will ask for: what the binary does on the network, how to verify a download, how access control works, how data is encrypted at rest, how it fits a confidential computing deployment, what the license says, and where to report a vulnerability.
What the binary does on the network
There is no telemetry. The binaries don't report usage, don't send crash dumps, don't
check licenses, and don't check for updates. The server's outbound traffic goes to the
object store you configured with -store (S3, GCS, Azure, or any
S3-compatible endpoint), plus AWS STS when cross-account role assumption is on. The
polign CLI and polign-apikey connect to whatever server address
you give them, localhost by default. That's the complete list.
The easiest way to check this claim is to enforce it: an egress policy that allows
only your object store and STS breaks nothing. Air-gapped deployments work for the same
reason, against an internal S3-compatible store or a plain fs:
directory.
Verify a download
Each release attaches a checksums.txt with the SHA-256 of every archive.
The install script already checks it before
unpacking. Downloading by hand, the same check is:
V=$(curl -fsSL https://dl.polign.com/latest/version)
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
curl -fsSLO "https://dl.polign.com/$V/polign_db_${OS}_${ARCH}.tar.gz"
curl -fsSLO "https://dl.polign.com/$V/checksums.txt"
grep "polign_db_${OS}_${ARCH}.tar.gz" checksums.txt | shasum -a 256 -c -
Archives aren't signed yet; the checksums and archives are published together on
GitHub releases and fetched over TLS, and signed releases are on the roadmap. Every
archive carries its LICENSE and CHANGELOG, so you can tell
later exactly what a host is running.
How access control works
polign_db is single-tenant: one deployment serves one application, and isolation
between customers means one instance per customer, not anything in-process. The data
plane (put, get, search, list,
delete) carries no credential on purpose, so anything that can reach the
data listeners can read and write every vector. Reachability is the access control. The
server binds 127.0.0.1 unless you tell it otherwise, and anything wider
belongs behind your gateway, mesh, or VPN, which is also where per-caller auth and rate
limiting live.
API keys guard the surfaces that act with the server's own cloud credentials: the
collection API, the management API at /v1/admin, and the admin UI's storage
probe. A key is plgn_<key_id>_<secret> with a 256-bit random
secret. Only the secret's SHA-256 is ever stored, so a leaked bucket listing yields no
usable credential; verification is a constant-time compare, and every auth failure
returns the same opaque error. The plgn_ prefix is there so secret scanners
recognise a leaked key.
When a collection is bound to your own bucket, the server never holds long-lived
credentials for it. Access goes through IAM role assumption with a server-minted
ExternalId as the confused-deputy guard, and the wiring is verified against
the bucket before the collection activates. The server's own -store bucket
is reached as the ambient identity (the instance or task role), so a normal deployment
has no static keys anywhere. The hardening details live in
Operate in production.
Known limitations
Written down here so they're chosen, not discovered:
- Rate limiting is one server-wide ceiling. There's no per-caller metering; a gateway provides fairness where it matters.
- Nothing bounds a caller's resident vectors or bucket bytes. There are no storage quotas.
- Keys have no scopes and no expiry. A key grants its whole API surface and lives until you disable it.
- TLS certificates load once at startup, so rotating them means a restart. mTLS is left to your mesh or proxy.
Encryption at rest
Every object store encrypts at rest if you ask it to (SSE-S3 and SSE-KMS on AWS, the equivalents on GCS and Azure). That encryption is done by the storage service: it decrypts on every GET and encrypts on every PUT, so the service handles your plaintext on every request and holds, or can fetch, the key. It is the right tool against a lost disk and the wrong one when the party you are protecting against is the cloud operator.
For that case, polign_db encrypts before the bytes leave the process. Give the server
a keyring file with -store-encryption-key-file (or the
POLIGN_STORE_ENCRYPTION_KEY_FILE environment variable) and every object it
writes to any store is AES-256-GCM ciphertext: the write log, segments, indexes,
manifests, API-key records, and the entries in its local disk cache. The bucket, its
backups, and the key service behind it hold ciphertext only. Keys are read from a file
or the environment and never fetched from a cloud key service, so the trusted computing
base stays at the binary plus whatever handed it the key.
Objects are framed in fixed 16 KiB chunks, so cold reads still fetch only the byte ranges they need, with no extra round trip. Each object's key is derived from its name, so a ciphertext moved to another name fails to open, and frames authenticate their position, so reordering, truncation, and tampering are reported as corruption, never as absence. A store written with keys is marked, and a node started without them refuses it at startup instead of reading garbage or writing plaintext into it. Rotation is adding a line to the keyring: new writes use the new key, old objects keep reading.
Two things to know before turning it on. Encryption is decided at the first write: a store cannot be converted in place, so an existing deployment moves to a new bucket or prefix. And the format hides content, not shape: object names, sizes, and access patterns remain visible to the store. The setup steps are in Operate in production.
Confidential computing
Confidential computing protects data while it is being processed: the CPU runs
your workload in an isolated environment with encrypted memory, so nothing else on
the host, the cloud operator included, can read what is in use. That protection
comes from the hardware, not from polign_db. What polign_db contributes is software
that fits inside such a boundary without ceremony: the serving engine is one static
Linux binary (polign-server, built with CGO_ENABLED=0; the
other binaries in the archive are operator tools), with no control plane and no
vendor in the data path. In practice that means moving a deployment inside a
confidential boundary is moving one process, auditing what runs there is hashing one
artifact against the release checksums, and your trusted computing base grows by
exactly one thing: this binary.
On a confidential VM (AMD SEV-SNP or Intel TDX instance types on AWS, GCP Confidential VM, Azure confidential VMs) the server runs unmodified: it is an ordinary Linux process whose only dependency is the object store endpoint. The hardware keeps memory encrypted while data is in use, and the no-egress posture above means a strict network policy costs nothing. What closes the loop is client-side encryption: bucket-side SSE would hand every object to a storage service that decrypts it, which is exactly the party a confidential deployment is meant to exclude. With a keyring, plaintext exists only inside the protected memory and the bucket holds ciphertext. Encrypted at rest, in transit, and in use, with the entire search engine inside a trust boundary you own.
The keyring reaches the process by whatever attested path the platform provides. On
a sealed-environment platform such as dstack, the keyring text goes in
POLIGN_STORE_ENCRYPTION_KEYS. On a confidential VM with attested secret
release, the boot chain fetches it into a tmpfs file and the server reads that path.
polign_db never fetches keys from a cloud key service itself.
AWS Nitro Enclaves take one extra piece: an enclave has no network of its own, so reaching the bucket means a vsock proxy, and the keyring is released by KMS against the enclave's attestation document, then written to a tmpfs path for the server. The static binary and per-release checksums make the enclave image straightforward to build and measure. A reproducible walkthrough is on the roadmap; if you are deploying into an enclave today, write to us and we'll work through it with you.
License
polign_db is proprietary and the source isn't public. The binaries are licensed, not
sold, and free to self-host while polign_db is in v0.x early access, with no license key
and no feature gates (Pricing has the details). The full text
ships in every release archive as LICENSE; it's a conventional proprietary
grant: run it for your own internal purposes, no redistribution, no derivative works, no
reverse engineering.
Reporting a vulnerability
Email security@polign.com with a description and a reproduction if you have one. Please don't open a public issue for anything you believe is exploitable. You'll get an acknowledgement within a few days, and fixes ship in the next patch release with credit unless you ask otherwise. Only the latest release gets security fixes, so upgrading is the patch channel.