CVE-2026-55834: Github.com/pocket id/pocket id/backend Pocket-ID Has An Open Redirect Vulnerability

MODERATE
Advisory Identifier: GHSA-2wvm-8mvp-22qv
CVSS 4.3
CWE-601
Published
Advisory Summary

CVE-2026-55834 is a MODERATE (CVSS 4.3) pocket-id has an open redirect vulnerability (CWE-601: URL Redirection to Untrusted Site ('Open Redirect')) affecting Github.com/pocket id/pocket id/backend libraries in the Go ecosystem. The issue involves pocket-id has an open redirect on the oidc /authorize page via unvalidated redirect_uri with prompt=none. Remediation is available by upgrading affected packages to version 2.9.0.

CVE-2026-55834 at a Glance

CVE Identifier CVE-2026-55834
GHSA Identifier GHSA-2wvm-8mvp-22qv
Severity MODERATE
CVSS v3.1 Base Score 4.3
CWE Classification CWE-601: URL Redirection to Untrusted Site ('Open Redirect')
Affected Product Github.com/pocket id/pocket id/backend
Package Ecosystem Go
Published Date
Last Updated

Security Impact

CVSS: 4.3

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction Required (UI:R)
Scope Unchanged (S:U)
Confidentiality None (C:N)
Integrity Low (I:L)
Availability None (A:N)

How to Fix CVE-2026-55834

To remediate this vulnerability, upgrade all affected Github.com/pocket id/pocket id/backend dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

github.com/pocket-id/pocket-id/backend fixed: 2.9.0
Upgrade github.com/pocket-id/pocket-id/backend to 2.9.0
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for github.com/pocket-id/pocket-id/backend

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-55834, inspect your project dependencies for Github.com/pocket id/pocket id/backend:

inspect dependencies for github.com/pocket-id/pocket-id/backend

Analyze the terminal output to locate any version of Github.com/pocket id/pocket id/backend in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 2.9.0), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-601: URL Redirection to Untrusted Site ('Open Redirect'), where the web application accepts a user-controlled input that specifies a link to an external site, and uses that link in a redirect. In Github.com/pocket id/pocket id/backend, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### Summary The OIDC authorization page in the pocket-id frontend redirects the browser to an attacker-controlled URL without consulting the backend redirect_uri allow-list when the request uses prompt=none. An attacker who knows a valid client_id can craft an /authorize link that sends a victim (or a victim's browser doing a silent re-auth) to any external https URL, enabling phishing and OAuth response smuggling. The backend allow-list validation that protects the normal authenticated flow is bypassed because this path is handled entirely client-side. ### Details For an OIDC authorization request with prompt=none, the SvelteKit frontend short-circuits the flow before the backend ever validates the redirect_uri against the client's registered callback list. File: frontend/src/routes/authorize/+page.ts (line 14) parses the raw redirect_uri query parameter from the incoming URL. File: frontend/src/routes/authorize/+page.svelte - in onMount(), when the request carries prompt=none and the user cannot be silently authorized (for example the visitor is not logged in, so login_required must be returned), the page builds the callback URL from the raw redirect_uri and performs: window.location.href = `${callbackURL}?error=login_required...` The callbackURL is taken directly from the user-supplied redirect_uri. The only filtering applied is a scheme check that blocks javascript: and data: URLs; any http: or https: origin passes through. The backend allow-list validator GetCallbackURLFromList (which the authenticated code path uses to confirm the redirect_uri matches one of the client's registered callback URLs) is never invoked on this branch. This means the per-client redirect_uri allow-list, the central control that makes redirect_uri safe in OAuth/OIDC, is not enforced for the prompt=none error-return path. A client_id is not a secret: client metadata is retrievable at /api/oidc/clients/:id/meta, and client_ids appear in any integration's authorization links. Confirmation that the bypass is purely frontend: an unauthenticated POST to the backend /api/oidc/authorize endpoint correctly returns 401 ({"error":"You are not signed in"}), so the backend never authorizes the request. The redirect nonetheless happens in the browser because +page.svelte issues window.location.href before/without a successful backend authorization. A second variant exists for an authenticated victim: when prompt=none is combined with a first-time (not yet consented) authorization of a client, the same client-side path can be reached. Contrast: the standard interactive flow (no prompt=none) posts to the backend, which validates redirect_uri against the registered list before returning a callback. The defect is specific to the client-side prompt=none short-circuit. ### PoC Prerequisites: a running pocket-id instance, a registered OIDC client whose client_id is known to the attacker (obtainable from /api/oidc/clients/:id/meta or any existing integration), and a victim whose browser opens the link (the victim need not be logged in for the login_required branch). 1. Attacker constructs an authorization URL pointing at the victim's pocket-id, supplying an external redirect_uri and prompt=none: https://idp.victim.example/authorize?client_id=<known_client_id>&redirect_uri=https://attacker.example/collect&response_type=code&scope=openid&prompt=none 2. Victim opens the link. The frontend authorize page loads, determines the silent auth cannot succeed (login_required), and executes: window.location.href = "https://attacker.example/collect?error=login_required&state=..." 3. The browser is redirected to https://attacker.example/collect. Expected result on a fixed build: the page would refuse the redirect because redirect_uri does not match the client's registered callback list and would render an error in place instead of navigating off-origin. Validation level: code-level confirmation at commit fc42f62. This is a browser-side window.location.href redirect, so it is not reproducible with curl; the backend was confirmed to reject the unauthenticated request (401) while the frontend performs the navigation regardless. Evidence notes saved to screenshots/001_open_redirect_evidence.txt. ### Impact Unauthenticated attacker, victim interaction required (clicking or being silently redirected). The trusted pocket-id domain is used to bounce a victim to an arbitrary external site, which is effective for credential phishing (the user trusts the IdP origin in the initial link) and for leaking OIDC error/state parameters to an attacker endpoint. Integrity impact is limited to redirection; no confidentiality or availability loss of pocket-id itself. Note: an abandoned PR (#1450) addressed a related protocol-relative URL issue in a different email-redirect path but was not merged and does not cover this authorize-page path.

CVE-2026-55834 Affected Github.com/pocket id/pocket id/backend Versions

1 component(s)
Fixed Versions:
2.9.0
Product / Package Ecosystem Affected Versions Fixed Version
github.com/pocket-id/pocket-id/backend
Go
≥ 2.6.0
< 2.9.0
2.9.0

References

Frequently Asked Questions

What is CVE-2026-55834?
CVE-2026-55834 is a security vulnerability in Github.com/pocket id/pocket id/backend involving Pocket-ID has an Open Redirect on the OIDC /authorize page via unvalidated redirect_uri with prompt=none under CWE-601: URL Redirection to Untrusted Site ('Open Redirect').
Which Github.com/pocket id/pocket id/backend versions are affected?
Affected versions include releases prior to 2.9.0 across affected packages: github.com/pocket-id/pocket-id/backend.
What version fixes CVE-2026-55834?
Upgrading to 2.9.0 (or the latest patched release for your respective branch) resolves the vulnerability.
Is github.com/pocket-id/pocket-id/backend affected?
Yes, github.com/pocket-id/pocket-id/backend is affected in releases prior to 2.9.0. Upgrade your dependency to 2.9.0 or later.
What is the CVSS score of CVE-2026-55834?
CVE-2026-55834 has a CVSS v3.1 base score of 4.3 (MODERATE) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N.
What CWE is associated with CVE-2026-55834?
CVE-2026-55834 is classified under CWE-601: URL Redirection to Untrusted Site ('Open Redirect') (The web application accepts a user-controlled input that specifies a link to an external site, and uses that link in a redirect.).
How can I check Go dependencies for CVE-2026-55834?
Run the dependency tree command: 'inspect dependencies for github.com/pocket-id/pocket-id/backend'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-2wvm-8mvp-22qv",
  "modified" : "2026-08-28T16:28:20Z",
  "published" : "2026-08-28T16:28:20Z",
  "aliases" : [ "CVE-2026-55834" ],
  "summary" : "Pocket-ID has an Open Redirect on the OIDC /authorize page via unvalidated redirect_uri with prompt=none",
  "details" : "### Summary\nThe OIDC authorization page in the pocket-id frontend redirects the browser to an attacker-controlled URL without consulting the backend redirect_uri allow-list when the request uses prompt=none. An attacker who knows a valid client_id can craft an /authorize link that sends a victim (or a victim's browser doing a silent re-auth) to any external https URL, enabling phishing and OAuth response smuggling. The backend allow-list validation that protects the normal authenticated flow is bypassed because this path is handled entirely client-side.\n\n### Details\nFor an OIDC authorization request with prompt=none, the SvelteKit frontend short-circuits the flow before the backend ever validates the redirect_uri against the client's registered callback list.\n\nFile: frontend/src/routes/authorize/+page.ts (line 14) parses the raw redirect_uri query parameter from the incoming URL.\n\nFile: frontend/src/routes/authorize/+page.svelte - in onMount(), when the request carries prompt=none and the user cannot be silently authorized (for example the visitor is not logged in, so login_required must be returned), the page builds the callback URL from the raw redirect_uri and performs:\n\n    window.location.href = `${callbackURL}?error=login_required...`\n\nThe callbackURL is taken directly from the user-supplied redirect_uri. The only filtering applied is a scheme check that blocks javascript: and data: URLs; any http: or https: origin passes through. The backend allow-list validator GetCallbackURLFromList (which the authenticated code path uses to confirm the redirect_uri matches one of the client's registered callback URLs) is never invoked on this branch.\n\nThis means the per-client redirect_uri allow-list, the central control that makes redirect_uri safe in OAuth/OIDC, is not enforced for the prompt=none error-return path. A client_id is not a secret: client metadata is retrievable at /api/oidc/clients/:id/meta, and client_ids appear in any integration's authorization links.\n\nConfirmation that the bypass is purely frontend: an unauthenticated POST to the backend /api/oidc/authorize endpoint correctly returns 401 ({\"error\":\"You are not signed in\"}), so the backend never authorizes the request. The redirect nonetheless happens in the browser because +page.svelte issues window.location.href before/without a successful backend authorization.\n\nA second variant exists for an authenticated victim: when prompt=none is combined with a first-time (not yet consented) authorization of a client, the same client-side path can be reached.\n\nContrast: the standard interactive flow (no prompt=none) posts to the backend, which validates redirect_uri against the registered list before returning a callback. The defect is specific to the client-side prompt=none short-circuit.\n\n### PoC\nPrerequisites: a running pocket-id instance, a registered OIDC client whose client_id is known to the attacker (obtainable from /api/oidc/clients/:id/meta or any existing integration), and a victim whose browser opens the link (the victim need not be logged in for the login_required branch).\n\n1. Attacker constructs an authorization URL pointing at the victim's pocket-id, supplying an external redirect_uri and prompt=none:\n\n   https://idp.victim.example/authorize?client_id=<known_client_id>&redirect_uri=https://attacker.example/collect&response_type=code&scope=openid&prompt=none\n\n2. Victim opens the link. The frontend authorize page loads, determines the silent auth cannot succeed (login_required), and executes:\n\n   window.location.href = \"https://attacker.example/collect?error=login_required&state=...\"\n\n3. The browser is redirected to https://attacker.example/collect. Expected result on a fixed build: the page would refuse the redirect because redirect_uri does not match the client's registered callback list and would render an error in place instead of navigating off-origin.\n\nValidation level: code-level confirmation at commit fc42f62. This is a browser-side window.location.href redirect, so it is not reproducible with curl; the backend was confirmed to reject the unauthenticated request (401) while the frontend performs the navigation regardless. Evidence notes saved to screenshots/001_open_redirect_evidence.txt.\n\n### Impact\nUnauthenticated attacker, victim interaction required (clicking or being silently redirected). The trusted pocket-id domain is used to bounce a victim to an arbitrary external site, which is effective for credential phishing (the user trusts the IdP origin in the initial link) and for leaking OIDC error/state parameters to an attacker endpoint. Integrity impact is limited to redirection; no confidentiality or availability loss of pocket-id itself. Note: an abandoned PR (#1450) addressed a related protocol-relative URL issue in a different email-redirect path but was not merged and does not cover this authorize-page path.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Go",
      "name" : "github.com/pocket-id/pocket-id/backend"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "2.6.0"
      }, {
        "fixed" : "2.9.0"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 2.8.0"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/pocket-id/pocket-id/security/advisories/GHSA-2wvm-8mvp-22qv"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/pocket-id/pocket-id/commit/8a7577497131229badb35cb4b3a4227b1300afff"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/pocket-id/pocket-id"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/pocket-id/pocket-id/releases/tag/v2.9.0"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-601" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-08-28T16:28:20Z",
    "nvd_published_at" : null
  }
}