Skip to content

transferSize might reveal HttpOnly cookies #238

Closed

Description

@annevk

Which does not seem ideal. The web platform networking APIs purposefully filter out cookie headers everywhere. (Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=1679737.)

Activity

  1. rniwa commented on Nov 22, 2020

    @rniwa

    This is one of many reasons Safari / WebKit doesn't expose transferSize.

  2. marcelduran commented on Nov 22, 2020

    @marcelduran
  3. rniwa commented on Nov 22, 2020

    @rniwa

    Hence TAO (timing-allow-origin) header, right? Or am I missing something?

    TAO wouldn't help here. This isn't a cross origin issue.

  4. marcelduran commented on Nov 24, 2020

    @marcelduran
  5. yoavweiss commented on Nov 24, 2020

    @yoavweiss
    Contributor

    httpOnly cookies should not be exposed to web content, even for the same origin. transferSize can enable sites to estimate those cookie sizes, which can reveal variations in those cookies which should not be observable.

  6. bdekoz commented on Dec 3, 2020

    @bdekoz

    hey @rniwa can you expand a bit on what keeps Safari / WebKit from exposing transferSize or encoded transfer size? Is there a common x-kind of transfer size that is acceptable to all the vendors here?

  7. nicjansma commented on Dec 3, 2020

    @nicjansma
    Contributor

    @annevk Could you provide a brief summary of how you could use transferSize to detect HttpOnly cookies? When I first saw this I was thinking you could compare document.cookie.length to transferSize-encodedBodySize (to get "headers size"), but the later would also obviously include the other HTTP headers as well. I don't think the client would be able to know the exact size of the "other" headers unless they changed very little by time/useragent.

  8. annevk commented on Dec 4, 2020

    @annevk
    MemberAuthor

    @nicjansma you could just do a fetch(), no?

  9. rniwa commented on Dec 4, 2020

    @rniwa

    @nicjansma you could just do a fetch(), no?

    Also, we don't want to make it a requirement for web servers to insert varying lengths of HTTP(S) headers to obscure the presence of HttpOnly cookies.

  10. nicjansma commented on Dec 5, 2020

    @nicjansma
    Contributor

    @annevk Ah yep, thanks, forgot XHR/fetch have access to all headers in some cases.

  11. yoavweiss commented on Jan 18, 2021

    @yoavweiss
    Contributor

    This was discussed on the WG call the other week.

    Seems like a good path forward would be to remove the header sizes from transferSize, and replace it with a fixed value (e.g. 300 bytes) that would enable the current cache state related use cases ("is the resource fetched from cache?" and "was the resource successfully revalidated?") to remain viable without breaking existing code that relies on current values.

  12. Krinkle commented on Jan 19, 2021

    @Krinkle
    Member

    I've analysed usage in Wikimedia codebases, and the libraries we distribute currently. Indeed the only use case currently found was to "guess" whether a resource was a local cache hit, 304 Not Modified response, or fresh download.

    Follows this pattern generally:

    // Resource Timing API
    if (nt.transferSize === 0) {
    	browserCache = 'local hit';
    } else if (nt.transferSize > 0 && nt.encodedBodySize > 0 && nt.transferSize < nt.encodedBodySize ) {
    	browserCache = 'local hit (after HTTP 304)';
    } else {
    	browserCache = 'miss (HTTP 200 OK)';
    }

    I support the mitigation reducing transferSize to just a fixed amount for headers plus encodedBodySize, if transferred.

    Now that we've learned that we don't want to expose the actual transfer size, I wonder it would make sense to remove this in a future interation of the spec. From what I can tell, it seems likely safe for web compat for it to become undefined, as the original spec didn't have it (afaik), and Safari still doesn't implement it.

    In that case, we may want to first decide how to provide the cache status in a more intiutive manner for future generations, since this definitely doesn't seem like a good API for it long-term. It would be confusing both because it doesn't provide what it appears to, and the thing it actually provides (cache status) is hard to learn/discover this way. It seems appealing to jump for a shiny new field like cacheStatus holding three possible values, but that might be rather inflexible over the long-term and presents the same problem we've since faced in other APIs when we try to capture complex information in a single string, which means we can't then add new values to it that are related without breaking existing code. In this case something more split up might make sense e.g. boolean wasBodyTransferred. Depending on whether we want to long-term expose http status codes and/or to differenteiate between 304 vs fully local hit, we might want to add another bool or integer field.

    (Wording of "was" vs "did" still TBD in w3ctag/design-reviews#547)

  13. added a commit that references this issue on Oct 25, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions