#AI#大模型#DevOps

Multi-Tenant AI Envelope Encryption Boundaries: Prevent Cross-Tenant Ciphertext Substitution with DEKs, AAD, and Key Domains

A platform-wide KMS key proves only that data is encrypted; it cannot prevent cross-tenant substitution or unintended decryption. This article designs tenant key hierarchies, context binding, caching, and recovery validation.

Key Points

  • Topic Focus: AI、大模型、DevOps
  • Suitable for: indie hackers, full-stack engineers, AI application developers
  • Core value: quickly understand background, practical paths, common pitfalls, and engineering advice
Author @admin·Published July 26, 2026·Updated July 26, 2026

Object storage showing SSE-KMS does not mean a multi-tenant boundary exists. If an application uses one service-level key to decrypt every conversation, embedding, and fine-tuning adapter, an attacker only needs to replace tenant B's object with ciphertext from tenant A, and flawed code may decrypt it under legitimate KMS permissions. The earlier article on MCP Multi-Tenant Isolation constrains requests, caches, and asynchronous context; this article binds the same tenant identity to ciphertext bytes and key operations.

Define Tenant Key Domains Instead of One Universal Key

Freeze ai.envelope.v1. Each tenant and data purpose has an independent logical key domain, such as tenant-42/conversation, tenant-42/vector, or tenant-42/adapter. You do not necessarily need to create a KMS key for every record; a restricted KEK can wrap short-lived DEKs, but the KEK policy, grants, and ledger must prevent one tenant domain from unwrapping another domain's DEK. The key-usage, lifecycle, and archival principles in NIST SP 800-57 should be implemented as queryable metadata rather than merely documented in policy.

Use an authenticated encryption mode such as AES-256-GCM for data. Generate a random nonce for every encryption operation and never reuse one under the same DEK. AAD must cover at least the tenant ID, data purpose, stable object ID, schema version, and region; authentication must fail when ciphertext is copied from one object into another context. AWS KMS Encryption Context can also bind these fields, but it is not secret and may appear in audit logs, so it must not contain prompts, email addresses, or original filenames.

json
{
  "schema": "ai.envelope.v1",
  "tenant": "t_42",
  "purpose": "conversation",
  "objectId": "conv_01J...",
  "region": "ap-east-1",
  "keyVersion": "tenant-42/conversation/7",
  "wrappedDek": "base64...",
  "nonce": "base64...",
  "ciphertext": "base64..."
}

tenant must come from the authenticated session and a server-side resource record; the request body must not be trusted. KMS conditions and application AAD must use the same canonicalized values, with rules for casing, Unicode, null values, and version conversion frozen with the schema. The service identity described in MCP Server Authentication Boundaries may only receive the capability to "unwrap on behalf of an authorized tenant request"; it must not be able to list or bulk-decrypt all tenants.

Control Plaintext, DEK Caches, and Derived Copies

DEKs should exist in memory only briefly. Cache keys must include tenant, purpose, KEK version, and policy generation, with limits on TTL, entry count, and instances. Before every decryption, obtain a short-lived decryptLease from a linearly consistent tenant fence and register the operation ID, object, generation, purpose, and expiration time; even a cache hit must not bypass the fence. When a tenant is disabled, access is revoked, or a key is disabled, the control plane atomically advances the generation and stops issuing leases, erases old caches, and then cancels or drains operations registered under the previous generation.

During a KMS failure, only operations registered before the failure, permitted by policy to continue, and holding an unexpired lease may finish using a cached DEK. New requests arriving after the failure and work without an operation record must fail; they cannot be redefined as "in flight." An unreachable fence, stale generation, or expired lease must fail closed, without falling back to a global key or extending the cache.

Conversation summaries, vectors, evaluation samples, exported files, and temporary debugging copies must all inherit the tenant domain. Encrypting only the primary table while writing prompts into Trace Telemetry bypasses the boundary. Message queues should carry ciphertext and non-sensitive references, with workers decrypting in place after authorization. Plaintext must not enter exception stacks, swap partitions, image layers, or cross-tenant batch-processing directories.

Backups must retain a signed manifest, every stable object ID, ciphertext digest, wrapped DEK digest, complete AAD, envelope revision, and key version. The recovery tool must reauthenticate for the target tenant and region, perform a full set diff between the manifest and actual objects, and verify each tenant, AAD value, revision, key version, and digest. Reads may be enabled only after the counts of missing, extra, unknown-key, and cross-tenant entries are all zero; sampling cannot replace proof of complete coverage. "Database recovery succeeded" does not mean the key boundary was recovered successfully. The standby region described in Cloud Disaster Recovery should have a restricted KMS path provisioned in advance, without exporting the production KEK.

Validate with Substitution Attacks and Recovery Drills

Test fixtures must cover at least placing tenant A's ciphertext under tenant B's object ID, replacing the tenant or purpose, omitting an AAD field, reusing a nonce, using a disabled key version, forging a wrapped DEK, forcing a KMS timeout, allowing one worker to retain an old cache, and restoring a backup into the wrong tenant. Every cross-domain combination must fail at the unwrap policy or AEAD authentication stage, and error responses must not reveal whether a key exists.

Release evidence must include key-policy summaries, KMS decisions, active key-version coverage, old caches, ciphertext schemas, complete recovery manifest reports, and negative tests. Logs should retain only random object IDs, key IDs, and context digests. The dual credentials described in AI Platform Key Rotation appear here as old and new KEKs coexisting, but new writes must move monotonically to the new version.

Migration uses read-old/write-new. Every rewrap.v1 event carries a stable event ID, object ID, from/to key version, target envelope revision, and expected old wrapped-DEK hash. The worker uses CAS to write the new wrapped DEK only if the object still matches the old revision and hash. A lost response can be replayed idempotently by event ID; if a concurrent application update wins, the old rewrap becomes a no-op. During the transition, every object explicitly declares its key version, and the reader selects only the corresponding key instead of trying each key in turn.

Once the complete object set, revisions, and backup manifests contain no old references, first stop old writes, then disable the old KEK and observe the rollback window. Rollback may restore only an explicit read/write policy for an uncompromised old key; it must not overwrite new envelopes created concurrently. A compromised KEK must be rotated and rewrapped.

When a tenant is offboarded, disabling its KEK can quickly block online decryption, but "undecryptable" and physical deletion are not the same promise. Actual deletion must also cover backups, logs, and derived data. The goal of a verifiable encryption boundary is to ensure that any ciphertext can be opened only at the intersection of the correct tenant, correct purpose, correct object, and valid key generation.

Further Reading

Related

Related Content