daax-dev / daax-dev/daax-web

Agent View cannot authenticate on Linux hosts: reads carry no identity and the daemon's local trust is listener-scoped

Open
#494 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
1
Forks
1
Avg merge
12h 20m
Merged PRs (30d)
13

Description

Follow-up to #493, which fixed the Host rejection and made Agent View work on the macOS workstation. It does not make it work on the Linux fleet hosts, and this is why.

Why macOS works

agentd's local-trust rule reads a fact about the socket, not the caller (internal/api/authmiddleware.go):

Three rules in this package read "did this arrive on the loopback listener": whether raw payloads are served (ADR 0014), whether the settings write is answered, and now whether a session is required.

agentd listens on 127.0.0.1:7717. On Docker Desktop the container's connection arrives on that loopback listener, so no session is required and fetchDaemon — which sends only Accept — is served. Verified: /api/agentview/agents returns 200 with live agents after #493.

Why Linux cannot do the same

On a Linux host the container reaches the host over the bridge (172.22.0.1 / 172.17.0.1), so:

  1. agentd on 127.0.0.1 simply refuses the connection — nothing is listening on the bridge address.
  2. Rebinding it to the bridge (or 0.0.0.0) makes it an off-loopback listener, and then --auth=oidc requires a session on every request.
  3. fetchDaemon carries no credential at all, so those reads become 401.

Measured on all three Linux hosts before #493:

agentd bind:  127.0.0.1:7717
extra_hosts:  []                      <- fixed in #493
container -> host.docker.internal:7717 -> 000 (name did not resolve)

Two ways out, both with a real cost

A. Reads vouch for the caller. Extend the GET path in app/api/agentview/[...path]/route.ts to do what the POST path already does — deriveAuthContext(req.headers) — and have fetchDaemon send the proxy proof + identity headers, exactly as postDaemonSignal does. agentd already has the matching side (--trusted-proxy-secret-file, --trusted-proxy-proof-header, --trusted-identity-header); the workstation is already configured with all three. This is the architecturally intended shape: the daemon should know who is reading, and today reads only work because Docker Desktop happens to make the caller look local.

Cost: reads start asserting identity, so the assertion path needs the same scrutiny the signal path got, and every Linux host needs --trusted-proxy <bridge CIDR> added.

B. Forward the bridge to loopback on the host. A systemd-socket-proxyd/socat unit listening on the bridge gateway and connecting to 127.0.0.1:7717. No code change; the daemon keeps its loopback listener and reads stay free.

Cost: it extends the daemon's local trust to every container on the host, silently. That is a real widening of a boundary the listener rule exists to draw, and it should not be done just because it is the smaller diff.

Recommendation

(A). (B) buys a config-only fix by giving away the property the loopback rule is protecting.

Note postDaemonSignal already sends X-Forwarded-For: 127.0.0.1, which trips the daemon's own "a loopback request carrying a forwarding header is treated as remote" tripwire — and compensates by carrying proof + identity. Reads would follow the same pattern.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with app/api/agentview/[...path]/route.ts, comparing the GET path with the existing postDaemonSignal flow and its deriveAuthContext usage. Read fetchDaemon and internal/api/authmiddleware.go to understand the proxy proof, identity headers, and listener trust rules. Done means Agent View reads authenticate and return live agents on Linux hosts without widening loopback trust.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, linux, typescript
Domain
api, authentication, backend, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.