Join our Newsletter — 33% off our NHI Course

How should teams handle client-side applications that expose valid API credentials?

Treat exposed client-side credentials as a trust boundary failure, not just a secret leak. Tighten scope, shorten lifetime, and ensure backend authorisation can distinguish expected app context from reused credentials. If a client can be unpacked and inspected, assume the attacker will eventually recover whatever is embedded there.

Why client-side API credentials change the trust model

When an application embeds valid API credentials in code shipped to a browser, desktop client, mobile app, or other user-controlled runtime, those credentials are no longer protected by the developer’s environment. The client becomes part of the attack surface, which means confidentiality, authorisation, and abuse resistance all need to be judged on the assumption that the credential can be extracted, replayed, or repurposed. That is why this is not just a secret-handling issue. It is a boundary design issue.

For teams deciding how to handle this pattern, the key question is not whether the secret is technically hidden, but whether the backend can still enforce meaningful limits if it is recovered. In practice, the answer is often only partly. Public clients may need a credential for basic service access, but that credential should never be treated as a durable proof of trusted application identity. The most relevant design expectation is that a recovered credential will be used outside the intended app context unless the server has separate checks that constrain what the credential can do.

In practice, many security teams discover the real problem only after a client build has already been unpacked and the embedded credential reused at scale.

How teams should contain the blast radius

The right response is to minimise what the exposed credential can authorise and to make reuse detectable or unhelpful. If a client-side application must carry a credential, that credential should be scoped to the smallest viable set of operations, have a short lifetime, and be revocable without breaking unrelated services. The backend should then enforce application-level rules that do not rely on the credential alone, because the credential itself is no longer a strong trust signal.

That usually means separating access into layers. The embedded credential may identify the application family or enable low-risk calls, but higher-value operations should require additional server-side context such as user authentication, transaction-specific checks, or a backend-issued token that is harder to reuse outside the intended flow. Where possible, the service should distinguish between expected client behaviour and generic credential replay by looking at request path, rate, origin, device signals, or other context that the attacker cannot easily forge at the same time as the credential.

A practical containment approach often includes the following:

  • scope credentials to read-only or low-impact functions where feasible
  • rotate or expire credentials quickly so extraction has limited value
  • bind sensitive actions to server-side authorisation, not to the client secret alone
  • monitor for abnormal reuse patterns, especially from unexpected geographies, rates, or user agents
  • assume the client binary, package, or script will eventually be inspected

Where teams get this wrong is by treating the embedded value as a gatekeeper instead of a convenience mechanism for reaching a controlled backend. That guidance breaks down when the backend has no independent way to tell legitimate app calls from copied calls.

When the pattern is acceptable, and when it is not

Tighter controls often increase implementation overhead, requiring teams to balance developer convenience against the reality that any client-held secret can be extracted. The acceptable cases are usually narrow: low-risk public access, limited data exposure, and services where credential loss does not create broad downstream privilege. The unacceptable cases are those where the credential unlocks privileged APIs, customer data, write operations, or administrative functions.

There is also a meaningful trade-off between usability and assurance. Public clients cannot safely hold long-lived secrets in the same way a backend service can, so teams sometimes confuse “not ideal” with “safe enough.” That is a mistake. If the client is user-controlled, the embedded credential should be treated as an identifier for throttling or coarse access control, not as evidence of a trusted workload. For higher-assurance scenarios, teams should move the sensitive call path behind a server they control, or redesign the workflow so the public client never directly possesses the most powerful secret.

Another edge case is mobile or desktop software that uses certificate pinning, obfuscation, or packaging controls. These measures can raise effort for casual extraction, but they do not turn a client runtime into a secure vault. They may reduce opportunistic abuse, yet they do not change the underlying trust model. The safest operational rule is to treat embedded credentials as recoverable, constrain their privilege accordingly, and ensure the backend still behaves safely after compromise.

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 address the attack and risk surface, while CIS Controls v8, NIST CSF 2.0 and MITRE-ATTACK set the governance and control requirements practitioners need to meet.

Framework Control / Reference Relevance
OWASP Non-Human Identity Top 10 NHI-01 Client-side embedded API credentials are non-human secrets that must be scoped and governed as recoverable credentials.
Recommendation: Keep embedded machine credentials narrow, short-lived, and replaceable so extraction does not equal broad service abuse.
CIS Controls v8 6 The question is about limiting what exposed credentials can access if reused.
Recommendation: Restrict access rights so a copied client credential cannot reach sensitive functions or data.
NIST CSF 2.0 PR.AC The core issue is whether the backend can still distinguish legitimate use from replayed client credentials.
Recommendation: Use authentication and access control that remain effective even when the client-side secret is exposed.
MITRE-ATTACK T1552 Embedded API credentials are recoverable secrets that attackers commonly extract and reuse.
Recommendation: Assume exposed credentials will be found and abused, then limit the blast radius of that reuse.

Practitioner Guidance

What to prioritise: Start by classifying every client-held credential by what it can actually do if copied. The highest-risk items are anything that can write data, call privileged endpoints, or unlock broad API access. Those should be the first candidates for redesign rather than hardening.

What to verify: Confirm the backend has an independent control that limits damage after extraction. If the only thing standing between an attacker and abuse is the embedded secret, the design is not resilient enough for a client-side runtime. Verify revocation speed, scope boundaries, and whether monitoring can distinguish normal app traffic from replay.

Decision rule: If the credential cannot be meaningfully scoped or short-lived, move the sensitive operation out of the client path. If the application must remain public, keep the embedded credential on the lowest-risk side of the trust boundary and require stronger server-side checks for anything important.

Practitioner takeaway: The correct goal is not to hide client-side credentials better, but to make their loss non-fatal; if extraction would still expose privileged capability, the architecture still trusts the client too much.