HIGH container escapejwt tokens

Container Escape with Jwt Tokens

How Container Escape Manifests in Jwt Tokens

Container escape attacks aim to break out of an isolated runtime (e.g., Docker, containerd) and gain access to the host filesystem or other containers. When JWT tokens are used to authenticate to a container orchestration platform — most commonly the Kubernetes API server — a flaw in JWT validation can grant an attacker privileged API access. With that access the attacker can:

  • Create or patch a privileged pod that mounts the host’s root directory (hostPath: /).
  • Exec into that pod and run commands on the host.
  • Modify privileged service accounts or cluster roles.

The JWT‑specific code paths where this appears are typically:

  1. Token receipt – the API server extracts the Authorization: Bearer <token> header.
  2. Signature verification – the server validates the token’s signature using a shared secret or public key.
  3. Claims validation – checks such as iss, aud, exp, and custom claims like groups or username.
  4. Authorization mapping – validated claims are mapped to Kubernetes RBAC subjects.

If any of these steps is mis‑implemented, an attacker can forge a token that maps to a system:master or cluster‑admin user. Real‑world examples include:

  • Algorithm confusion ("none") – accepting a token with the alg:none header and skipping signature verification (see CVE‑2022-23521 for a Kubernetes‑related token bypass).
  • KID injection – using the kid claim to reference a file path (../../etc/passwd) when the validation library incorrectly treats the key ID as a filesystem path, leading to disclosure of the secret key.
  • Weak secret / brute‑force – a low‑entropy HMAC secret allows an attacker to compute a valid signature for arbitrary claims.

Once the attacker holds a token that maps to a cluster‑admin, they can issue a request such as:

POST /api/v1/namespaces/default/pods
{
  "apiVersion": "v1",
  "kind": "Pod",
  "metadata": {"name": "escape-pod"},
  "spec": {
    "containers": [{
      "name": "shell",
      "image": "alpine",
      "command": ["sleep", "3600"],
      "volumeMounts": [{ "name": "host", "mountPath": "/host" }]
    }],
    "volumes": [{ "name": "host", "hostPath": { "path": "/", "type": "Directory" } }]
  }
}

Executing a shell in that pod gives the attacker direct read/write access to the host’s filesystem — effectively a container escape.

Jwt Tokens-Specific Detection

Detecting JWT‑related container‑escape risks involves checking both the token handling logic and the configuration of the service that consumes the token. middleBrick’s unauthenticated black‑box scan includes the following checks that surface these issues:

  • Authentication check – verifies whether the endpoint accepts a Bearer token without proper signature validation.
  • Input Validation check** – probes for algorithm confusion by sending tokens with alg:none and modified claims.
  • Property Authorization check** – ensures that claims such as iss, aud, and custom role claims are enforced.
  • Data Exposure check** – looks for token leakage in response headers, error messages, or debug endpoints.

During a scan, middleBrick will:

  1. Baseline the endpoint with no token to confirm it requires authentication.
  2. Send a series of crafted JWTs:
    • A token with alg:none and a payload that sets "groups":["system:masters"].
    • A token where the kid points to a traversal path (../../../etc/ssl/private/ca.key).
    • A token signed with a weak secret (e.g., secret) to test brute‑force feasibility.
  3. Analyze responses: any 2xx response that returns privileged data (e.g., list of secrets, ability to create pods) indicates a missing or broken validation step.
  4. Correlate findings with the LLM/AI Security module if the endpoint also serves an LLM, ensuring that token‑related misconfigurations are not overlooked in AI‑specific contexts.

The scan report will list each finding with:

  • Severity (Critical/High/Medium/Low) based on the impact of gaining cluster‑admin privileges.
  • Remediation guidance referencing the specific JWT library method that is misused.
  • References to relevant CVEs (e.g., CVE‑2022-23521) and OWASP API Security Top 10 items (Broken Authentication, Improper Asset Management).

Because middleBrick requires no agents or credentials, a developer can simply paste the API URL (e.g., https://api.example.com) and receive a prioritized list of JWT‑related risks that could lead to container escape.

Jwt Tokens-Specific Remediation

Fixing JWT validation to prevent privilege escalation and subsequent container escape involves using the library’s verification features correctly and enforcing strict claim checks. Below are language‑specific examples that demonstrate the safe patterns.

Node.js (jsonwebtoken)

Incorrect (vulnerable) code that accepts any token:

const jwt = require('jsonwebtoken');
function auth(req, res, next) {
  const token = req.headers.authorization?.split(' ')[1];
  try {
    // ❌ No verification – just decodes
    const payload = jwt.decode(token);
    req.user = payload;
    next();
  } catch (err) {
    res.status(401).send('Invalid token');
  }
}

Correct implementation:

const jwt = require('jsonwebtoken');
const SECRET = process.env.JWT_SECRET; // strong, random value
function auth(req, res, next) {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) return res.status(401).send('Missing token');

  try {
    const payload = jwt.verify(token, SECRET, {
      // Enforce algorithm – reject "none"
      algorithms: ['HS256'],
      // Validate standard claims
      issuer: 'https://auth.example.com',
      audience: 'https://api.example.com',
      // Optional: enforce expiration leeway
      clockTimestamp: Math.floor(Date.now() / 1000)
    });
    // Additional application‑specific claims
    if (!payload.groups || !payload.groups.includes('system:masters')) {
      return res.status(403).send('Insufficient privileges');
    }
    req.user = payload;
    next();
  } catch (err) {
    // Distinguish token errors from other failures
    if (err.name === 'JsonWebTokenError') {
      return res.status(401).send('Invalid token');
    }
    if (err.name === 'TokenExpiredError') {
      return res.status(401).send('Token expired');
    }
    return res.status(400).send('Bad request');
  }
}

Python (PyJWT)

Incorrect (vulnerable) code:

import jwt
from flask import request, abort

def require_auth():
    auth = request.headers.get('Authorization', '')
    if not auth.startswith('Bearer '):
        abort(401)
    token = auth.split(' ')[1]
    # ❌ No verification
    payload = jwt.decode(token, options={"verify_signature": False})
    request.user = payload

Correct implementation:

import jwt
from flask import request, abort

SECRET = os.environ.get('JWT_SECRET')  # must be strong

def require_auth():
    auth = request.headers.get('Authorization', '')
    if not auth.startswith('Bearer '):
        abort(401, 'Missing Bearer token')
    token = auth.split(' ')[1]

    try:
        payload = jwt.decode(
            token,
            SECRET,
            algorithms=['HS256'],  # reject "none"
            issuer='https://auth.example.com',
            audience='https://api.example.com',
            leeway=10  # small clock skew tolerance
        )
        # Enforce custom claim
        groups = payload.get('groups', [])
        if 'system:masters' not in groups:
            abort(403, 'Insufficient privileges')
        request.user = payload
    except jwt.InvalidTokenError as e:
        abort(401, f'Invalid token: {str(e)}')

Additional hardening steps that apply regardless of language:

  • Use a strong, randomly generated secret (minimum 32 bytes for HS256) or, preferably, an asymmetric key pair (RS256/ECDSA) where the public key is stored securely and never exposed to clients.
  • Rotate secrets periodically and invalidate old tokens via a token revocation list or short expiration times (exp ≤ 15 min) combined with refresh tokens.
  • Avoid using the kid header to reference file paths; if a key ID is needed, map it to a known key identifier in a secure key store.
  • Log authentication failures (including malformed tokens) and monitor for spikes that may indicate brute‑force or algorithm‑confusion attempts.
  • Regularly scan the endpoint with middleBrick (via CLI, GitHub Action, or the MCP Server) to ensure that any regression in JWT handling is caught early.

By applying these fixes, the service will correctly reject forged tokens that attempt to map to privileged Kubernetes subjects, thereby removing the pathway that attackers use to achieve container escape via JWT misuse.

Frequently Asked Questions

Can middleBrick detect a JWT "none" algorithm attack on my API?
Yes. During its Authentication and Input Validation checks, middleBrick sends a token with the alg:none header and a payload that attempts to elevate privileges (e.g., setting groups to ["system:masters"]. If the endpoint accepts the token and returns privileged data, the finding is reported with high severity and guidance to enforce algorithm verification in your JWT library.
What should I do if middleBrick reports a weak JWT secret on my endpoint?
The finding indicates that the HMAC secret used to sign tokens is low‑entropy, making it feasible for an attacker to forge a token with arbitrary claims. Remediate by generating a strong secret (at256‑bit randomvalue) and configuring your service to use it. Rotate the secret periodically, update all token‑issuing services, and consider moving to an asymmetric algorithm (RS256/ECDSA) where the public key is stored separately from the private signing key. After making the change, rescan with middleBrick to confirm the issue is resolved.