Confinement with Origin Web Labels

Editor’s Draft,

This version:
https://w3c.github.io/webappsec-cowl/
Latest published version:
https://www.w3.org/TR/COWL/
Version History:
https://github.com/w3c/webappsec-cowl/commits/master/index.src.html
Feedback:
public-webappsec@w3.org with subject line “[cowl] … message topic …” (archives)
Editors:
(Intrinsic and UC San Diego)
(UC San Diego)
Participate:
File an issue (open issues)

Abstract

This specification defines an API for specifying privacy and integrity policies on data, in the form of origin labels, and a mechanism for confining iframes according to such policies. This allows Web application authors and server operators to shared data with untrusted—buggy but not malicious—code (e.g., in a mashup scenario) yet impose restrictions on how the code running in an iframe can share the data further.

Status of this document

This is a public copy of the editors’ draft. It is provided for discussion only and may change at any moment. Its publication here does not imply endorsement of its contents by W3C. Don’t cite this document other than as work in progress.

Changes to this document may be tracked at https://github.com/w3c/webappsec.

The (archived) public mailing list public-webappsec@w3.org (see instructions) is preferred for discussion of this specification. When sending e-mail, please put the text “cowl” in the subject, preferably like this: “[cowl] …summary of comment…

This document was produced by the Web Application Security Working Group.

This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

This document is governed by the 1 March 2017 W3C Process Document.

1. Introduction

This section is not normative.

Modern Web applications are conglomerations of JavaScript written by multiple authors. Authors routinely incorporate third-party scripts into their applications and share user data with third-party services (e.g., as part of a mashup). Unfortunately, in the existing model, the user’s data confidentiality and integrity is put at risk when one incorporates untrusted third-party code or shares data with untrusted third-party services.

Mechanisms such as CORS and CSP can be used to mitigate these risks by giving authors control over whom they share data with. But, once data is shared, these mechanisms do not impose any restrictions on how the code that was granted access can further disseminate the data.

This document specifies an extension to the current model called Confinement with Origin Web Labels (COWL). COWL provides authors with APIs for specifying (mandatory) access control policies on data, including content, in terms of origin labels. These policies are enforced in a mandatory fashion, transitively, even once code has access to the data. For example, with COWL, the author of https://example.com can specify that a password is confidential to https://example.com (and thus should only be disclosed to https://example.com) before sharing it with a third-party password strength checking service. In turn, COWL ensures that the third-party service, which necessarily computes on the sensitive password, is confined and respects the policy on the password: COWL disallows it from disclosing the password to any origin other than https://example.com.

COWL enforces such policies by confining code at the context-level, according to the sensitivity (i.e., the label) of the data the code has observed. To reap the greatest benefits of COWL, authors will need to compartmentalize applications into multiple contexts (e.g., iframes).

In the existing model, any page served from an origin has the ambient, implicit authority of that origin. This documents generalizes this notion of authority and gives authors explicit control over it with privileges. For example, by default, a page whose origin is https://example.com has the privilege for https://example.com. This gives the page the authority to arbitrarily disseminate data sensitive to https://example.com; to be backwards-compatible, COWL does not confine the page when reading data sensitive to https://example.com. However, COWL allows the author to run iframes with "weaker" delegated privileges (e.g., one corresponding the current user at https://example.com) or to drop the privilege altogether.

COWL is intended to be used as a defense-in-depth mechanism that can restrict how untrusted—buggy but not malicious—code handles sensitive data. Given the complexities of browser implementations and the presence of covert channels, malicious code may be able to exfiltrate data. Authors should still use discretionary access control mechanisms, such as CSP and CORS, to restrict access to the data in the first place.

1.1. Goals

The goal of COWL is to provide authors with a means for protecting the confidentiality and integrity of data that is shared with untrusted code, whether third-party or their own. Existing mechanisms (e.g., CORS’s Access-Control-Allow-Origin header and the targetOrigin argument to postMessage()) provide a way for restricting which origins may access the shared data. But, once content has access to data it can usually disseminate it without restrictions. While CSP can be used to confine code, i.e., restrict how confidential data is disseminated, setting a correct CSP policy (as to confine code) is difficult and limited to content the author has control over. Indeed, sharing confidential data in the existing model almost always requires the sender to trust the receiver not to leak the data, accidentally or otherwise. COWL provides a defense-in-depth option for protecting data confidentiality and integrity. In particular, with COWL:

  1. Authors should be able to specify confidentiality and integrity policies on data in terms of origin labels: the origins to whom the data is confidential and the origins that endorse the data. This allows authors to share sensitive data with third-party content and impose restrictions on the origins with which it can communicate once it inspects the sensitive data. Dually, it allows authors to share data via intermediate content while retaining its integrity.

  2. Authors should be able to run code with least privilege by restricting the origins the code can communicate with and thus how it can disseminate sensitive data.

  3. Authors should be able to privilege separate applications by compartmentalizing them into separate contexts that have delegated privileges.

1.2. Use Cases/Examples

1.2.1. Confining untrusted third-party services

An author wishes to use a service, loaded in the form of an cowl iframe, without trusting it (or its dependencies) to not leak her sensitive data. To protect the data, the author associates a confidentiality label with the data, specifying the origins allowed to read the data. The author then shares the newly created labeled object with the untrusted code. In turn, COWL confines the untrusted code once it inspects the sensitive data, as to ensure that it can only communicate according to the author-specified policy (the label).

The author of https://example.com wishes to use a third-party password strength checker provided by https://untrusted.com. To protect the confidentiality of the password, the https://example.com application can use COWL to run the checker code in a cowl iframe and associate a confidentiality policy, in the form of a label, with the password before sending it to the untrusted service:
// Create new policy using Labels that specifies that the password is sensitive
// to https://example.com and should only be disclosed to this origin:
var policy = new Label(window.location.origin);

// Associate the label with the password:
var labeledPassword = new LabeledObject(password, { confidentiality: policy });

// Send the labeled password to the checker iframe:
checker.postMessage(labeledPassword, "https://untrusted.com");

// Register listener to receive a response from checker, etc.

Once the checker inspects the label-protected object, i.e., the password, COWL limits the iframe to communicating with origins that preserve the password’s confidentiality (in this case, https://example.com). This policy is enforced mandatorily, even if the https://untrusted.com iframe sends the password to yet another iframe.

Note, until the checker actually inspects the labeled password, it can freely communicate with any origins, e.g., with https://untrusted.com. This is important since the checker may need to fetch resources (e.g., regular expressions) to check the password strength. It’s also safe—the checker has not inspected the sensitive password, and thus need not be confined.

Other use cases in this category include password managers and encrypted document editors, for example, where an encryption/decryption layer and a storage layer are provided by distrusting, but not malicious, services. The academic paper on COWL describes these use cases in detail [COWL-OSDI].

1.2.2. Sharing data with third-party mashups

A server operator wishes to provide third-party mashups access to user data. In addition to using CORS response headers to restrict the origins that can access the data [CORS], the operator wishes to restrict how the data is further disseminated by these origins once they have access to it, in the browser. To do so, the perator sends a response header field named Sec-COWL (described in §3.5.2 Sec-COWL in HTTP Responses) whose value contains the sensitivity of the data in the form of a serialized confidentiality label. In turn, COWL enforces the label restrictions on the third-party code.

The server operator of https://provider.com uses a CORS response header to grant https://mashup.com access to a resource. The operator also sets a COWL header to specify that the resource is confidential to https://provider.com and should not be disseminated arbitrarily:
Access-Control-Allow-Origin: https://mashup.com
Sec-COWL: data-confidentiality https://provider.com

COWL only allows a https://mashup.com context to read the sensitive response if the label restrictions of the response are respected, i.e., if the code can only communicate with https://provider.com.

Note, COWL only allows the code to inspect the response if the context labels, which dictate the context’s ability to communicate, are more restricting than the labels of the response. A more permissive approach, which does not require the context give up its ability to communicate arbitrarily is to use a labeled JSON response. The mashup XHR example shows how authors can accomplish this.

1.2.3. Content isolation via privilege separation

A server operator wishes to isolate content (e.g., of different users) while serving it from a single physical origin. The operator can leverage privileges to ensure that content of one part of the site has different authority from another and, importantly, does not have the authority of the physical origin. Concretely, when serving content, the operator can set the content’s context privilege to a weaker, delegated privilege. This ensures that the content are privilege separated.

Suppose https://university.edu wished to isolate different parts of their site according to users. The server operator can weaken the privilege of a page when serving user content by providing a response header field named Sec-COWL (see §3.5.2 Sec-COWL in HTTP Responses) whose value contains a serialized delegated privilege. For example, for any content under https://university.edu/~user1, the following header is set:
Sec-COWL: ctx-privilege 'self' OR app:user1

Having this privilege can be understood as having the authority of user1’s part of the application’s origin. COWL ensures that the content of this page cannot interfere with the content of https://university.edu or that of another user e.g., user2. For example, the content cannot modify https://university.edu cookies or the DOM of another https://university.edu page.

This delegated privilege also ensures that the content cannot disseminate data sensitive to another user (e.g., user2) arbitrarily—without being confined, it can only disseminate user1’s data on https://university.edu. Of course, this requires the server operator to label sensitive data (e.g., when sending it to the user agent) appropriately (e.g., user2’s data is labeled Label("https://university.edu").or("app:user2")).

The sub-origin isolation in JavaScript example shows how this can be implemented using the COWL JavaScript APIs.

Note, sub-domains should be used when possible to ensure that content is isolated using the Same-Origin Policy. But, even in such cases, COWL can provide a useful layer of defense.

1.2.4. Running content with least-privileges

An author wishes to use a library that is tightly coupled with the page (e.g., jQuery), but not trust it to protect the user’s confidentiality and integrity. With COWL, the author can do this by dropping privileges (from the context’s default privilege) and then loading the untrusted library. In dropping privileges, the content (and untrusted library) loses its implicit authority over the content’s origin.

The author of https://example.com can drop privileges in JavaScript:
// Drop privileges, by setting the context privilege to an empty privilege:
COWL.privilege = new Privilege();

// Load untrusted library

Or, by setting the content’s initial privilege to the empty privilege using Sec-COWL response header:

Sec-COWL: ctx-privilege 'none'
Note, while this ensures that the context code cannot, for instance, access the origin’s cookies, the author must still associate a confidentiality label with resources (e.g., HTTP responses) to ensure that data is properly protected.

In some cases it is useful for a particular context to have the privilege to disseminate certain categories of data. (The or part of labels can be used to easily categorize differently-sensitive data.) To this end, the author should run the context with a delegated privilege instead of the empty privilege. The above §1.2.3 Content isolation via privilege separation shows one such example.

1.3. Security Considerations

1.3.1. Information leakage via covert channels

COWL provides developers with a way of imposing restrictions on how untrusted code can disseminate sensitive data. However, authors should avoid sharing sensitive data with malicious code, since such code may be able to exploit covert channels to leak the data. Covert channels are prevalent in most browsers. COWL can only prevent information leakage from code that uses overt communication channels.

Similarly, COWL provides no guarantees against attacks wherein users are manipulated into leaking sensitive data via out-of-band channels. For example, an attacker may be able to convince a user to navigate their user agent to an attacker-owned origin by entering a URL that contains sensitive information into the user agent’s address bar.

1.3.2. Defense in depth

COWL has been defined within the context of existing security mechanisms (CSP, SRI, CORS, and iframe sandbox) and SHOULD be used as an additional layer of defense. The goal of this specification is not to replace existing discretionary access control mechanisms.

1.4. Privacy Considerations

1.4.1. Encoding information in labels

This specification introduces the Sec-COWL HTTP request header to provide server operators with information about the context that made the request (e.g., the context privilege). This header is sent in accordance to thereferrer policy [REFERRER-POLICY]. However, since the request header may contain serialized application-specific principals, this can have privacy implications when the principals encode private user information. It is RECOMMENDED that authors and server operators not include any private information in labels—labels SHOULD be treated as public data.

1.4.2. Using labels to enhance privacy

COWL provides mechanisms for restricting how information flows from within the confines of the user agent. Thus, from a privacy perspective, application developers, server operators, and specification authors are encouraged to consider using these mechanisms (namely, labels) to prevent unwanted or accidental information leaks.

2. Key Concepts and Terminology

2.1. Labels

  1. An origin label, or more succinctly a label, encodes either a confidentiality or integrity security policy as conjunctive normal form (AND’s and OR’s) formulae over principals (typically origins.) Labels can be associated with contexts or with structurally clonable objects.

    When associated with a context, the label restricts the origins that the context can communicate with, as detailed in §3.3 Labeled Contexts.

    The confidentiality label Label("https://a.com").or("https://b.com"), when associated with a context, restricts the context to sending data to https://a.com or https://b.com, but no other origins. This context label reflects the fact the context may contain data that is sensitive to either https://a.com or https://b.com; it is thus only safe for it to communicate to these origins.

    Note, because the context can communicate data to either origin, another context associated with the more restricting label Label("https://a.com") cannot send it data. Doing so would allow for data confidential to https://a.com to be leaked to https://b.com.

    The integrity label Label("https://a.com").or("https://b.com"), when associated with a context, restricts the context to receiving data from (a context or server) that is at least as trustworthy as https://a.com or https://b.com. This context label ensures that the code running in the context can only be influenced by data which either https://a.com or https://b.com endorse.

    When associated with an object, a confidentiality label specifies the origins to whom the object is sensitive, while an integrity label specifies the origins that endorse the object. Objects that have labels associated with them are called labeled objects. §3.4 Labeled Objects defines how labels are associated with objects.

    Consider an https://example.com page that receives a labeled object (e.g., via postMessage()) with the following labels:
    • Confidentiality: Label("https://example.com"). This label indicates that the object is sensitive to https://example.com.

    • Integrity: Label("https://a.com"). This label indicates that the object has been endorsed by https://a.com. If https://example.com received the message from an intermediary https://b.com context, this label reflects the fact that the object (produced by https://a.com) was not tampered.

  2. A principal is a string that represents an authoritative entity. There are three kind of principals:

  3. Mathematically, a label is a conjunctive normal form formula over principals [DCLabels].

    A label is in normal form if reducing it according to the label normal form reduction algorithm produces the same value.

    Two labels are equivalent if their normal form values are mathematically equal.

    A label A subsumes (or is more restricting than) another label B if the result of running the label subsumption algorithm on the normal forms of A and B returns true. Labels are partially ordered according to this subsumes relation.

    The current confidentiality label is the confidentiality label associated with the current context. §3.3 Labeled Contexts specifies how labels are associated with contexts.

    The current integrity label is the integrity label associated with the current context. §3.3 Labeled Contexts specifies how labels are associated with contexts.

    When reading a labeled object, a context gets tainted, i.e., its context labels are updated by invoking context tainting algorithm, to reflect that it has read sensitive data, or data of potentially different trustworthiness, and should be confined accordingly.

2.2. Privileges

  1. A privilege is an unforgeable object that corresponds to a label. Privileges are associated with contexts and reflect their authority.

    Privileges can be used to bypass confinement restrictions imposed by confidentiality labels. In particular, a privilege can be used to bypass the restrictions imposed by any label that is subsumed by the privilege’s corresponding label—the internal privilege label.

    Consider a context from https://a.com whose current confidentiality label is Label("https://a.com").and("https://b.com"). This label confines the context to only communicating with entities whose labels are at least as restricting as this label. For example, it restricts the context from communicating with a context labeled Label("https://b.com"), since doing so could leak https://a.com data to https://b.com. It similarly prevents the context from communicating with https://a.com.

    But, suppose that the context’s current privilege corresponds to Label("https://a.com") (afterall, the context originated from https://a.com). Then, the context would be able to bypass some of the restrictions imposed by the context label. Specifically, the context would be able to communicate with https://b.com; the privilege confers it the right to declassify https://a.com data to https://b.com. Indeed, when taking this privilege into consideration, the effective confidentiality label of the context is Label("https://b.com").

    Note, the privilege does not allow the context to bypass any label restrictions. For example, it does not allow the context to communicate with https://a.com since doing so could leak https://b.com data.

    To be flexible, COWL uses the context privilege to remove certain restrictions imposed by the context label. To avoid accidentally leaking sensitive context data, authors should use LabeledObjects.

    Privileges can also be used to bypass integrity restrictions imposed by integrity labels. In particular, a privilege can be used to endorse an otherwise untrustworthy labeled context (or labeled object) as to allow it to communicate with more trustworthy end-points (another context or server).

    Consider an https://a.com context whose current integrity label is Label("https://a.com").or("https://b.com"). This label confines the context to only communicating with entities that are at most as trustworthy as this label. For example, it restricts the context from communicating with a context whose current integrity label is Label("https://a.com"), since doing so would potentially corrupt https://a.com data (e.g., by allowing https://b.com to influence the computation).

    But, if the context’s current privilege corresponds to Label("https://a.com"), the context would be able to bypass some of these integrity restrictions. Specifically, the context would be able to communicate with the more-trustworthy context (labeled Label("https://a.com")) since the privilege confers it the right to endorse (or vouch for) its context on behalf of https://a.com. Indeed, when taking privileges into account, the effective integrity label of the context is Label("https://a.com").

    Note, the privilege cannot be used to bypass any integrity restrictions. For example, it does not allow the context to communicate with a context whose integrity label is Label("https://b.com").

    Note, browsing contexts have a current privilege that, by default, corresponds to the origin of the context, as described in §3.3 Labeled Contexts. But, authors should set the current privilege to a delegated privilege to follow the principle of least privilege.

  2. The current privilege is the privilege associated with the current context. §3.3 Labeled Contexts specifies how privileges are associated with contexts.

  3. The effective confidentiality label is the label returned by the label downgrade algorithm when invoked with the current confidentiality label and current privilege.

  4. The effective integrity label is the label returned by the label upgrade algorithm when invoked with the current integrity label and current privilege.

  5. Code can take ownership of a privilege priv by setting the current privilege to the privilege produced via the combination of the current privilege and priv. In doing so, it is said that the context owns the privilege.

3. Framework

This sub-section is not normative.

In a nut-shell, the COWL framework provides:

Policy specification via labels
COWL provides a Label interface for specifying confidentiality and integrity policies in terms of principals (typically, origins). Labels can be associated with data and content using the JavaScript LabeledObject and COWL interfaces or the Sec-COWL HTTP header field.
Explicit authority via privileges
The COWL framework provides a JavaScript Privilege interface for operating on and minting new privileges. The COWL JavaScript interface and Sec-COWL HTTP response header can be used to explicitly control the authority of a context by setting the context privilege.
Confinement enforcement mechanism
COWL extends browsing contexts, in particular iframes with labels and privileges, which are used when enforcing confinement, i.e., when restricting a context’s network and cross-context messaging communication. This document defines the necessary changes and extensions to existing browser constructs and algorithms to enforce confinement.

3.1. Labels

Each label is an immutable object represented by a Label object, the interface of which is defined in this section.

A Label MUST have an internal label set, which is a non-empty set of disjunction sets.

A disjunction set is a set of principals.

A label is said to be an empty label if its label set contains a single, empty disjunction set.

[Constructor, Constructor(DOMString principal), Exposed=(Window, Worker)]
interface Label {
  boolean equals(Label other);
  boolean subsumes(Label other, optional Privilege priv);

  Label and((Label or DOMString) other);
  Label _or((Label or DOMString) other);

  stringifier;
};

3.1.1. Constructors

Label()
When invoking the Label() constructor, the user agent MUST return a new empty label.
Label(DOMString principal)
When invoking the Label(principal) constructor, the user agent MUST use an algorithm equivalent to the following:
  1. If the principal argument is not a principal, the constructor MUST throw a TypeError exception [ECMA-262] and terminate this algorithm.

  2. Else, it MUST return a new Label that contains a label set of a single disjunction set, which itself MUST contain the principal corresponding to the principal argument.

3.1.2. Methods

equals(Label other)
The user agent MUST return true if the Label on which the method has been called is equivalent to the other parameter; otherwise it MUST return false.
subsumes(Label other, optional Privilege priv)
The user agent MUST use an algorithm equivalent to the following:
  1. Let lab be the Label on which the method has been called.

  2. If the priv argument is provided, let lab be lab.and(priv.asLabel()).

  3. Return true if lab subsumes the other parameter and false otherwise.

and((Label or DOMString) other)
The user agent MUST use an algorithm equivalent to the following:
  1. Let O be the other argument.

  2. If the type of other is DOMString, run the following sub-steps:

    1. Set O to the result of invoking the Label(other) constructor with other as an argument, if the constructor did not raise an exception.

    2. Else, re-throw the exception and terminate this algorithm.

  3. Return a new normal form Label that is equivalent to a label whose label set contains the disjunction sets of O and the Label on which the method was invoked.

or((Label or DOMString) other)
The user agent MUST use an algorithm equivalent to the following:
  1. Let O be the other argument.

  2. If the type of other is DOMString, run the following sub-steps:

    1. Set O to the result of invoking the Label(other) constructor with other as an argument, if the constructor did not raise an exception.

    2. Else, re-throw the exception and terminate this algorithm.

  3. Return a new Label, in normal form, which is equivalent to adding each element of each disjunction set of O’s label set to each disjunction set of the label set of the Label on which the method was called.

3.1.3. Serializing labels

The stringification behavior MUST return the serialization of the label, which adheres to the label-expression grammar, using an algorithm equivalent to the following:

  1. Let label be the label being serialized.

  2. If label is the empty label, return "'none'" and terminate this algorithm.

  3. Let result be the empty string.

  4. For each element dset in the label’s label set:

    1. If result is not the empty string, append the characters " AND " to it.

    2. If the number of elements in dset is greater than 1:

      1. Append the character "(" (U+0028) to result.

      2. Append the character " " (U+0020) to result.

    3. Let o be the empty string.

    4. For each element prin in the disjunction set dset:

      1. If o is not the empty string, append the characters " OR " to it.

      2. Append prin to o.

    5. Append o to result.

    6. If the number of elements in dset is greater than 1:

      1. Append the character " " (U+0020) to result.

      2. Append the character ")" (U+0029) to result.

3.1.4. Examples

Example labels. Intuition for each label’s semantics is given in the context of it being used as a confidentiality label (C) and integrity label (I).
// C: Public data.
// I: Non-endorsed/untrustworthy data.
var empty = new Label();

// C: Data confidential to a.com.
// I: Data endorsed/trusted by a.com.
var a = new Label("https://a.com");

// C: Data confidential to b.com.
// I: Data endorsed/trusted by b.com.
var a = new Label("https://b.com");

// C: Data confidential to both a.com and b.com
// I: Data endorsed/trusted by a.com and b.com.
var aANDb = new Label("https://a.com").and("https://b.com");

// C: Data confidential to either a.com or b.com.
// I: Data endorsed/trusted by either a.com or b.com.
var aORb = new Label("https://a.com").or("https://b.com");

Examples of label comparisons with intuition for the semantics.

// C: Data confidential to a.com (b.com) data is more sensitive than public data.
// I: Data endorsed by a.com (b.com) is more trustworthy than non-endorsed/untrustworthy data.
a.subsumes(empty) === true;
b.subsumes(empty) === true;

// C: Data that is confidential to a.com and b.com is more
//    confidential than data that is only sensitive to a.com (b.com).
// I: Data that is endorsed/trusted by both a.com and b.com is
//    more trustworthy than data endorsed only by a.com (b.com).
aANDb.subsumes(a) === true;
aANDb.subsumes(b) === true;

// C: Data that that is confidential to a.com (b.com) is not comparable to
//    data that is confidential to b.com (a.com).
// I: Data that that is endorsed by a.com (b.com) is not comparable to
//    data that is endorsed by b.com (a.com).
a.subsumes(b) === false;
b.subsumes(a) === false;

// C: Data that is confidential to a.com (b.com) is more confidential than data that is
//    confidential to either a.com or b.com. Alternative intuition: data that can be read by
//    a.com or b.com can be read by an entity that can read a.com (b.com) data alone.
// I: Data that is endorsed by a.com (b.com) is more trustworthy than data that is endorsed
//    by either a.com or b.com. Alternative intuition: an entity that trusts data endorsed
//    by either a.com or b.com necessarily trusts data endorsed by a.com (b.com) alone.
a.subsumes(aOrb) === true;
b.subsumes(aOrb) === true;
Using the labels defined in the above example, this example shows how labels are serialized. We only define an additional label:
var aORbANDc = aORb.and(new Label("https://c.com");

Converting to string:

empty.toString()    === "'none'";
a.toString()        === "https://a.com";
aANDb.toString()    === "(https://a.com) AND (https://b.com)";
aORb.toString()     === "https://a.com OR https://b.com";
aORbANDc.toString() === "(https://a.com OR https://b.com) AND (https://c.com)";

3.2. Privileges

Each privilege is an immutable object represented by a Privilege object, the interface of which is defined in this section.

A Privilege MUST have an internal privilege label.

The combination of privileges A and B is a privilege produced by invoking the combine() method on A (respectively, B) with B (respectively, A) as an argument.

A privilege is said to be an empty privilege if its internal privilege label is the empty label. A context is said to be unprivileged if its context privilege is the empty privilege. By setting the context privilege to the empty privilege, a context is said to be dropping privileges.

A privilege P1 is said to be a delegated privilege of P2 if P2’s internal privilege label subsumes P1’s internal privilege label.

[Constructor, Exposed=(Window, Worker), SecureContext]
interface Privilege {
  static Privilege FreshPrivilege(); // Named constructor
  Label asLabel();

  Privilege combine(Privilege other);
  [Throws] Privilege delegate(Label label);
};

3.2.1. Constructors

Privilege()
When invoking the Privilege() constructor, the user agent MUST return a new Privilege that has its internal privilege label set to the empty-label.
FreshPrivilege()

When invoking the FreshPrivilege() constructor, the user agent MUST use an algorithm equivalent to the following:

  1. Let unique principal be a freshly generated unique principal.

  2. Let unique label be the label produced by invoking the Label(principal) constructor with unique principal.

  3. Return a new Privilege that has an internal privilege label set to unique label.

3.2.2. Methods

asLabel()
The user agent MUST return the internal privilege label of the Privilege on which the method has been called.
combine(Privilege other)

The user agent MUST return a new Privilege whose internal privilege label is equivalent to a label created according to an algorithm equivalent to the following:

  1. Let internalLabel be the internal privilege label of the Privilege on which the method has been called.

  2. Let otherLabel be the internal privilege label of the other argument.

  3. Return internalLabel.and(otherLabel).

delegate(Label label)

The user agent MUST return a new Privilege whose internal privilege label is equivalent to a label created according to an algorithm equivalent to the following:

  1. Let internalLabel be the internal privilege label of the Privilege on which the method has been called.

  2. If the internalLabel does not subsume the label argument, throw a SecurityError exception and terminate this algorithm.

  3. Else, return a new Privilege that has an internal privilege label set to label.

Note, the Privilege constructors and the combine() and delegate() methods only provide ways for creating privileges. Context code must still take ownership of or set the current privilege to the privilege for it to be used (to bypass label restrictions).

3.2.3. Examples

To be backwards-compatible with the Same-Origin Policy, COWL grants each browsing context a default privilege that corresponds to their origin. For example, a page on https://example.com has a privilege whose internal privilege label is Label("https://example.com").

As a result, reading data that is sensitive to Label("https://example.com") does not confine the context. For example, reading a labeled object whose confidentiality label is Label("https://example.com") does not restrict the context from communicating—and thus accidentally leaking that object’s contents—to another origin. To prevent accidental leaks, the author should drop privileges by setting the current privilege to an empty privilege:

// Save privilege in case we need it later:
var __savedPriv = COWL.privilege;

// Drop privilege (set the context privilege to the empty privilege):
COWL.privilege = new Privilege();

After this point, if the context reads data with a Label("https://example.com") confidentiality label, COWL will restrict it to communicating with https://example.com.

Consider an extension to the password strength checker example of §1.2.1 Confining untrusted third-party services that uses FreshPrivilege()s to ensure that the untrusted checker cannot communicate with any entity other than the parent context.
// Create new fresh privilege:
var priv = new FreshPrivilege();

// Take ownership of the fresh privilege:
COWL.privilege = COWL.privilege.combine(priv);

// Associate the unique label with the password:
var labeledPassword = new LabeledObject(password, {confidentiality: priv.asLabel()});

// Send the labeled password to the checker iframe:
checker.postMessage(labeledPassword, "https://untrusted.com");

Once the https://untrusted.com cowl iframe reads the password it will be tainted by the unique, internal privilege label of priv; the unique origin ensures that it cannot send the password to, for example, public parts of https://example.com. Indeed, only the owner of priv can disseminate the labeled password (result) arbitrarily.

Consider an implementation of the content isolation example of §1.2.3 Content isolation via privilege separation using the COWL JavaScript API. In this example, the author https://university.edu isolates different parts of their site according to users. For user1 it can do this as follows:
// Create a label corresponding to the university origin:
var uni = new Label(window.location.origin);
// Create a new label that corresponds to user1’s data on university.edu:
var user1 = uni.or("app:user1"); // Here the app:user1 is an application-specific princial

// Originally, COWL.privilege.asLabel().equals(uni).
// Drop the current context privilege to a delegated privilege:
COWL.privilege = COWL.privilege.delegate(user1);

At this point, the context can only arbitrarily disseminate data that is labeled Label("https://university.edu").or("app:user1"); it cannot disseminate data that is sensitive to the university (e.g., which is labeled Label("https://university.edu")) or to another user (e.g., user2’s data is labeled Label("https://university.edu").or("app:user2")).

3.3. Labeled Contexts

COWL extends browsing contexts with a COWL state, which is used to restrict the context’s communication channels. The COWL state consists of:

  • The confinement mode status, which indicates whether or not COWL confinement is enabled and thus labels should be enforced in the current context.

    A context is considered a confined context if its confinement mode status is set, and a unconfined context otherwise.

    Note: confinement mode is currently only be enabled for contexts instantiated in cowl iframes. In future versions we may generalize the enforcement to other browsing contexts and Workers.

  • The context labels, which consist of:

    • context confidentiality label reflects the sensitivity of the data that the context has read.

    • context integrity label reflects the integrity of the data that the context has read.

  • The context privilege, which encodes the context’s ability to bypass the restrictions of certain labels.

Each context’s COWL state MUST be initially set to the default COWL state, where:

The default COWL state is backwards-compatible with the existing Web model. Specifically:

COWL restricts the code running in a confined context from communicating with other contexts or remote servers in a way that preserves confidentiality and integrity (see §3.7 Confinement Enforcement).

In general, COWL does not restrict code running in unconfined contexts from communicating with other unconfined contexts or remote servers. To preserve this invariant COWL does, however, prevent such code from reading overly sensitive data (i.e., data that would taint the context) or communicating with certain confined contexts and COWL-enabled servers.

Note: the COWL state of an unconfined context does not change from its original default COWL state.

The COWL state is exposed to confined contexts via the COWL interface defined below. This interface MUST not be exposed to unconfined contexts.

[SecureContext, COWLContext]
interface COWL {
  [SetterThrows] static attribute Label confidentiality;
  [SetterThrows] static attribute Label integrity;
  [SetterThrows] static attribute Privilege privilege;
};

3.3.1. Attributes

confidentiality, of type Label
integrity, of type Label
privilege, of type Privilege
  • On getting, the user agent MUST return the current privilege.

  • On setting, the user agent MUST use an algorithm equivalent to the following:

    1. Let priv be the set privilege.

    2. Set the current privilege to priv.

3.3.2. Examples

Below are several examples showing how to use the COWL API. The §3.2.3 Examples illustrate the use of context privileges.
An author can set the context integrity label to ensure that the context can only receive messages from (another context or server of) the same origin:
COWL.integrity = new Label(window.location.origin);
The author of https://mashup.com can set the context confidentiality label to receive data sensitive from https://provider.com:
COWL.confidentiality = new Label('https://provider.com');

At this point, the context can only communicate with https://provider.com. The data provider can ensure that only appropriately labeled contexts can inspect an HTTP response by setting response labels using the Sec-COWL response header.

3.4. Labeled Objects

A LabeledObject interface represents an immutable object that is protected by a confidentiality and integrity label, i.e., the object has associated labels.

This API is designed to be used in conjunction with other APIs and elements on the web platform. In particular, postMessage() and XMLHttpRequest (e.g., with an overloaded send() method for LabeledObject arguments). It SHOULD be exposed to both confined contexts and unconfined contexts.

A LabeledObject MUST have an internal protected object, a confidentiality label, and an integrity label. The interface is defined below.

dictionary CILabel {
  Label? confidentiality;
  Label? integrity;
};

[Constructor(object obj, CILabel? labels), Exposed=(Window, Worker), SecureContext]
interface LabeledObject {
  readonly attribute Label confidentiality;
  readonly attribute Label integrity;

  [GetterThrows] readonly attribute object protectedObject;

  [Throws] LabeledObject clone(CILabel labels);
};

3.4.1. Constructors

LabeledObject(obj, labels)

When invoking the LabeledObject() constructor, the user agent MUST use an algorithm equivalent to the following:

  1. Let obj clone be the result of obtaining a structured clone of the obj argument.

  2. Let labels be the labels argument if it provided, otherwise an empty object with no members.

  3. Let conf be the confidentiality member of labels, if it is set. Otherwise, let conf be the current confidentiality label.

  4. Let int be the integrity member of labels, if it is set. Otherwise, let int be the current integrity label.

  5. Let canWrite be the result of invoking the write check algorithm with the conf and int labels.

  6. If canWrite is false, the constructor MUST throw a SecurityError exception and terminate this algorithm.

  7. Else, the user agent MUST return a new LabeledObject, with the protected object set to obj clone, the confidentiality label set to conf, and the integrity label set to int.

Because COWL enforces labels at context boundaries, there is usually no reason to label an object and then use the labeled object within the same context. LabeledObjects are mainly useful for sending sensitive data to an untrusted confined context, e.g., via cross-document messaging, as a way to ensure that the data’s confidentiality and integrity (as specified by the labels) are respected by the untrusted context. Hence, the LabeledObject() constructor only accepts objects that can be structurally cloned.

3.4.2. Attributes

confidentiality, of type Label, readonly
On getting, the user agent MUST return the LabeledObject’s confidentiality label.
integrity, of type Label, readonly
On getting, the user agent MUST return the LabeledObject’s integrity label.
protectedObject, of type object, readonly

should protectedObject be a promise? Otherwise we may be a bit too inflexible.

On getting, the user agent MUST use an algorithm equivalent to the following:

  1. If the current settings object is not a secure context, then the user agent MUST throw a SecurityError exception and terminnate this algorithm.

  2. Invoke the context tainting algorithm with the LabeledObject’s confidentiality and integrity labels.

  3. If the tainting algorithm raised an exception, re-throw the exception and terminate this algorithm.

    The tainting algorithm fails if code in a unconfined context tries to read data that should confine the context. To make it easier for developers to debug such cases, the user agent SHOULD report a message to inform developers that they can create cowl iframes wherein they can inspect such sensitive objects instead.
  4. Else, return the LabeledObject’s protected object.

Note: the labels of a LabeledObject are essentially public since code can always inspect the labels. However, to inspect the internal, protected object, the current context must be tainted according to the object’s labels. This ensures two things:
  • The context can’t violate the confidentiality of the data (as specified by the confidentiality label) by communicating arbitrarily once it reads data labeled as such.

  • The context can’t violate the integrity of entities more trustworthy than the data. (The trustworthiness of the data is specified by the integrity label.) In particular, once the context reads the data and gets tainted, the rest of the computation is restricted to writing to entities that are at most as trustworthy as the data, since the read data may have influenced the computation.

3.4.3. Methods

clone(CILabel labels)

On invocation, the user agent MUST use an algorithm equivalent to the following:

  1. Let obj be the protected object of the object on which the method was invoked.

  2. Let conf be the confidentiality label of the object on which the method was invoked.

  3. Let int be the integrity label of the object on which the method was invoked.

  4. Let newConf be the confidentiality member of the labels argument, if it is set. Otherwise, let newConf be conf.

  5. Let newInt be the integrity member of the labels parameter, if it is set. Otherwise, let newInt be int.

  6. Let privs be the internal privilege label of the current context privileges.

  7. If newConf.subsumes(conf, privs) returns false or if int.subsumes(newInt, privs) returns false, the method MUST throw a SecurityError exception and terminate this algorithm.

    Note, these checks ensure that the new labels of the object are at least as restricting as the original labels, taking into consideration the privileges of the context.

  8. Else, return a new LabeledObject, with the protected object set to obj, the confidentiality label set to newConf, and the integrity label set to newInt.

3.4.4. Examples

Below are several examples showing the usage of LabeledObjects. §1.2.1 Confining untrusted third-party services gives an example of how LabeledObjects can be used to confine third-party libraries (e.g., a password strength checker). §3.6.1.1 Examples and §3.6.2.1 Examples show how LabeledObjects are used with the XMLHttpRequest constructor.
The author of https://police.gov wishes to plot the location of police cars on a map provided by https://maps.biz without revealing the individual car locations (to the map provider). After revealing the general area to https://maps.biz, the author of https://police.gov labels the police car coordinates and sends them to the mapping service:

// Fetch map for provided location and draw it
mapsIframe.postMessage({ cmd: 'draw', location: ... }, mapsOrigin);

var locations = ... // Array of police-car coordinates

// Label the locations (as being sensitive to the police origin):
var labeledLocations = new LabeledObject(locations,
                             { confidentiality: new Label(window.location.origin) });

// Send the labeled locations to the map iframe to plot them
mapsIframe.postMessage({ cmd: 'plot', locations: labeledLocations }, mapsOrigin);

When receiving a draw message, the author of https://maps.biz navigates the iframe map (a nested context) to draw the map; otherwise, it simply forwards messages from the parent (e.g., plot, zoom, and move). (This design ensures that only the innermost iframe gets tainted.)

The innermost map cowl iframe registers a handler, that, for example, draws cars on top of map tiles:

window.addEventListener("message", function (event) {
  switch (event.data.cmd) {
    case 'plot':
      var coordinates = event.data.locations.protectedObject;
      coordinates.forEach(function (coordinate) {
        // add car to map at coordinate
      });
    case 'zoom': ...
    case 'move': ...
    ...
  };
}, false);

Note that before getting the first protectedObject, the iframe can communicate arbitrarily, e.g., to fetch map tiles. But once it inspects the confidential locations COWL confines the code—it restricts it to only communicating with https://police.gov. Importantly, it can keep receiving messages from its parent context via postMessage() to, for instance, move a car.

The author of https://example.com wishes to ensure that a particular JSON object conforms to a set of validation filters before submitting it to a remote server. Consider, for example, a form validator that checks if an email address is valid. To this end, it labels the JSON and sends the labeled object to a cowl iframe that performs the validation.

The validation author inspects the object, but only endorses it if it it is an email:

function handler(lObj) {
  if (isValidEmail(lObj.protectedObject)) {
    var origin = window.location.origin;
    // Endorse with application-specific label: ' OR app:isValidEmail'
    var endorsement = new Label(origin).or('app:isValidEmail');
    // Return a clone of the labeled object that is additionally
    // endorsed by the validator’s (sub-)origin.
    return lObj.clone({ integrity: lObj.integrity.and(endorsement) });
  } else {
    return null;
  }
}

The author of https://example.com can then pass the endorsed object to other validators (e.g., a validator that checks emails against a black-list) or end-point (e.g., a server), who can, in turn, further endorse the object or verify the origins that have endorsed it.

The Sec-COWL HTTP header field is used to convey label metadata.

Label metadata is either labeled context metadata or labeled data metadata.

Labeled context metadata encodes COWL state information, including:

Its ABNF is:

ctx-metadata        = ctx-directive *( ";" [ ctx-directive ] )
ctx-directive       = *WSP ctx-directive-name 1*WSP label-expression
ctx-directive-name  = "ctx-confidentiality" / "ctx-integrity" / "ctx-privilege"

Labeled data metadata is used to convey the confidentiality and integrity labels of an HTTP request or response, using the data-confidentiality and data-integrity directives. Its ABNF is:

data-metadata       = data-directive *( ";" [ data-directive ] )
data-directive      = *WSP data-directive-name 1*WSP label-expression
data-directive-name = "data-confidentiality" / "data-integrity"

The ABNF for serialized labels is:

label-expression   = empty-label / and-expression / or-expression / principal-expression
and-expression     = *WSP "(" or-expression *WSP ")" *( 1*WSP "AND" WSP and-expression )
or-expression      = *WSP principal-expression *( 1*WSP "OR" WSP or-expression ) 
empty-label        = "'none'"

Note, the ABNF grammar limits the expression of labels to conjunctions of disjunctions, even though the JavaScript API allows AND’s and OR’s to be used interchangably. This is done to simplify auditing of declarative (header) labels, but may be changed in future versions to be more flexible.

The ABNF for serialized principals is:

principal-expression        = origin-principal-expression 
                            / app-principal-expression 
                            / unique-principal-expression
origin-principal-expression = "'self'" / host-source
app-principal-expression    = "app:" 1*( ALPHA / DIGIT / "-" )
unique-principal-expression = "unique:" UUID

The parsing algorithms for label metadata are given in §4.10 Parse labeled data metadata and §4.11 Parse labeled context metadata.

3.5.1. Sec-COWL in HTTP Requests

The ABNF for Sec-COWL HTTP requests is:

"Sec-COWL:" ( ctx-metadata [ "," data-metadata ] ) / ( data-metadata [ "," ctx-metadata ] )

The user agent MUST send a header field named Sec-COWL along with requests if confinement mode is enabled and calling determine request’s referrer algorithm does not return none. The value of this header MUST contain the labeled context metadata of the context that performed the request. This labeled context metadata MUST include the current context confidentiality label, context integrity label, and context privileges. The user agent MAY send another header with this field name whose value is labeled data metadata (e.g., when sending labeled objects with XMLHttpRequest).

Note, according to [RFC2616], the user agent MAY combine multiple header field values into a single, comma-separated value.

Request header from a https://a.com page that has read data sensitive to https://b.com.
Sec-COWL: ctx-confidentiality https://b.com;
          ctx-integrity 'none';
          ctx-privilege https://a.com
A request sent from a public, untrustworthy https://university.edu context that owns a delegated privilege and a FreshPrivilege():
Sec-COWL: ctx-confidentiality 'none';
          ctx-integrity 'none';
          ctx-privilege (https://university.edu OR app:user1) AND (unique:a0281e1f-8412-4068-a7ed-e3f234d7fd5a)

When processing a request, a server SHOULD only use the first Sec-COWL header that contains a ctx-metadata directive to retrieve the labeled context metadata. Similarly, a server SHOULD only use the first Sec-COWL header that contains a data-metadata directive to retrieve the labeled data metadata of the request.

3.5.2. Sec-COWL in HTTP Responses

The ABNF for Sec-COWL HTTP responses is:

"Sec-COWL:" ctx-metadata / data-metadata

The header value may contain labeled context metadata which can be used to set the initial COWL state of a context; or it may contain labeled data metadata which specifies the sensitivity of the response (which COWL then uses to determine whether or not to block the response).

An author may wish to specify that the https://university.edu/~user1 page should run with a delegated privilege—namely, Label("https://university.edu/").or("app:user1")—from the start:
Sec-COWL: ctx-privilege 'self' OR app:user1;
The author of https://a.com may wish to respond to a request with data that is sensitive to both https://a.com and https://b.com, while simultaneously indicating that it endorses the response data:
Sec-COWL: data-confidentiality 'self' AND https://b.com;
          data-integrity 'self'

COWL blocks the response unless the current context’s labels are at least as restricting.

To process this header, the user agent MUST use the Process response to request as COWL algorithm when performing a fetch, as described in §3.7.1 Modifications to Fetch.

3.6. Extensions to XMLHttpRequest

should we disable XHR and just force developers to use fetch?

The XMLHttpRequest specification SHOULD contain the modifications described below to enable the rest of this specification’s work [XHR].

3.6.1. Sending labeled objects

To allow authors to send labeled objects to a remote server, this specification extends the XMLHttpRequest interface with an overloaded send() method:
partial interface XMLHttpRequest {
  void send(LabeledObject lobj);
};

The send(lobj) method MUST use an algorithm that is equivalent to the following:

  1. Let obj be the protected object of the lobj argument.

  2. Let conf be the confidentiality label of the lobj argument.

  3. Let int be the integrity label of the lobj argument.

  4. Let privs be the current context privileges.

  5. Let remoteConf be the label returned by the Label(principal) constructor called with the stringified origin url associated with the request.

  6. If remoteConf.subsumes(conf, privs) returns false, throw a SecurityError and terminate this algorithm.

    The user agent SHOULD report a warning that the context attempted to leak data to a remote server.

  7. Let json be a new JSON object with the following entries:

    • "confidentiality" set to the serialized conf.

    • "integrity" set to the the serialized int.

    • "object" set to obj.

  8. Set the Content-Type header to application/labeled-json.

  9. Append a header named Sec-COWL to the author request headers associated with the object this methods was called on. The value of the Sec-COWL header MUST be labeled data metadata containing the confidentiality and integrity labels of the lobj argument.

  10. Invoke the send() method on the object this method was called on with json as an argument.

    Note, that send() throws an exception if obj cannot be serialized. User agents MUST ensure that all protected objects can be serialized at the time of creating LabeledObjects.

    This algorithm does not check if the integrity label of the object subsumes the server’s integrity label. It is the server’s responsibility to ensure that untrustworthy data does not affect its computation in an unsafe way. Indeed, the only reason for checking the confidentiality labels is because the user agent has no way to ensure that the server will respect the confidentiality of the data.
3.6.1.1. Examples
Author of https://example.com sends JSON object endorsed by https://validator.com:
// Suppose that labeledObject is a public, high-integrity value:
labeledObject.confidentiality.toString() === "'none'";
labeledObject.integrity.toString() === "https://validator.com";

// Create an XHR request:
var req = new XMLHttpRequest()
req.open("POST", "https://example.com/");

// Send the labeled object:
req.send(labeledObject);

Assuming the context has a default COWL state, send() would make an HTTP request of the form:

Sec-COWL: ctx-confidentiality 'none';
          ctx-integrity 'none';
          ctx-privilege https://example.com
Sec-COWL: data-confidentiality 'none';
          data-integrity https://validator.com
Content-Type: application/labeled-json;

{
  "confidentiality": "'none'",
  "integrity": "https://validator.com",
  "object": ... JSON object ...
}

The server can then verify the integrity label of the request and ensure that, if the user agent is conformant, the data was endorsed by https://validator.com.

3.6.2. Receiving labeled objects

To allow authors to receive labeled objects from remote servers, the XMLHttpRequest specification SHOULD contain the following modifications [XHR]:
  1. The XMLHttpRequestResponseType enumeration is extended with a new response type:

    enum XMLHttpRequestResponseType {
      // ... existing response types ...
      "labeled-json"
    };
    
  2. The Response body section of the specification is modified to add:

    1. An XMLHttpRequest has associated response LabeledObject object.

    2. A labeled JSON response is the return value of these steps:

      1. If the response LabeledObject object is non-null, return it.

      2. If responseType is not "labeled-json" or the final MIME type is not application/labeled-json, return null.

      3. Let bytes be the response’s body.

      4. If bytes is null, return null.

      5. Let JSON text be the result of running utf-8 decode on byte stream bytes.

      6. Let JSON object be the result of invoking the initial value of the parse property of the JSON object, with JSON text as its only argument. If that threw an exception, return null. [ECMA-262]

      7. If the JSON object is missing any of the three entries: "object", "confidentiality", or "integrity" return null.

      8. Let protected object be the value of the "object" entry.

      9. Let self be the url associated with the response.

      10. Let conf be the label returned by invoking the §4.12 Parse label expression algorithm with the "confidentiality" entry of the JSON object and self. If parsing failed, return null.

      11. Let int be the label returned by invoking the §4.12 Parse label expression algorithm with the "integrity" entry of the JSON object and self. If parsing failed, return null.

      12. Let responseInt be the label returned by the Label(principal) constructor called with self.

      13. If responseInt does not subsume int, return null.

        The user agent SHOULD report a warning message indicating that the server provided an integrity label that it is not allowed to provide.

      14. Set the response LabeledObject object to a newly created LabeledObject whose protected object is protected object, whose confidentiality label is conf, and whose integrity label is int.

      15. Return the response LabeledObject object.

  3. Modify the response attribute by adding the following clause to step 2 of the ↪ Otherwise clause:

    ↪ If responseType is "labeled-json"

    Return the labeled JSON response.

  4. Modify step 12 of the open() method by adding the following sub-step:

3.6.2.1. Examples
§1.2.2 Sharing data with third-party mashups gives an example of a mashup scenario wherein the data provider uses the Sec-COWL HTTP response header to ensure that the mashup integrator can only read the HTTP response if it is sufficiently confined. A more permissive approach is to send a labeled JSON response.

Specifically, the server operator of https://provider.com uses a CORS response header to send https://mashup.com a labeled JSON object. To ensure that the data is protected it sets the Content-Type response header value to application/labeled-json and sets the labels appropriately:

Access-Control-Allow-Origin: https://mashup.com
Content-Type: application/labeled-json;

{
  "confidentiality": "'self'",
  "integrity": "'self'",
  "object": ... JSON object ...
}

The confidentiality label specifies that the object is confidential to https://provider.com and should not be disseminated arbitrarily.

Note, the server operator can also set a Sec-COWL response header if it wished to ensure that the context is already confined according to some label.

The author of https://mashup.com can read such labeled responses by simply setting the responseType accordingly:


// Create an XHR request to get the data:
var req = new XMLHttpRequest()
req.open("GET", "https://provider.com/apis/...");
req.responseType = "labeled-json";
req.onload = function (e) {
  var labeledObject = req.response; // is a LabeledObject

  // At this point, the context is still untainted, but:
  labeledObject.confidentiality.toString() === "https://provider.com";
  labeledObject.integrity.toString() ===  "https://provider.com";
};
req.send();

Here, COWL sets the response to a new LabeledObject, but does not taint the context with the response label. Indeed the https://mashup.com integrator can perform many other requests to different origins. Only when the protected objects of these labeled objects are used will COWL taint the context and impose the label restrictions.

An image provider can serve "read-once" images by labeling them with a unique origin when reply to an HTTP request:
Access-Control-Allow-Origin: *
Content-Type: application/labeled-json;

{
  "confidentiality": app:too-secret,
  "integrity": 'none',
  "object": ... base64-encoded image ...
}

Once the receiver inspects the protectedObject of the response, COWL taints the context and ensures that it cannot communicate with anybody.

Note, to read the protected object, one must do so in a confined context since reading such a sensitive data would prevent code from communicating arbitrarily thereafter.

3.7. Confinement Enforcement

This sub-section is non-normative

To enforce confinement, COWL ensures that code in a context cannot send data (e.g., via cross-document messaging or by performing a fetch) to contexts or servers that do not preserve the confidentiality of the data. Similarly, COWL ensures that a context cannot receive data from a context or server that is less trustworthy.

3.7.1. Modifications to Fetch

The Fetch specification SHOULD contain the following modifications in order to enable the rest of this specification’s work [FETCH]:

  1. Perform the following step between step 5 and 6 in the "main fetch" algorithm:

    1. If should fetching request be blocked as COWL returns blocked, set response to a network error.

  2. Perform the following step between step 13 and 14 in the "main fetch" algorithm:

    1. If process response to request as COWL returns blocked, set response to a network error.

3.7.2. Modifications to Web Messaging

The Web Messaging specification SHOULD contain the following modifications in order to enable the rest of this specification’s work [WEBMESSAGING]:

  1. Perform the following step between step 9 and 10 in the posting messages algorithm:

    1. Let conf be the current context’s effective confidentiality label.

    2. Let int be the current context’s effective integrity label.

    3. Let dstState be the COWL state associated with the Document of the Window object on which the method was invoked.

    4. Let dstConf be the Label returned by the label upgrade algorithm when invoked with the dstState context confidentiality label and context privilege.

      Note, in using the label upgrade COWL flexibly assumes that receivers wish to receive data potentially sensitive to their origin (really data they can declassify with their privileges).

    5. Let dstInt be the dstState context integrity label.

    6. If dstConf does not subsume conf or if int does not subsume dstInt, then abort the remaining steps silently.

  2. Perform the following step between step 9 and 10 in the MessagePort postMessage() method:

    1. Let conf be the current context’s effective confidentiality label.

    2. Let int be the current context’s effective integrity label.

    3. Let dstState be the COWL state associated with the owner of the target port the Message Port postMessage() was called on.

    4. Else, let dstConf be the Label returned by the label upgrade algorithm when invoked with the dstState context confidentiality label and context privilege.

      Note, in using the label upgrade COWL flexibly assumes that receivers wish to receive data potentially sensitive to their origin (really data they can declassify with their privileges).

    5. Let dstInt be the dstState context integrity label.

    6. If dstConf does not subsume conf or if int does not subsume dstInt, then abort the remaining steps.

3.7.3. Modifications to HTML5

The HTML5 specification SHOULD contain the following modifications in order to enable the rest of this specification’s work [HTML5]:

  1. To allow authors to create confined contexts this this specification extends the HTMLIFrameElement interface with a new cowl attribute:

    partial interface HTMLIFrameElement {
      attribute boolean cowl;
    };
    

    The cowl attribute, when specified, enables a set of extra restrictions on any content hosted by the iframe, much like the sandbox attribute. We call an iframe with the cowl attribute set a cowl iframe.

    When an iframe element with a cowl attribute has its nested browsing context created (before the initial about:blank Document is created), the user agent MUST enable the context’s confinement mode. The iframe element’s cowl attribute may not be set or changed after this point.

    what’s the best way to deal with authors modifying the cowl attribute?

  2. When confinement mode is enabled the user agent MUST ensure that content cannot access other content from the same origin (e.g., using an iframe’s contentDocument) or use otherwise unsafe APIs that would violate label restrictions.

    Specifically, if a browsing context’s confinement mode is enabled the user agent MUST set the following flags of the context’s active sandboxing flag set:

    In addition to these flags, the user agent MUST set a container policy of the cowl iframe that contains the confined context that disables the following features:

4. Algorithms

4.1. Label Normal Form Reduction

The label normal form reduction algorithm takes a label argument and produces a Label value according to the following steps:
  1. Let lset be the label set of an empty label.

  2. For each disjunction set dset in the label set of label:

    1. If there is no disjunction set in lset that is a subset of dset, then:

      1. Remove every disjunction set in lset that dset is a subset of.

      2. Add dset to lset.

  3. Return a newly created Label whose label set is lset.

Note, this algorithms assumes that disjunction sets and label sets do not have duplicate elements, much like mathematical sets.

The Label API uses this algorithm to ensure that labels don’t have redundant information. Consider for example, the following labels:
var a    = Label("https://a.com");  // https://a.com
var aORb = Label("https://a.com").or("https://b.com"); // https://a.com OR https://b.com
var a2   = a.and(aORb); // (https://a.com) AND (https://a.com OR https://b.com) ≡ https://a.com

The label a2 is equivalent to a (since a.subsumes(aORb)):

a2.toString() === "https://a.com";
a2.equals(a);

4.2. Label Subsumption

The label subsumption algorithm takes a two labels A and B and produces a boolean according to these steps:
  1. If, for each disjunction set b in the label set of B there is disjunction set a in the label set of A such that a is a subset of b, return true.

  2. Else, return false.

Note, when interpreting labels as mathematical formulae, label subsumption is logical implication: A subsumes B is equivalent as A implies B, i.e, AB.

4.3. Label Downgrade

The label downgrade algorithm takes a label label and a privilege priv, and returns the least restricting label according to the following steps:
  1. Let privLabel be the internal privilege label of priv.

  2. Let lset be the label set of an empty label.

  3. For each disjunction set dset in the label set of label:

    1. Let cur be a newly created Label whose label set is dset.

    2. If privLabel does not subsume cur, add dset to lset.

  4. Return a newly created Label whose label set is lset.

Note, label downgrade removes every disjunction set permitted by priv. This is used to safely declassify data labeled label.

4.4. Label Upgrade

The label upgrade algorithm takes a label label and a privilege priv, and returns the most permissive label according to the following steps:
  1. Let privLabel be the internal privilege label of priv.

  2. Return label.and(privLabel).

Note, label upgrade is the dual of label downgrade. This can be used to safely endorse data labeled label (and thus potentially already endorsed).

4.5. Context Tainting

The context tainting algorithm takes a two labels, confidentiality and integrity, and updates the context labels to allow for reading data labeled with these labels. If the context is an unconfined context and tainting the context would change its COWL state, the algorithm throws a SecurityError exception. The user agent MUST use an algorithm whose behavior is as follows:
  1. Let currentConf be the current context confidentiality label.

  2. Let currentInt be the current context integrity label.

  3. Let newConf be the Label returned by the by the label downgrade algorithm when invoked with currentConf.and(confidentiality) and current privilege.

  4. Let newInt be the Label returned by the label downgrade algorithm when invoked with currentInt.or(integrity) and current privilege.

  5. If the current context is an unconfined context and either newConf or newInt are not the empty label, throw a SecurityError exception and terminate this algorithm.

  6. Set the context confidentiality label to newConf.

  7. Set the context integrity label to newInt.

4.6. Write Check

The write check algorithm takes two labels, objConf and objInt, and returns true if the current context is allowed to write to (or create) an entity labeled as such; otherwise, it returns false. The user agent MUST use an algorithm whose behavior is as follows:
  1. Let currentConf be the current context’s effective confidentiality label.

  2. Let currentInt be the current context’s effective integrity label.

  3. If objConf does not subsume currentConf or if currentInt does not subsume objInt, return false.

  4. Else, return true.

4.7. Structured Cloning

When a user agent is required to obtain a structured clone of an object whose type is defined in this document, it MUST use an algorithm whose behavior is as follows:
  1. Let input be the value being cloned.

  2. If input is a Label object, let output be a newly constructed Label object with the same label set as that of input.

  3. If input is a Privilege object, then:

    1. If the input’s internal privilege label subsumes any label whose label set is a singleton origin principal, let output be null.

    2. Else, let output be a newly constructed Privilege object with the same internal privilege label as that of input.

    To prevent attacks that launder default privileges, the current version of COWL only allows transferring weaker delegated privileges or privileges constructed with FreshPrivilege(). The first step above ensures this by setting the output to null if the privilege subsumes any privilege corresponding to an origin principal.
  4. If input is a LabeledObject object, let output be a newly constructed LabeledObject object whose confidentiality and integrity labels are the same as that of input, and whose internal protected object is a structured clone of the protected object of the input LabeledObject.

  5. Return output.

Note, cross-context messaging constructs such as postMessage() use the structured clone algorithm (e.g., see the internal structured cloning algorithm). This algorithm is used to allow authors to transfer COWL object, such as LabeledObjects, to other contexts.

4.8. Should fetching request be blocked as COWL?

Note: this algorithm is used to determine whether a request should be entirely blocked, because it may potentially leak sensitive data to an unauthorized server.

Given a Request request, a user agent determines whether the Request request should proceed or not via the following algorithm:

  1. Let context be the client associated with the request.

  2. If context is null, let context be the incumbent settings object.

    Note, the client associated with the request is null when navigating, so we use the incumbent settings object to get the COWL state of the context that initiated the request.

  3. Let state be the COWL state retrieved via the environment settings object context.

  4. If the state confinement mode is not enabled, return allowed and terminate this algorithm.

  5. Let conf be the state effective confidentiality label.

  6. Let dstConf be the Label created by invoking the Label(principal) constructor with the stringified origin of the url associated with the request.

  7. If dstConf subsumes conf, return allowed.

  8. Else, return blocked.

    The user agent SHOULD report a warning that the context attempted to leak data to a remote server.

Note, the integrity label of the current context is not used in this algorithm since, conceptually, the integrity label of a server is the empty label and, thus, always subsumed. Server operators SHOULD check the Sec-COWL request header to ensure untrustworthy data does not affect the computation in an unsafe way.

4.9. Process response to request as COWL

If a request proceeds, we still might want to block the response based on the labeled data metadata of the response. For example, if the current confidentiality label does not subsume the confidentiality label of the response, the user agent MUST block the response since it could otherwise violate the confidentiality of the response data. (The dual holds for integrity.) This algorithm is used to make the determination of whether or not a response is blocked.

This algorithm is also used to set the COWL state for new documents and Workers according to the server-supplied labeled context metadata.

Given a Request request and Response response, a user agent determines whether the response should be returned via the following algorithm:

  1. If the response’s header list has no header whose name is Sec-COWL, return allowed and terminate this algorithm.

  2. Let destination be the request’s destination.

  3. Let context be the client associated with the request.

  4. If context is null, let context be the incumbent settings object.

    Note, the client associated with the request is null when navigating, so we use the incumbent settings object to get or set the COWL state of the context that initiated the request.

  5. Let state be the COWL state retrieved via the environment settings object context.

  6. Let metadata be the first header whose name is Sec-COWL in the response’s header list.

  7. If destination is "document", "worker" or "serviceworker":

    1. Let self be the serialization of the origin retrieved via the environment settings object context.

    2. Let conf, int, priv be the result of calling the parse labeled context metadata algorithm with metadata and self.

    3. If either conf, int, or priv are null, return blocked.

      The user agent SHOULD report a warning that the server supplied a malformed Sec-COWL header.

    4. Else:

      1. If context is an unconfined context, return blocked and terminate this algorithm.

        The user agent SHOULD report a warning that the application attempted to embed confined content outside a cowl iframe.

      2. If priv is not a delegated privilege of the state context privilege, return blocked and terminate this algorithm.

        The user agent SHOULD report a warning that the server supplied a privilege that it is not trusted for.

      3. If the state effective integrity label does not subsume int, return blocked and terminate this algorithm.

        The user agent SHOULD report a warning that the server supplied an integrity label that it is not trusted for.

      4. Set the state context confidentiality label to conf.

      5. Set the state context integrity label to int.

        Note, by performing the label subsumption check (step 3 above) before setting the context privilege (next step), the context integrity label can be upgraded from the empty label, while allowing the context privilege to also be dropped.

      6. Set the state context privilege to priv.

      7. Return allowed.

  8. Else:

    1. Let self be the origin of the url associated with the response.

    2. Let conf and int be the results of calling the parse labeled data metadata with metadata and self.

    3. If either conf or int is null, return blocked and terminate this algorithm.

      The user agent SHOULD report a warning that the server supplied a malformed Sec-COWL header.

    4. Let effConf be the Label returned by the label downgrade algorithm when invoked with conf and the state current privilege.

      Note, effConf is the effective confidentiality label of the response—COWL flexibly declassifies responses (as much as the current privilege permits).

    5. If the state context confidentiality label subsumes effConf and int subsumes the state effective integrity label, return allowed.

    6. Else, return blocked.

      Note, COWL conservatively blocks a response that is potentially more confidential or less trustworthy than the context making the request. In future versions of COWL, certain responses (e.g., images) which are only not as trustworthy as the context integrity label may be allowed by the user agent.

4.10. Parse labeled data metadata

To parse labeled data metadata metadata for origin self, the user agent MUST use an algorithm equivalent to the following:

  1. Let conf be null.

  2. Let int be null.

  3. For each non-empty token returned by strictly splitting the string metadata on the character U+003B SEMICOLON (;):

    1. Skip whitespace.

    2. Collect a sequence of characters that are not space characters. The collected characters are the directive name.

    3. If there are characters remaining in token, skip ahead exactly one character (which must be a space character).

    4. The remaining characters in token (if any) are the directive value.

    5. Let label value be the label returned by invoking the parse label-expression algorithm with the directive value and self. If parsing failed, terminate the rest of these sub-steps.

      The user agent SHOULD report a warning that the server provided a malformed label directive.

    6. If directive name is data-confidentiality and conf is null, let conf be label value.

    7. Else, if directive name is data-integrity and int is null, let int be label value.

    8. Else, terminate the rest of these sub-steps.

      The user agent SHOULD report a warning that the server provided a malformed label directive.

  4. Return conf and int.

To make it easier for developers to debug applications, user agents SHOULD report the directives that were ignored.

4.11. Parse labeled context metadata

To parse labeled context metadata metadata for origin self, the user agent MUST use an algorithm equivalent to the following:

  1. Let conf be null.

  2. Let int be null.

  3. Let priv be null.

  4. For each non-empty token returned by strictly splitting the string metadata on the character U+003B SEMICOLON (;):

    1. Skip whitespace.

    2. Collect a sequence of characters that are not space characters. The collected characters are the directive name.

    3. If there are characters remaining in token, skip ahead exactly one character (which must be a space character).

    4. The remaining characters in token (if any) are the directive value.

    5. Let label value be the label returned by invoking the parse label-expression algorithm with the directive value and self. If parsing failed, terminate the rest of these sub-steps.

      The user agent SHOULD report a warning that the server provided a malformed label directive.

    6. If directive name is ctx-confidentiality and conf is null, let conf be label value.

    7. Else, if directive name is ctx-integrity and int is null, let int be label value.

    8. Else, if directive name is ctx-privilege and priv is null, let priv be a newly created privilege whose internal privilege label is set to label value.

    9. Else, terminate the rest of these sub-steps.

      The user agent SHOULD report a warning that the server provided a malformed label directive.

  5. Return conf, int, and priv.

To make it easier for developers to debug applications, user agents SHOULD report the directives that were ignored.

4.12. Parse label expression

The parse label-expression algorithm takes a input representing a label-expression and a stringified origin URL self and returns the parsed Label. If at any point the algorithm says that it "fails", this means that it is aborted at that point and returns nothing. The user agent MUST use an algorithm equivalent to the following:

  1. Let label be a new empty label.

  2. If input is not a string, fail.

  3. Strip and collapse whitespace from input.

  4. Let AND expr be the remaining characters in input.

  5. If AND expr is the string "'none'", return label and terminate this algorithm.

  6. Split the AND expr string on "AND". Let AND tokens be the resulting list of tokens, if the splitting didn’t fail. Otherwise, fail.

  7. For each token in AND tokens, run the following sub-steps:

    1. Let input be the token.

    2. If the number of elements in AND tokens is greater than 1:

      1. If first character of input is not "(" (UA+0028), fail.

      2. If last character of input is not ")" (UA+0029), fail.

      3. Remove the first and last characters from input.

    3. Else, if first character of input is "(" (UA+0028) or if last character of input is ")" (UA+0029):

      1. If first character of input is not "(" (UA+0028), fail.

      2. If last character of input is not ")" (UA+0029), fail.

      3. Remove the first and last characters from input.

    4. Let OR expr be the remaining characters in input.

    5. Let orExp be a new empty label.

    6. Split the string OR expr on "OR". Let OR tokens be the resulting list of tokens, if the splitting didn’t fail. Otherwise, fail.

    7. For each token in OR tokens, run the following sub-steps:

      1. Let prin be the token.

      2. If prin is the string "'self'", set prin be self.

      3. Set orExp to orExp.or(prin), if calling the or method didn’t throw an exception. Otherwise, fail.

        Note, the method throws an exception if prin is not a principal. Hence, this algorithm should fail.

    8. Set label to label.and(orExp).

  8. Return label.

When a user agent has to split a string on particular delimiter characters delimiter, it MUST use an algorithm equivalent to the following:

  1. Let input be the string being split.

  2. Let position be a pointer into input, initially pointing at the start of the string.

  3. Let delimiter length be the number of characters in delimiter.

  4. Let tokens be the resulting list of tokens.

  5. Strip leading and trailing whitespace.

  6. If input is the empty string, fail.

  7. While position is not past the end of input:

    1. Let s be the empty string.

    2. Skip whitespace.

    3. Let done be false.

    4. While done is false and position is not past the end of input:

      1. Collect a sequence of characters that are not space characters. Append the resulting sequence to s.

      2. If position points past the end of input, set done to true and end these sub-steps.

      3. Collect a sequence of characters that are space characters. Let ws be the resulting sequence.

      4. If the next delimiter length characters are an ASCII case-insensitive match for the string delimiter, then set done to true and advance position by delimiter length characters.

      5. Else, append ws to s.

    5. Append s to tokens.

  8. Return tokens.

5. IANA Considerations

5.1. The Sec-COWL HTTP Header Field

The permanent message header field registry should be updated with the following registration [RFC3864]:
Header field name
Sec-COWL
Applicable protocol
http
Status
standard
Author/Change controller
W3C
Specification document
This specification (See §3.5 The Sec-COWL HTTP Header Field)

5.2. The application/labeled-json MIME media type

Type name
application
Subtype name
labeled-json
Required parameters
Same as for application/json. [JSON]
Optional parameters
Same as for application/json. [JSON]
Encoding considerations
Same as for application/json. [JSON]
Security considerations
Same as for application/json. [JSON]
Interoperability considerations
Same as for application/json. [JSON]
Published specification
Labeling a resource with the application/labeled-json type asserts that the resource is a JSON text that consists of an object with a single entry called "confidentiality" consisting of a string, a single entry called "integrity" consisting of string, and a single entry called "object" consisting of a JSON object. The relevant specifications are the JSON specification and this specification. [JSON]
Author/Change controller
W3C

6. Acknowledgements

Thanks to Niklas Andreasson, Dan Boneh, Brendan Eich, Lon Ingram, Brad Hill, Dave Herman, Bobby Holley, Brad Karp, Jonathan Kingston, Petr Marchenko, David Mazières, Devon Rifkin, Alejandro Russo, Brian Smith, and the W3C WebAppSec team for influencing (directly or otherwise) the design of COWL and/or their comments on this document.

Conformance

Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Conformant Algorithms

Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and abort these steps") are to be interpreted with the meaning of the key word ("must", "should", "may", etc) used in introducing the algorithm.

Conformance requirements phrased as algorithms or specific steps can be implemented in any manner, so long as the end result is equivalent. In particular, the algorithms defined in this specification are intended to be easy to understand and are not intended to be performant. Implementers are encouraged to optimize.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[CORS]
Anne van Kesteren. Cross-Origin Resource Sharing. 16 January 2014. REC. URL: https://www.w3.org/TR/cors/
[CSP2]
Mike West; Adam Barth; Daniel Veditz. Content Security Policy Level 2. 15 December 2016. REC. URL: https://www.w3.org/TR/CSP2/
[CSP3]
Mike West. Content Security Policy Level 3. 13 September 2016. WD. URL: https://www.w3.org/TR/CSP3/
[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMA-262]
ECMAScript Language Specification. URL: https://tc39.github.io/ecma262/
[ENCODING]
Anne van Kesteren. Encoding Standard. Living Standard. URL: https://encoding.spec.whatwg.org/
[FEATURE-POLICY]
Feature Policy. Living Standard. URL: https://wicg.github.io/feature-policy/
[FETCH]
Anne van Kesteren. Fetch Standard. Living Standard. URL: https://fetch.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[HTML5]
Ian Hickson; et al. HTML5. 28 October 2014. REC. URL: https://www.w3.org/TR/html5/
[IndexedDB]
Nikunj Mehta; et al. Indexed Database API. 8 January 2015. REC. URL: https://www.w3.org/TR/IndexedDB/
[JSON]
T. Bray, Ed.. The JavaScript Object Notation (JSON) Data Interchange Format. March 2014. Proposed Standard. URL: https://tools.ietf.org/html/rfc7159
[REFERRER-POLICY]
Jochen Eisinger; Emily Stark. Referrer Policy. 26 January 2017. CR. URL: https://www.w3.org/TR/referrer-policy/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[RFC2616]
R. Fielding, Ed.; J. Reschke, Ed.. Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content. June 2014. Proposed Standard. URL: https://tools.ietf.org/html/rfc7231
[RFC3864]
G. Klyne; M. Nottingham; J. Mogul. Registration Procedures for Message Header Fields. September 2004. Best Current Practice. URL: https://tools.ietf.org/html/rfc3864
[RFC4122]
P. Leach; M. Mealling; R. Salz. A Universally Unique IDentifier (UUID) URN Namespace. July 2005. Proposed Standard. URL: https://tools.ietf.org/html/rfc4122
[RFC5234]
D. Crocker, Ed.; P. Overell. Augmented BNF for Syntax Specifications: ABNF. January 2008. Internet Standard. URL: https://tools.ietf.org/html/rfc5234
[RFC6454]
A. Barth. The Web Origin Concept. December 2011. Proposed Standard. URL: https://tools.ietf.org/html/rfc6454
[SECURE-CONTEXTS]
Mike West. Secure Contexts. 15 September 2016. CR. URL: https://www.w3.org/TR/secure-contexts/
[SERVICE-WORKERS-1]
Alex Russell; et al. Service Workers 1. 11 October 2016. WD. URL: https://www.w3.org/TR/service-workers-1/
[URL]
Anne van Kesteren; Sam Ruby. URL. WD. URL: https://www.w3.org/TR/url
[WebIDL]
Cameron McCormack; Boris Zbarsky; Tobie Langel. Web IDL. 15 December 2016. ED. URL: https://heycam.github.io/webidl/
[WEBIDL2]
Cameron McCormack; Boris Zbarsky. Web IDL (Second Edition). ED. URL: https://heycam.github.io/webidl/
[WEBMESSAGING]
Ian Hickson. HTML5 Web Messaging. 19 May 2015. REC. URL: https://www.w3.org/TR/webmessaging/
[WEBRTC]
Adam Bergkvist; et al. WebRTC 1.0: Real-time Communication Between Browsers. 22 August 2017. WD. URL: https://www.w3.org/TR/webrtc/
[WEBSTORAGE]
Ian Hickson. Web Storage (Second Edition). 19 April 2016. REC. URL: https://www.w3.org/TR/webstorage/
[WORKERS]
Ian Hickson. Web Workers. 24 September 2015. WD. URL: https://www.w3.org/TR/workers/
[XHR]
Anne van Kesteren. XMLHttpRequest Standard. Living Standard. URL: https://xhr.spec.whatwg.org/

Informative References

[COWL-OSDI]
Deian Stefan; et al. Protecting Users by Confining JavaScript with COWL. URL: https://www.usenix.org/system/files/conference/osdi14/osdi14-paper-stefan.pdf
[DCLabels]
Deian Stefan; et al. Disjunction Category Labels. URL: http://www.scs.stanford.edu/~deian/pubs/stefan:2011:dclabels.pdf
[DOM-Parsing]
Travis Leithead. DOM Parsing and Serialization. 17 May 2016. WD. URL: https://www.w3.org/TR/DOM-Parsing/

IDL Index

[Constructor, Constructor(DOMString principal), Exposed=(Window, Worker)]
interface Label {
  boolean equals(Label other);
  boolean subsumes(Label other, optional Privilege priv);

  Label and((Label or DOMString) other);
  Label _or((Label or DOMString) other);

  stringifier;
};

[Constructor, Exposed=(Window, Worker), SecureContext]
interface Privilege {
  static Privilege FreshPrivilege(); // Named constructor
  Label asLabel();

  Privilege combine(Privilege other);
  [Throws] Privilege delegate(Label label);
};

[SecureContext, COWLContext]
interface COWL {
  [SetterThrows] static attribute Label confidentiality;
  [SetterThrows] static attribute Label integrity;
  [SetterThrows] static attribute Privilege privilege;
};

dictionary CILabel {
  Label? confidentiality;
  Label? integrity;
};

[Constructor(object obj, CILabel? labels), Exposed=(Window, Worker), SecureContext]
interface LabeledObject {
  readonly attribute Label confidentiality;
  readonly attribute Label integrity;

  [GetterThrows] readonly attribute object protectedObject;

  [Throws] LabeledObject clone(CILabel labels);
};

partial interface XMLHttpRequest {
  void send(LabeledObject lobj);
};

enum XMLHttpRequestResponseType {
  // ... existing response types ...
  "labeled-json"
};

partial interface HTMLIFrameElement {
  attribute boolean cowl;
};

Issues Index

should protectedObject be a promise? Otherwise we may be a bit too inflexible.
should we disable XHR and just force developers to use fetch?
what’s the best way to deal with authors modifying the cowl attribute?
is there a better way for us to just disallow direct DOM access and preserve same-origin?