Repository navigation
[RefImpl] Harden the trace exporter's file and endpoint handling, and the spans it vouches for #283
Copy link
Copy link
Open
Labels
priority:P2Maintainers onlyMaintainers onlyscope:in-focusFeeds the ninety-day committed outcome. Maintainers onlyFeeds the ninety-day committed outcome. Maintainers onlystatus:acceptedIn the backlog. Maintainers onlyIn the backlog. Maintainers onlytype:refimplReference implementation or adapter workReference implementation or adapter workworkstream:refimplOwning workstream. Maintainers onlyOwning workstream. Maintainers only
Milestone
Description
Target runtime or language
AGT reference Guardian: packages/guardian/src/otel-trace-exporter.ts, server.ts
What this proves
This is part of issue #274, the second of three slices.
The exporter's file and network handling must not leak trace content or write through a link. Spans must not carry a request pair that the Guardian cannot vouch for.
Scope, with no blocker:
- File opens.
- On every append, open with
O_WRONLY|O_APPEND|O_CREAT|O_NOFOLLOW|O_NONBLOCK, thenfstatthe descriptor. - Refuse when the path is not a regular file, or when the effective user doesn't own it. Otherwise set mode 0600 with
fchmod. - Do not refuse a file only because its mode is wider. PR Batch Guardian log writes and drain them on shutdown #112 keeps existing file modes, so the rule here should tighten the mode, not refuse.
fs.promises.appendFilewithO_NOFOLLOWstill follows a symlink in Bun 1.3.14, so useopenpluswrite.- Refuse a parent directory that the user doesn't own, or that others can write to.
- On Windows,
O_NOFOLLOWdoes not exist. Write the Windows behavior as a documented branch, and give it a test.
- On every append, open with
- Non-loopback
http://endpoint. Build no endpoint output unless an explicit opt-in variable is set. IfOTEL_EXPORTER_OTLP_*HEADERSis set, refuse even with the opt-in, because the headers can carry credentials. Decide what counts as loopback from the parsed address (127.0.0.0/8,::1,::ffff:127.0.0.1), not with string checks. Document TLS and headers in the Guardian README. - Steps open at shutdown. If a step is still open and older than the timeout, give it class
timeout, notother. elapsed_ms. A late decision must never showelapsed_msequal totimeout_ms. Fix the rounding.- Error codes. Clamp oversized error codes so they never overflow int64.
Scope that waits for a decision:
- Spans the Guardian cannot vouch for. Today, re-posting a real pair puts three events on that pair's span: an allow, a
guardian_error, and a deny. The schema-invalid re-post comes back as a deny withenvelope_invalid, not as an error, so a rule that looks only at error responses misses it. The proposed rule is that the Guardian puts a pair on a span only when it can vouch for it. @bar-capsule, please decide how such a span is represented: is it dropped, or written under names outsidestep_to_span? After PR fix(agt): implement ACS-Core wire safeguards #229 lands, "vouch" means the signature verified. - The signal path (
main.ts,process.once, the second SIGTERM). This waits for PR Batch Guardian log writes and drain them on shutdown #112, which rewrites the same lines.
Acceptance tests:
- File opens. A symlink at the final path is refused. A symlink in the parent directory is refused. A hardlink is refused. An existing 0644 file ends up 0600.
- Endpoint.
http://10.0.0.1:4318gives no endpoint output and a report. With the opt-in, it gives output plus a warning. With the opt-in and a headers variable set, it is refused. - Re-post. Replaying the four re-posts from the issue Trace exporter follow-ups from the PR #244 review #274 premortem leaves exactly one span carrying the real pair.
Do you intend to implement this yourself
Yes. @sabasiddique1 is implementing it after the first slice is in review. The reviewer is @rocklambros.
Current Priority Scope
Feeds the runnable Guardian reference implementation
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
priority:P2Maintainers onlyMaintainers onlyscope:in-focusFeeds the ninety-day committed outcome. Maintainers onlyFeeds the ninety-day committed outcome. Maintainers onlystatus:acceptedIn the backlog. Maintainers onlyIn the backlog. Maintainers onlytype:refimplReference implementation or adapter workReference implementation or adapter workworkstream:refimplOwning workstream. Maintainers onlyOwning workstream. Maintainers only
Type
Projects
- StatusShow more project fieldsAccepted
Activity
sabasiddique1 commentedon Oct 15, 2026
I’ll pick this up once #282 is in review.
bar-capsule commentedon Oct 17, 2026
@rocklambros @sabasiddique1 keep them under separate names. A forged or replayed request is worth seeing, so dropping it would hide the attack, but it should never be recorded under the genuine request's IDs.