{
  "id": "security/oauth2-state-parameter-missing",
  "signature": "OAuth2 authorization code injection: missing state parameter enables CSRF",
  "signature_zh": "OAuth2授权码注入：缺少state参数导致跨站请求伪造",
  "regex": "state parameter missing|CSRF.*state.*not found|Invalid state parameter",
  "domain": "security",
  "category": "auth_error",
  "subcategory": null,
  "root_cause": "The OAuth2 client does not generate or validate a cryptographically random state parameter, allowing an attacker to inject their own authorization code into a victim's session.",
  "root_cause_type": "generic",
  "root_cause_zh": "OAuth2客户端未生成或验证加密随机的state参数，使攻击者可以将自己的授权码注入到受害者的会话中。",
  "versions": [
    {
      "version": "OAuth2 2.0 RFC 6749",
      "introduced": null,
      "deprecated": null,
      "removed": null,
      "behavior_change": null,
      "status": "active"
    },
    {
      "version": "Passport.js 0.6.0",
      "introduced": null,
      "deprecated": null,
      "removed": null,
      "behavior_change": null,
      "status": "active"
    },
    {
      "version": "OmniAuth 2.1.0",
      "introduced": null,
      "deprecated": null,
      "removed": null,
      "behavior_change": null,
      "status": "active"
    }
  ],
  "os_specific": {},
  "dead_ends": [
    {
      "action": "",
      "why_fails": "Static state is predictable and does not prevent CSRF; attacker can guess or reuse it.",
      "fail_rate": 0.95,
      "condition": "",
      "sources": []
    },
    {
      "action": "",
      "why_fails": "Cookie-only state can be stolen via XSS or reused across sessions.",
      "fail_rate": 0.7,
      "condition": "",
      "sources": []
    },
    {
      "action": "",
      "why_fails": "Redirect_uri matching does not prevent CSRF; attacker can still inject code via a pre-registered URI.",
      "fail_rate": 0.85,
      "condition": "",
      "sources": []
    }
  ],
  "workarounds": [
    {
      "action": "Generate a cryptographically random state value per request, store it in the user session, and validate it on callback. Example in Node.js: const state = crypto.randomBytes(16).toString('hex'); req.session.oauthState = state; res.redirect(authUrl + '&state=' + state);",
      "success_rate": 0.95,
      "how": "Generate a cryptographically random state value per request, store it in the user session, and validate it on callback. Example in Node.js: const state = crypto.randomBytes(16).toString('hex'); req.session.oauthState = state; res.redirect(authUrl + '&state=' + state);",
      "condition": "",
      "sources": []
    },
    {
      "action": "Use PKCE (Proof Key for Code Exchange) with S256 challenge method, which inherently binds the authorization code to the client session",
      "success_rate": 0.9,
      "how": "Use PKCE (Proof Key for Code Exchange) with S256 challenge method, which inherently binds the authorization code to the client session",
      "condition": "",
      "sources": []
    },
    {
      "action": "Enforce state parameter validation at the authorization server level by rejecting requests without a valid nonce",
      "success_rate": 0.85,
      "how": "Enforce state parameter validation at the authorization server level by rejecting requests without a valid nonce",
      "condition": "",
      "sources": []
    }
  ],
  "workarounds_zh": [
    "Generate a cryptographically random state value per request, store it in the user session, and validate it on callback. Example in Node.js: const state = crypto.randomBytes(16).toString('hex'); req.session.oauthState = state; res.redirect(authUrl + '&state=' + state);",
    "Use PKCE (Proof Key for Code Exchange) with S256 challenge method, which inherently binds the authorization code to the client session",
    "Enforce state parameter validation at the authorization server level by rejecting requests without a valid nonce"
  ],
  "transition_graph": {
    "leads_to": [],
    "preceded_by": [],
    "frequently_confused_with": []
  },
  "official_doc_url": "https://datatracker.ietf.org/doc/html/rfc6749#section-10.12",
  "official_doc_section": null,
  "error_code": "CSRF_TOKEN_MISSING",
  "verification_tier": "ai_generated",
  "confidence": 0.9,
  "fix_success_rate": 0.92,
  "resolvable": "true",
  "first_seen": "2023-05-20",
  "last_confirmed": "2024-06-01",
  "last_updated": "2024-06-01",
  "evidence_count": 1,
  "tags": [],
  "locale": "en",
  "aliases": []
}