A common mistake is passing sensitive credentials through business logic or using global state in a Lambda runtime. Both approaches can create accidental coupling, concurrency bugs, and cross-request leakage. The better pattern is to create credentials before handler execution, then store them in a request-bound context so the data layer can access only the current invocation’s values.
Why Tenant Credentials Should Never Flow Through Serverless Business Logic
Passing tenant credentials through a serverless application layer turns a short-lived access decision into application state, which is where teams start to lose isolation. The problem is not only secrecy, but timing, scope, and reuse. Once credentials are threaded through handler code, they become easier to cache, log, mishandle across concurrent invocations, or accidentally share between requests.
Serverless runtimes encourage compact code, but compactness can hide unsafe lifecycle assumptions. A credential that belongs to one invocation should exist only inside that invocation’s trust boundary. When it is pushed through business logic, the application starts acting like a relay for sensitive material instead of a boundary that contains it. That increases the chance that a bug in one layer becomes a tenant-to-tenant exposure.
Experienced teams usually discover the problem only after a concurrency defect, retry path, or debug trace has already carried the wrong value across a request boundary.
How It Works in Practice
The safer pattern is to create or resolve tenant credentials before the handler begins processing, then bind them to a request-scoped context that downstream code can read without mutating. That keeps the credential lifecycle aligned to one invocation, rather than to the lifetime of a warm runtime or shared module state. The data layer should receive only the current request’s context, not a globally reachable secret.
This matters because serverless platforms reuse execution environments. A global variable, singleton client, or module-level cache can survive beyond one request, which means a value intended for Tenant A can still be present when Tenant B arrives. If the code also performs retries, background work, or parallel async calls, the risk expands from leakage to nondeterministic cross-request behavior.
- Keep tenant credential material out of handler branching and transformation code.
- Bind credential values to per-request context objects, not shared globals.
- Refresh or resolve credentials at the edge of the invocation, then pass references inward.
- Make downstream data access read-only with respect to tenant context.
- Test warm-container reuse, concurrency, and retry paths explicitly.
When teams violate these boundaries, the same runtime optimization that improves latency can also preserve sensitive state longer than intended. These controls tend to break down when asynchronous fan-out and shared helpers are used to speed up request handling because the code path stops behaving like a single, isolated transaction.
Common Variations and Edge Cases
Tighter credential handling often increases implementation overhead, so teams have to balance speed of development against request isolation and auditability. The practical trade-off is usually between convenience, such as passing one object everywhere, and a cleaner security model that keeps tenant context explicit and short-lived.
One common edge case is middleware that looks harmless because it only enriches request context. If that middleware reads or writes credential data, it becomes part of the trust boundary and must be treated like security-sensitive code. Another is retry logic, where a failed invocation is replayed with stale state still attached to the runtime. That is especially dangerous when the credential points to a privileged downstream service or when the same runtime handles multiple tenants.
Current guidance suggests treating any credential-carrying object as request-scoped by default, then allowing exceptions only when a team can prove the object cannot survive beyond the current invocation. In practice, teams often underestimate how much leakage comes from helper libraries and observability hooks rather than from the main handler itself.
Risk and Threat Considerations
Passing tenant credentials through serverless layers creates exposure through state reuse, logging, and concurrency. The risk is highest when the runtime is warm, request handling is parallel, or code paths are shared across tenants, because the credential stops being a single-request artifact and becomes reusable application state.
Failure mechanism: A shared variable, cached client, or mutable context object can preserve tenant-specific credentials across invocations. An attacker or a logic fault does not need to break the platform, only to trigger the wrong code path, replay a request, or exploit a race so one tenant’s credential is read in another tenant’s execution path.
Impact: The result can be cross-tenant credential leakage, unauthorized downstream access, corrupted audit trails, and privilege misuse in the data layer. If the credential can reach production systems, blast radius grows quickly because the failure is no longer confined to one function call.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
OWASP Non-Human Identity Top 10 and OWASP Agentic AI Top 10 address the attack and risk surface, while CIS Controls v8 set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| OWASP Non-Human Identity Top 10 | NHI-01 — Secrets and Credential Management | Tenant creds in serverless are secrets that must not persist across requests. |
| NHI-03 — Privilege and Access Scope | Cross-request reuse can expand tenant access beyond the intended scope. | |
| NHI-07 — Lifecycle and Rotation | Warm runtimes can extend credential lifetime beyond a single invocation. | |
| Recommendation — Keep tenant credentials request-scoped and rotate or revoke any shared secret paths. Apply least privilege to each invocation and prevent credential reuse across tenants. Use short-lived credentials and reissue them before each handler execution. | ||
| OWASP Agentic AI Top 10 | A2 — Context and Tool Access Isolation | Serverless layers should isolate sensitive context before downstream use. |
| Recommendation — Bind sensitive context to one execution path and block shared state leakage. | ||
| CIS Controls v8 | 6 — Access Control Management | Tenant credentials must be restricted to the correct execution context. |
| 16 — Application Software Security | The issue arises in application-layer handling of sensitive credentials. | |
| Recommendation — Restrict access paths so only the current request can use tenant credentials. Test serverless handlers for shared-state and concurrency flaws that expose secrets. | ||
Practitioner Guidance
What to verify: Confirm that no credential-bearing object survives past the current invocation, including module scope, static helpers, and retry wrappers. Validate this under warm-container reuse, not just in unit tests.
Decision rule: If a value can authenticate to a downstream system, treat it as sensitive request-scoped material and pass it by context, not by shared state. If the code cannot prove isolation, assume the tenant boundary is already weakened.
What good looks like: Each invocation resolves only the credentials it needs, downstream code reads them once, and observability captures enough metadata to diagnose failures without exposing the secret itself.
Practitioner takeaway: The objective is not to make serverless code stateless in the abstract, it is to make tenant-sensitive state strictly local to one invocation so latency optimizations never become cross-request exposure paths.
Related resources from NHI Mgmt Group
- What do teams get wrong when they rely on application code for permission checks?
- What do IAM teams get wrong when they treat agentic AI as just another application?
- What do security teams get wrong when they treat CSPM as enough for application risk?
- What do teams get wrong when they try to model all permissions with one layer of application rules?