Summary
Correctness and API-consistency bugs in the servers that are individually small but collectively erode trust in ingest/query results.
Locations
- Jaeger prefix-integer parsing truncates garbage:
traces query.rs:801-811 parse_integer_prefix("17junk")→17 (pinned by test at :866); overflow on start/end degrades to unbounded (None) instead of 400 — fail-open to a wider scan. Dashboard since/until correctly use exact parse (:787-795).
- Logs ingest fabricates data:
logs api.rs:1670-1699 unparseable time falls back to now(); unknown level canonicalizes to "info" (:1657-1668). A typo'd column silently shifts rows instead of counting an error. parse_query_time (:1702-1712) is correctly strict-ish on the query side.
authctl parse_ttl overflow: timeless-authctl/src/lib.rs:313-330 quantity * 86_400 on i64 wraps (release) / panics (debug). Use checked_mul.
authctl policy init audience drift: lib.rs:143 emits timeless-{signal} while verifier fixtures use timeless-data-plane (auth.rs:1437-1438). Works (mint copies from policy) but cross-implementation tokens and docs disagree — pin one.
kid comment lies: authctl lib.rs:44-61 says "first 16 hex of SHA-256", code takes first 8 raw pubkey bytes. Fix comment or hash.
policy add-subject overwrites silently + accepts arbitrary scopes (lib.rs:171-189); verifier rejects at use time (fail-closed) but CLI gives no feedback.
- Clock-skew asymmetry:
auth.rs:677-681 gives +30 s leeway to nbf/iat but none to exp — 1 s-skewed clients see spurious expired_token.
enforce_query_limit heuristic (auth.rs:567-572): non-UTF8 skips; form-field scan false-positives on ingest bodies while {"limit":…} JSON bodies aren't caught. Verify every JSON query path sets RESULT_ROWS_HEADER so the post-check (:456-467) fires.
- Tail ordering differs: traces publishes after durable accept (
traces api.rs:461-469, deliberate); logs publishes before writer send (logs storage.rs:1211-1214) — a logs subscriber can see entries a search never returns.
- Backup blocks the single writer: logs
storage.rs:1690-1704 (flush + up to 1M optimize steps + checkpoint with 5 s retry) runs synchronously; repeated POST /api/v1/backup (open by default) is a throughput DoS. Same shape in metrics/traces.
- No shutdown deadline:
storage.rs:1579-1613 sequencing vs hung checkpoint_wal (lib.rs:58-79) can stall past orchestrator kill grace.
- API inconsistency: flush GET vs POST varies per signal; error envelopes vary (
{"error"} vs {"status":"error"} vs Prometheus shape); RESULT_ROWS_HEADER stripped on authed routes but emitted on open ones (auth.rs:456-467); no Retry-After/RateLimit-* on 429/503; logs field_values limit dance (api.rs:352-359) is obscure.
Also: unbounded regex compile per request (metrics query.rs:149-166, logs LogPredicate::Regex) with no pattern-length cap; PromQL parse input bounded only by the 10 MiB body cap with no depth cap; OTLP/log ingest admission bounded by batch count not spans/bytes (traces storage.rs:590-645, logs storage.rs:1193-1217).
Suggested fix
Exact integer parsing + bounded limits; strict ingest time/level handling; checked_mul TTL; one audience value; symmetric clock leeway; one tail contract; backup off the writer or rate-limited; shutdown deadline; one error envelope ({"error","reason"} + Prometheus shape on Prometheus routes); POST-only flush.
Source
Full code review @ bacdf6f, servers track.
Summary
Correctness and API-consistency bugs in the servers that are individually small but collectively erode trust in ingest/query results.
Locations
traces query.rs:801-811parse_integer_prefix("17junk")→17(pinned by test at:866); overflow on start/end degrades to unbounded (None) instead of 400 — fail-open to a wider scan. Dashboardsince/untilcorrectly use exact parse (:787-795).logs api.rs:1670-1699unparseable time falls back tonow(); unknown level canonicalizes to"info"(:1657-1668). A typo'd column silently shifts rows instead of counting an error.parse_query_time(:1702-1712) is correctly strict-ish on the query side.authctl parse_ttloverflow:timeless-authctl/src/lib.rs:313-330quantity * 86_400oni64wraps (release) / panics (debug). Usechecked_mul.authctl policy initaudience drift:lib.rs:143emitstimeless-{signal}while verifier fixtures usetimeless-data-plane(auth.rs:1437-1438). Works (mint copies from policy) but cross-implementation tokens and docs disagree — pin one.kidcomment lies:authctl lib.rs:44-61says "first 16 hex of SHA-256", code takes first 8 raw pubkey bytes. Fix comment or hash.policy add-subjectoverwrites silently + accepts arbitrary scopes (lib.rs:171-189); verifier rejects at use time (fail-closed) but CLI gives no feedback.auth.rs:677-681gives +30 s leeway to nbf/iat but none to exp — 1 s-skewed clients see spuriousexpired_token.enforce_query_limitheuristic (auth.rs:567-572): non-UTF8 skips; form-field scan false-positives on ingest bodies while{"limit":…}JSON bodies aren't caught. Verify every JSON query path setsRESULT_ROWS_HEADERso the post-check (:456-467) fires.traces api.rs:461-469, deliberate); logs publishes before writer send (logs storage.rs:1211-1214) — a logs subscriber can see entries a search never returns.storage.rs:1690-1704(flush + up to 1M optimize steps + checkpoint with 5 s retry) runs synchronously; repeatedPOST /api/v1/backup(open by default) is a throughput DoS. Same shape in metrics/traces.storage.rs:1579-1613sequencing vs hungcheckpoint_wal(lib.rs:58-79) can stall past orchestrator kill grace.{"error"}vs{"status":"error"}vs Prometheus shape);RESULT_ROWS_HEADERstripped on authed routes but emitted on open ones (auth.rs:456-467); noRetry-After/RateLimit-*on 429/503; logsfield_valueslimit dance (api.rs:352-359) is obscure.Also: unbounded regex compile per request (metrics
query.rs:149-166, logsLogPredicate::Regex) with no pattern-length cap; PromQL parse input bounded only by the 10 MiB body cap with no depth cap; OTLP/log ingest admission bounded by batch count not spans/bytes (traces storage.rs:590-645,logs storage.rs:1193-1217).Suggested fix
Exact integer parsing + bounded limits; strict ingest time/level handling;
checked_mulTTL; one audience value; symmetric clock leeway; one tail contract; backup off the writer or rate-limited; shutdown deadline; one error envelope ({"error","reason"}+ Prometheus shape on Prometheus routes); POST-only flush.Source
Full code review @
bacdf6f, servers track.