# Custom headers being stripped before reaching application - is this expected?

**URL:** <https://linkerd.buoyant.io/t/custom-headers-being-stripped-before-reaching-application-is-this-expected/821>\
**Category:** Linkerd General Discussion\
**Tags:** proxy, configuration\
**Created:** [October 31, 2025, 6:06pm UTC](https://linkerd.buoyant.io/t/custom-headers-being-stripped-before-reaching-application-is-this-expected/821 "2025-10-31T18:06:09Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![JonathanGill](https://yyz1.discourse-cdn.com/flex029/user_avatar/linkerd.buoyant.io/jonathangill/32/248_2.png) [@JonathanGill](https://linkerd.buoyant.io/u/JonathanGill)\
**Post date:** [October 31, 2025, 6:06pm UTC](https://linkerd.buoyant.io/t/custom-headers-being-stripped-before-reaching-application-is-this-expected/821/1 "2025-10-31T18:06:09Z")

</div>

I’ve been debugging why custom HTTP headers aren’t reaching our application in a Linkerd-injected environment, and I’ve narrowed it down to the proxy layer. I’m wondering if this is expected behavior or if there’s a configuration I’m missing.

**Setup**

- Linkerd edge-25.9.1 on AWS EKS
- Simple traffic path: ALB → Linkerd proxy → nginx → PHP app
- Server resource with proxyProtocol: HTTP/1 and accessPolicy: deny with an AuthorizationPolicy allowing all traffic

**What’s happening**

When I send custom headers like X-Force-Tracking: 1 or X-Test-Debug-Header: test, they never reach nginx or the application. But AWS infrastructure headers like X-Amzn-Trace-Id come through fine.

I added logging to nginx to see what it receives:

```auto
{
“x_force_tracking”: “”, // empty
“x_test_debug_header”: “”, // empty
“x_amzn_trace_id”: “Root=1-6904…” // present
}

```

So the headers are being stripped somewhere between the ALB and nginx.

**What I’ve tested**

I have an identical environment without Linkerd injection where the same headers work perfectly. Same ALB config, same nginx config, same app code. The only difference is the Linkerd injection.

**I tried:**

- Different header names (tested 6 variations including ones without the X- prefix)
- Changing proxyProtocol from HTTP/1 to unknown
- Changing accessPolicy from deny to all-unauthenticated
- Verified ALB has drop\_invalid\_header\_fields=true on both environments

None of that made any difference. Custom headers are consistently stripped while infrastructure headers pass through.

**What I’m trying to do**

We need to implement debug tracing where developers can send a custom header to trigger detailed logging/tracing on specific requests. Pretty standard debugging pattern but it doesn’t work with Linkerd in the mix.

**Questions**

Is this expected behavior? Is there some proxy configuration or annotation that controls which headers get passed through? I couldn’t find anything in the docs about this.

If this is by design, what’s the recommended workaround? Query parameters? Cookies? Or is there a way to whitelist certain header patterns?

Any help appreciated. I’ve spent about 7 hours systematically testing this and I’m confident the stripping is happening in the proxy, but I can’t figure out why or how to control it.

```auto
  ---
  Environment details if needed:
  apiVersion: policy.linkerd.io/v1beta3
  kind: Server
  spec:
    podSelector:
      matchLabels:
        app: raven
    port: 8080
    proxyProtocol: HTTP/1
    accessPolicy: deny

  ---

```

---

<div class="post-metadata">

**Author:** ![william](https://yyz1.discourse-cdn.com/flex029/user_avatar/linkerd.buoyant.io/william/32/5_2.png) [@william](https://linkerd.buoyant.io/u/william)\
**Post date:** [October 31, 2025, 6:08pm UTC](https://linkerd.buoyant.io/t/custom-headers-being-stripped-before-reaching-application-is-this-expected/821/2 "2025-10-31T18:08:59Z")

</div>

That is surprising to me…. in part because I have just been updating some [older docs](https://linkerd.io/2-edge/tasks/distributed-tracing/#proxy-header-propagation) that state that Linkerd will generally propagate unknown headers to allow for distributed tracing. Maybe @Flynn has some ideas?

---

<div class="post-metadata">

**Author:** ![Flynn](https://yyz1.discourse-cdn.com/flex029/user_avatar/linkerd.buoyant.io/flynn/32/41_2.png) [@Flynn](https://linkerd.buoyant.io/u/Flynn)\
**Post date:** [October 31, 2025, 8:35pm UTC](https://linkerd.buoyant.io/t/custom-headers-being-stripped-before-reaching-application-is-this-expected/821/3 "2025-10-31T20:35:08Z")

</div>

This is very strange – I regularly demo using a custom “x-faces-user” header for A/B testing with an HTTPRoute, and it works fine (I just doublechecked it with edge-25.9.4 and edge-25.10.7). The architecture here is:

web browser → `faces-gui` → `face` → `smiley`

with everything other than the browser in the mesh, and with `faces-gui` acting as the ingress. There’s an HTTPRoute doing header-based routing on `x-faces-user` for the `smiley` workload, so the header has to be propagated multiple times.

To state the obvious, I’m using neither an ALB nor nginx, but I feel confident in ruling out Linkerd. I actually don’t know of a way to even force Linkerd to strip headers… 🤔

---

<div class="post-metadata">

**Author:** ![JonathanGill](https://yyz1.discourse-cdn.com/flex029/user_avatar/linkerd.buoyant.io/jonathangill/32/248_2.png) [@JonathanGill](https://linkerd.buoyant.io/u/JonathanGill)\
**Post date:** [November 3, 2025, 9:23am UTC](https://linkerd.buoyant.io/t/custom-headers-being-stripped-before-reaching-application-is-this-expected/821/4 "2025-11-03T09:23:02Z")

</div>

Thank you both!

I had a feeling it was something I was doing, or not doing. So this confirmation helps me dig further into what Ive got configured wrong.

Ill update with what I find and what the ultimate fix is, just incase someone else faces similar issues later.
