Skip to main content

Early Review of draft-ietf-rats-coserv-07
review-ietf-rats-coserv-07-httpdir-early-pardue-2026-08-14-00

Request Review of draft-ietf-rats-coserv
Requested revision No specific revision (document currently at 07)
Type Early Review
Team HTTP Directorate (httpdir)
Deadline 2026-07-31
Requested 2026-06-29
Requested by Mike Bishop
Authors Paul Howard , Thomas Fossati , Henk Birkholz , Shefali Kamal , Giridhar Mandyam , Ding Ma
I-D last updated 2026-07-22 (Latest revision 2026-07-06)
Completed reviews Httpdir Early review of -07 by Lucas Pardue
Comments
Per request from RATS chairs
Assignment Reviewer Lucas Pardue
State Completed
Request Early review on draft-ietf-rats-coserv by HTTP Directorate Assigned
Reviewed revision 07
Result Not ready
Completed 2026-08-14
review-ietf-rats-coserv-07-httpdir-early-pardue-2026-08-14-00
The document defines a query/response format named CoSERV that operates with the
RATS architecture. In addition, a concrete "API binding" describes how HTTP can
be used to transfer the CoSERV query and response. This binding pays special
attention to request format and its role in HTTP caching, which appears to
address operation performance goals. A CoSERV query is serialized into a URI
using a well defined mechanism and sent in an HTTP request; a CoSERV response is
serialized in a new media type that is sent as response content. The document
also defines a discovery mechanism based on /.well-known.

I apologise for posting the review later than the deadline (2026-07-31). I
wanted to ensure I could give a thorough review. Having now completed that, I
feel obliged to record a "Not Ready" result. There are some fundamental issues
related to caching that raise questions that likely need to be answered by
the WG/authors. I do not think these issues are _that_ complicated but resolving
them now will help avoid future interop issues (especially within the HTTP
ecosystem that the design seems to want to leverage).

I have no background knowledge of RATS and so have focused the httpdir review on
HTTP topics, and only touched the RATS / CoSERV aspects needed to facilitate
understanding the HTTP parts. Therefore, I may have misunderstood something at
that layer. I am also not an HTTP caching expert, so have reviewed those aspects
only to the best of my capability. To complete this review, I performed a manual
review, combined with an automated review based on tooling in the repo
https://github.com/mnot/ietf-skill, and Claude to assist with background,
research, and cross referencing. I have checked and validated the review outcome
to the best of my ability. All text in this review report has been manually
generated based on the above and may still have mistakes.

# Major issues

1. Privacy concerns of the caching design wrt HTTP caching

IIUC this topic has been discussed in the WG. However, I think the current text,
in combination with fundamental design choices wrt HTTP caching, leaves a
potential adjacent privacy issue.

A CoSERV query is serialized into a URI using a well defined, **deterministic**
mechanism and sent in an HTTP request e.g. GET
/coserv/{base64url-encoded-string}. The protocol expects this URI to be used as
a cache key. The data that forms the input to the CoSERV query can contain
sensitive information for a small anonymity set. In my simplified comprehension
of RATS terms, an `instance` can identify a single unique device or component,
while a `group` is a group whose anonymity is only as good as its size.

While the document addresses some of this topic in RATS terms, the use of
generic HTTP caching, IIUC, introduces some potential new threats. The HTTP
cache itself can become an oracle; the timing of serving responses can indicate
if someone has already queried the information. An attack could come in the form
of scraping a list of predictable identifiers (correlating to a deterministic
URI) to gain intel on instances or groups based on the performance of HTTP
results. A generic HTTP cache makes itself available to any generic client to
perform such an attack.

The AI tooling suggests that this has been touched on in issue 81 and 67.
However, the text following text in the document is likely insufficient to
address the oracle problem:

> Although reusing cached responses is generally desirable, clients that need to
> bypass the caching infrastructure can do so by specifying Cache-Control:
> no-cache in their requests.

This cache control directive affects one aspect, skipping any cached value and
going to origin. However, that doesn't prevent the issue. The result of the
no-cache request **can be stored in the cache**. Its unclear to me if the
authors meant to specify the usage of the **no-store** directive. Importantly,
other clients can do other things; if they can probe a shared cache with private
info, a side channel exists.

A possible improvement is to lean on HTTP's toolkit more. The "private"
directive might be appropriate for very-fine-grained information in the query
such as instance or group. This would stop caching for those queries while
allowing broader queries to benefit.

If the WG/authors agree this oracle is an issue but cannot find consensus on a
standard mitigation, then security consideration text that highlights the
threats and HTTP toolkit might be sufficient. Sometimes its really up to
deployments to decide on the privacy/performance tradeoff. The important thing
is the ensure no naive use of shared caching; an "off-the-shelf" caching HTTP
server might just do that.

2. Safe methods and HEAD

The document states "only safe HTTP methods are used" and goes on to specify how
GET is used to make queries. But this is not an s/methods/method editorial-level
matter.

RFC 9110 states "All general-purpose servers MUST support the methods GET and
HEAD. All other methods are OPTIONAL.".

This document is silent on HEAD, which is problematic. HEAD is functionally
equivalent to GET ("SHOULD send the same header fields in response to a HEAD
request as it would have sent if the request method had been GET), implying that
a CoSERV server would run the same processing as the GET request. Is that
desirable?

There's also some deeper consideration to make wrt caching. Various freshness
validators _could_ be used with GET. However, RFC 9111 Section 4.3.5 states how
HEAD requests interact with caching in the absence of conditional GET.

This issue is somewhat elevated by the lack of explicit guidance on validators,
see (3).

For the purposes of CoSERV, it may be appropriate to disallow HEAD. This would
prevent clients from having a cheap way to trigger work on the server (i.e. a
low-bandwidth CPU amplification attack). Safe methods can be trivially replayed
and things like 0-RTT early data could make a server more liable to attack.

4. Query size bounds, URI privacy and QUERY method

This is probably going to be one of the more controversial comments.

The CoSERV HTTP binding requires converting a query into a base64url string
carried in the URI. I don't know how big the underlying query data tends to be
in practice but the HTTP ecosystem does tend to limit the size of URI they
support. IIUC query size is unbounded but there may be real practical limits to
sending them via HTTP.

The recently published QUERY method (RFC 10008) summarizes the potential
problems quite well:

> when the data conveyed is too voluminous to be encoded in the request's URI,
this pattern becomes problematic:

>  *  size limits often are not known ahead of time because a request can pass
through many uncoordinated systems (but note that Section 4.1 of [HTTP]
recommends senders and recipients to support at least 8000 octets),

>  *  expressing certain kinds of data in the target URI is inefficient because
of the overhead of encoding that data into a valid URI,

>  *  request URIs are more likely to be logged than request content and may
also turn up in bookmarks,

The simplest thing to do is consider adding some text to highlight the potential
failure mode. A 414 (URI too Long) mention might be useful. You may also want to
highlight the privacy issues with logging URIs that contain any potential PII.

Possibly unpalatable: consider adding/substituting support for QUERY. This would
allow you to have a safe method to send the query in a more efficient binary
representation. A valid reason not to adopt QUERY wholesale at this time is that
support is still rolling out. A future binding might want to consider it though,
especially if you need larger queries and bump into limits.

3. Validators and ETags

The document is quite quiet on conditional GETs. Perhaps thats ok since it
things might "just work". However, the document does mention use of ETags in an
example. And as presented, the example is both invalid and raises some
questions.

The AI was very concerned about the **determinism of the response** (in contrast
to the determinism of the request). While RFC 9110 describes its the origin
servers prerogative to calculate ETags however they like, this doc might have to
do more. The AI raised the requirement in section 3.5 "Result sets always
include a timestamp indicating the expiry time of the entire result set." and
highlighted that results are signed via COSE (section 4.6) which may not be
byte-for-byte identical unless the server uses RFC 6979. I am not qualified to
comment authoritatively on these aspects of the payload. However, RFC 9110
section 8.8.1 does have text on this type of thing. The document might want to
consider spec'ing the use of weak validators if that's a better representation
of the information. SCIM appears to have had to do so. Strong validators based
on a hash of the content might cause all conditional requests to fail, which
would defeat the caching purposes of this protocol.

More specifically on ETags, the examples that use them are invalid - the origin
should be the ones generating them.

5. Freshness

This one is borderline minor. The document attempts to align CoSERV result
"embedded freshness" with HTTP freshness and provides a recommendation:

> the origin server MUST NOT set HTTP cache directives (e.g. Cache-Control:
> max-age, Expires) such that the freshness lifetime of the HTTP response
> exceeds the result set expiry timestamp contained within the CoSERV results.

That's good, but an origin might not set any Cache-Control directive in
responses. That could trigger an HTTP cache to use its own heuristics for
deciding on the cache freshness; see RFC 9111 section 4.2.2:

> Since origin servers do not always provide explicit expiration times, a cache
> MAY assign a heuristic expiration time when an explicit time is not specified,
> employing algorithms that use other field values (such as the Last-Modified
> time) to estimate a plausible expiration time. This specification does not
> provide specific algorithms, but it does impose worst-case constraints on
> their results.

The document might want to highlight the possibility for such an origin to
behave this way, even if there's not much that can be done to make genric HTTP
caches deal with it.

# Minor issues

6. Discovery content negotiation and response caching

It seems #94 was not properly resolved. There was a comment "I think we need to
say that servers MUST support both formats" but no text was actually added to do
it.

Leading on from that, the discovery document has two formats, JSON or CBOR. By
default, the responses for these objects is going to be cachable too. However,
the spec doesn't mention it. For scalability, I suspect you might want to
embrace it. If so, consider adding text about the `Vary: Accept` field in the
origin's response to ensure that a HTTP cache doesn't accidentally serve
a different type than a client might expect.

7. Accept looseness

The document levies some requirements on the Accept header:

> If the client presents any media type other than these two options in its HTTP
> Accept header, the implementation SHOULD respond with an HTTP 406 (Not
> Acceptable) status code

RFC 9110 section 12.4.1 has some text too:

>  For each of the content negotiation fields, a request that does not contain
>  the field implies that the sender has no preference on that dimension of
>  negotiation.

> If a content negotiation header field is present in a request and none of the
> available representations for the response can be considered acceptable
> according to it, the origin server can either honor the header field by
> sending a 406 (Not Acceptable) response or disregard the header field by
> treating the response as if it is not subject to content negotiation for that
> request header field. This does not imply, however, that the client will be
> able to use the representation.

I'm not sure if this spec is trying to be stricter than RFC 9110 or not. This
probably needs tightening up with a MUST, or just defer to RFC 9110 if it
doesn't matter much.

8. Error Content-Type broadness

The doc states:

> For error responses (4xx or 5xx status codes), the Content-Type header field
> MUST be application/concise-problem-details+cbor... containing [title,
> detail].

This is a bit broad because HTTP layered. the CoSERV app is running atop
lower-layer HTTP things, which could generate their own errors. It's more
correct to state something along the liens that a CoSERVER MUST send
application/concise-problem-details+cbor... content when returning error
responses (including the useful details like content-type and fields etc). That
accomodates for a client seeing any kind of error status with any content (or
none at all), that might be generated in an Internet deployment.

9. Rate limiting

There is an example about ratelimiting. I'm not sure it fits this document well.
Its possible that a layer beneath CoSERV could be implementing the rate
limiting, yet this example seems to imply its the CoSERV server?

The use of 429 overlaps a bit with issue 7. What should a client expect to do
with a rate limiting response, especially if it isn't the
application/concise-problem-details+cbor you're mandating at the CoSERV level.

The document might want to nix the example and instead describe the possibility
of rate limiting in the binding or security consideration sections. HTTP
ratelimiting is also evolving, using one very specific example might lead people
up the garden path.

If you want to keep this, the "MAY" is an issue and should be rephrased.

10. Truncated examples

The request examples have truncated URIs such as "/coserv/ogB4I3R...". Given how
important these are to the whole caching story it would be really useful to have
a fully worked value in the document somewhere. Even if the examples use a
short-hand for presentation.

11. Redirects

There is no definition of how redirects are to be handled. This seems
problematic given that there seems to be some expectation that the URI is
closely related the response content.

12. Inconsistent discovery responses

Section 6.1.2.3 has examples. The requests are to the same /.well-known endpoint
and vary only by the Accept header. However, the AI suggests the
"result-verification-key" doesn't match. This contrasts with other normative
text that states the responses should be equivalent apart from the
serialization.

13. Caching examples and time

The AI states the examples in 6.1.4.2 misuse HTTP fields. Its worth double
checking this once the ETag stuff is decided upon. RFC 9111 states

> When a stored response is used to satisfy a request without validation, a
> cache MUST generate an Age header field (Section 5.1), replacing any present
> in the response with a value equal to the stored response's current_age; see
> Section 4.2.3.

The example decrements values in Cache-Control and doesn't use Age. This is not
correct.

# Nits

14. The [HTTP] and [HTTP-CACHING] references seem to have been inverted :-)

15. Use URI consistently. Aside from base64url encoding, there seems to be a few
    "URLs" that have crept in.