Skip to content

Bedrock SigV4 signing includes Connection header, causing 401 signature mismatch through Mantle #3563

Description

@cpsievert

Summary

BedrockOpenAI signs the hop-by-hop Connection request header. In our environment, that header changes between the SDK and Bedrock Mantle, so Bedrock calculates a different SigV4 canonical request and rejects valid AWS SSO credentials with HTTP 401.

This reproduces with openai==2.52.0 using BedrockOpenAI directly, without any downstream wrapper.

Minimal reproduction

from openai import BedrockOpenAI

client = BedrockOpenAI(
    aws_region="us-east-1",
    base_url="https://bedrock-mantle.us-east-1.api.aws/openai/v1",
)

client.responses.create(
    model="openai.gpt-5.6-sol",
    input="What is 1 + 1? Reply with only the number.",
)

The AWS credentials are valid:

aws sts get-caller-identity

The request fails with AuthenticationError, HTTP 401, and Bedrock reports that its calculated request signature does not match the submitted signature.

Diagnosis

Immediately before transport, the SDK signs:

Connection: keep-alive

Bedrock's canonical-request diagnostic shows it received:

connection:

Connection is a hop-by-hop header, so intermediaries may alter or remove it. Signing it makes the SigV4 signature depend on a value that is not stable end-to-end.

A temporary client-level workaround confirms this diagnosis:

import httpx
from openai import BedrockOpenAI

client = BedrockOpenAI(
    aws_region="us-east-1",
    base_url="https://bedrock-mantle.us-east-1.api.aws/openai/v1",
    http_client=httpx.Client(headers={"Connection": ""}),
)

response = client.responses.create(
    model="openai.gpt-5.6-sol",
    input="What is 1 + 1? Reply with only the number.",
)
assert response.output_text == "2"

Independent patch validation

I cloned the current main branch, reproduced the direct SDK failure, and added a regression test that signs a request containing Connection: keep-alive. On the current implementation, connection appears in both the signed headers and the SigV4 SignedHeaders list.

I then made the minimal local patch in src/openai/lib/_bedrock_auth.py: exclude connection before constructing the AWSRequest passed to SigV4Auth.

With only that change:

  • The new regression test passes.
  • pytest tests/lib/test_bedrock_auth_conformance.py -q -n 0 passes: 21 passed.
  • Ruff check and format check pass.
  • The same direct live BedrockOpenAI request above succeeds without a custom http_client and returns 2.

Suggested fix

Exclude connection from the header mapping passed to the Bedrock SigV4 signer. This is the smallest change that fixes the live reproduction and avoids signing a hop-by-hop header that can be rewritten in transit.

I intentionally omitted the raw AWS error body because it can echo temporary session-token values.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions