Ssrf Server Side with Jwt Tokens
JWT-Specific Remediation Techniques
Remediating SSRF in JWT contexts requires a defense-in-depth approach combining input validation, allowlisting, and secure defaults. The most effective strategy prevents untrusted data from controlling outbound requests.
Implement strict claim validation before processing JWTs. Only allow specific, expected values for claims that might influence URL construction. For jku claims, use a strict allowlist of trusted JWKS endpoints rather than trusting any URL provided by the client.
// Comprehensive JWT SSRF protection
const jwt = require('jsonwebtoken');
const axios = require('axios');
// Configuration
const JWKS_ALLOWLIST = [
/^https://auth\.example\.com/.well-known/jwks\.json$/,
/^https://api\.example\.org/keys/$/,
];
function validateJkuUrl(jkuUrl) {
const urlObj = new URL(jkuUrl);
// Protocol must be HTTPS
if (urlObj.protocol !== 'https:') {
throw new Error('Only HTTPS allowed for JKU');
}
// No custom ports
if (urlObj.port !== '') {
throw new Error('Custom ports not allowed');
}
// Check against allowlist
const matchesAllowlist = JWKS_ALLOWLIST.some(pattern =>
pattern.test(jkuUrl)
);
if (!matchesAllowlist) {
throw new Error('JKU URL not in allowlist');
}
return true;
}
async function secureValidateWithJku(token) {
const decoded = jwt.decode(token, { complete: true });
// Validate jku claim exists and is valid
if (!decoded.payload.jku) {
throw new Error('Missing JKU claim');
}
validateJkuUrl(decoded.payload.jku);
// Fetch and verify
const jwksResponse = await axios.get(decoded.payload.jku);
const key = jwksResponse.data.keys.find(k =>
k.kid === decoded.header.kid
);
if (!key) {
throw new Error('No matching key found');
}
return jwt.verify(token, key);
}For issuer-based validation, implement strict allowlisting of trusted issuers and validate the token's signature before making any outbound requests. Never use unverified token claims to construct URLs.
// Issuer validation with SSRF protection
async function validateIssuerSafe(token, trustedIssuers) {
try {
// Verify signature first
const decoded = jwt.verify(token, process.env.PUBLIC_KEY);
// Validate issuer against allowlist
if (!trustedIssuers.includes(decoded.iss)) {
throw new Error('Untrusted issuer');
}
// Only make introspection request if issuer is trusted
const introspectionUrl = `${decoded.iss}/introspect`;
const response = await axios.post(introspectionUrl, {
token: token
}, {
headers: { 'Content-Type': 'application/json' }
});
return response.data.active;
} catch (error) {
// Handle verification errors
if (error.name === 'JsonWebTokenError') {
throw new Error('Invalid token signature');
}
throw error;
}
}Implement network-level protections including egress filtering, VPC service controls, and internal network segmentation. Even if JWT processing code has SSRF vulnerabilities, network controls can limit the impact by preventing access to internal services.
Consider using libraries that automatically validate JWT claims and provide secure defaults. The express-jwt middleware and similar frameworks handle many common security concerns out of the box.
Frequently Asked Questions
How does middleBrick detect SSRF vulnerabilities in JWT endpoints?
jku or iss URLs. It monitors for outbound HTTP requests to internal IP ranges (10.x, 172.x, 192.x, 169.254.x) and cloud metadata endpoints. The scanner tests 12 security categories in parallel, including SSRF detection, and provides severity ratings with remediation guidance. No credentials or agents are required—just submit your JWT endpoint URL for a 5-15 second scan.What's the difference between JWT SSRF and regular SSRF?
jku, iss, x5u) that are often trusted without validation. JWT SSRF can be more dangerous because token processing services typically have elevated network privileges and the vulnerability is hidden within authentication flows that developers assume are secure. The attack surface includes JWKS fetching, token introspection, and any JWT claim that influences outbound requests.