{
  "variant_id": "GHSA-5rr4-8452-hf4v-dns-shaped-ssrf-bypass",
  "created_at": "2026-07-07T23:40:00Z",
  "variant_summary": "The 1.6.11 fix for @better-auth/sso SSRF validates only the literal hostname of user-supplied OIDC endpoints. A public-looking FQDN that resolves to a private IP (e.g., an attacker-controlled public domain or container hostname) is accepted and then fetched server-side during the OIDC callback, reproducing the SSRF on the patched version. Latest release (1.6.23) blocks this with runtime DNS resolution checks.",
  "relation": "newer_version_sibling",
  "origin_kind": "pruva_variant",
  "repository": "https://github.com/better-auth/better-auth.git",
  "submitted_target": {
    "target_kind": "npm_version",
    "version": "1.6.10",
    "display": "@better-auth/sso@1.6.10 / better-auth@1.6.10 (vulnerable baseline)"
  },
  "variant_target": {
    "target_kind": "git_commit",
    "commit_sha": "37f60cb176cb53147da7dfd5ec15afa5b486e81e",
    "version": "1.6.11",
    "display": "better-auth@37f60cb / @better-auth/sso@1.6.11 (patched version where bypass was reproduced)"
  },
  "same_root_cause_confidence": "high",
  "same_surface_confidence": "high",
  "claimed_surface": "api_remote",
  "validated_surface": "api_remote",
  "required_entrypoint_kind": "endpoint",
  "required_entrypoint_detail": "POST /api/auth/sso/register -> /api/auth/sign-in/sso -> /api/auth/sso/callback/:providerId",
  "attacker_controlled_input": "attacker-controlled OIDC endpoint URLs using a public-FQDN hostname that resolves to a private IP, supplied in POST /sso/register with skipDiscovery:true",
  "trigger_path": "POST /api/auth/sso/register (provider persisted) -> POST /api/auth/sign-in/sso -> /api/auth/sso/callback/:providerId -> server-side fetch to tokenEndpoint and userInfoEndpoint",
  "observed_impact_class": "ssrf",
  "exploitability_confidence": "high",
  "evidence_scope": "production_path",
  "runtime_manifest_present": true,
  "end_to_end_target_reached": true,
  "inferred": false,
  "file_path": "packages/sso/src/oidc/discovery.ts",
  "line_start": 151,
  "line_end": 166,
  "secondary_anchors": [
    {
      "file_path": "packages/sso/src/oidc/discovery.ts",
      "line_start": 176,
      "line_end": 195
    },
    {
      "file_path": "packages/sso/src/routes/sso.ts",
      "line_start": 670,
      "line_end": 680
    },
    {
      "file_path": "packages/sso/src/routes/providers.ts",
      "line_start": 490,
      "line_end": 500
    },
    {
      "file_path": "packages/sso/src/routes/sso.ts",
      "line_start": 1509,
      "line_end": 1530
    },
    {
      "file_path": "packages/sso/src/routes/sso.ts",
      "line_start": 1554,
      "line_end": 1560
    }
  ],
  "review_scope_paths": [
    "packages/sso/src/oidc/discovery.ts",
    "packages/sso/src/routes/sso.ts",
    "packages/sso/src/routes/providers.ts",
    "packages/sso/src/routes/saml-pipeline.ts",
    "packages/core/src/utils/host.ts"
  ],
  "artifact_refs": {
    "variant_manifest": "bundle/vuln_variant/variant_manifest.json",
    "validation_verdict": "bundle/vuln_variant/validation_verdict.json",
    "runtime_manifest": "bundle/vuln_variant/runtime_manifest.json",
    "repro_log": "bundle/logs/vuln_variant.log",
    "root_cause_equivalence": "bundle/vuln_variant/root_cause_equivalence.json",
    "reproducer": [
      "bundle/vuln_variant/reproduction_steps.sh"
    ]
  }
}
