---
title: "ADR-0008: Check every redirect hop and bind credentials to their origin"
manual: "HTTP Guard"
version: "main"
permalink: "https://docs.typo3.org/permalink/netresearch/nr-http-guard:adr-0008@main"
source: "Adr/ADR-0008-RedirectsAndCredentials.rst"
rendered: "2026-10-18T14:31:38+00:00"
---

# ADR-0008: Check every redirect hop and bind credentials to their origin {#adr-0008}

-   *Status:* Historical proposal (original status: Proposed)
-   *Date:* 2026-10-08
-   *Original decision makers:*

    Project architecture/security owners; approval
    still pending in the original proposal.

-   *Requirements:* HG-017, HG-023, HG-024, HG-025
-   *Original supersession:* None; a new decision for the proposed product.

> [!NOTE]
> This is the full English translation of the historical proposal dated
> 2026-10-08, originally Proposed. Its pending approval is historical and
> creates no additional alpha approval gate. Current
> [Security model and limits](https://docs.typo3.org/permalink/netresearch/nr-http-guard:security@main), [Development and tests](https://docs.typo3.org/permalink/netresearch/nr-http-guard:development@main), [Verification report](https://docs.typo3.org/permalink/netresearch/nr-http-guard:verification-report@main) and
> [Requirements and security invariants](https://docs.typo3.org/permalink/netresearch/nr-http-guard:development-requirements@main) describe the operative scope and evidence.
>
> The later single-package decision is recorded in [ADR-0015: One installable extension](https://docs.typo3.org/permalink/netresearch/nr-http-guard:adr-0015@main).

## Context {#adr-0008-context}

An allowed initial URL can redirect to an internal target. Even exclusively
public targets may receive confidential bodies or custom authentication
headers. Generic middleware cannot reliably recognize these secrets. Guzzle
processes redirects outside custom handlers, and PSR-18 sends do not follow
automatically.

Sources: `[S01, S05, S15, S20]`.

## Decision {#adr-0008-decision}

The generic client applies same-origin policy. Every followed Location is
checked after response middleware; the next attempt needs a new
ConnectionPlan. Scheme, host and effective port form the origin. HTTPS
downgrades are prohibited. A profile can disable following entirely.

A separate public-fetch client may follow cross-origin redirects, but only as
GET/HEAD without a body, cookies, client certificate, authorization or freely
supplied headers. This client must not inherit global credential defaults. The
next address must satisfy public policy again.

The effective follow mode and hop limit are validated against operator policy.
An excessive limit already captured by the outer Guzzle redirect code is
rejected, rather than appearing bounded by an ineffective inner option change.
Custom wrappers set correct limits when constructing the client/request.
`allow_redirects=false` and PSR-18 return 30x unchanged.

Retry logic remains with the caller; every genuinely new attempt is authorized
again. Policy errors are not a reason for automatic retries.

## Rejected alternatives {#adr-0008-rejected-alternatives}

-   **Block only private redirect targets:** does not prevent credentials
    reaching public attacker targets.
-   **Remove known authentication headers:** misses custom headers and body
    data.
-   **Block every redirect:** unnecessary for same-origin/public fetch.
-   **Inner clamp without effect on outer redirect state:** a false security
    promise.

## Consequences {#adr-0008-consequences}

Generic requests with legitimate cross-origin redirects may break. The safe
special-purpose API deliberately has a small input surface. Method changes and
hop limits must be tested specifically for each major.

## Evidence and acceptance in the original proposal {#adr-0008-verification-and-acceptance}

`T045, T046, T047, T048, T049, T050, T051, T052, T081`. Details and
expected results are in [Original verification specification](https://github.com/netresearch/typo3_http_guard/blob/3f929ae8794ca04ab3dd25627e94d601a2db23e0/specification/specs/06-verification.md). These tests
were specified, not executed as part of the original documentation delivery.

## Reasons to reconsider {#adr-0008-reassessment-trigger}

An API for credential-bearing cross-origin redirects would introduce a new
authorization model and requires explicit target/credential permissions and
its own ADR.

## Related documents {#adr-0008-related-documents}

[Original ADR](https://github.com/netresearch/typo3_http_guard/blob/3f929ae8794ca04ab3dd25627e94d601a2db23e0/specification/adr/ADR-0008-redirects-und-credential-grenzen.md), [Original product requirements](https://github.com/netresearch/typo3_http_guard/blob/3f929ae8794ca04ab3dd25627e94d601a2db23e0/specification/specs/01-product-requirements.md), [Original security model](https://github.com/netresearch/typo3_http_guard/blob/3f929ae8794ca04ab3dd25627e94d601a2db23e0/specification/specs/02-security-model.md),
[Original architecture](https://github.com/netresearch/typo3_http_guard/blob/3f929ae8794ca04ab3dd25627e94d601a2db23e0/specification/specs/03-architecture.md) and [Original source catalogue](https://github.com/netresearch/typo3_http_guard/blob/3f929ae8794ca04ab3dd25627e94d601a2db23e0/specification/specs/08-evidence-and-sources.md) (`S01-S23`),
plus the [ADR index](https://docs.typo3.org/permalink/netresearch/nr-http-guard:adr-index@main). [Original sources](https://docs.typo3.org/permalink/netresearch/nr-http-guard:adr-original-sources@main) explains
the immutable source index.
