forked from w3c/webappsec-cowl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.src.html
3238 lines (2602 loc) · 141 KB
/
index.src.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<h1>Confinement with Origin Web Labels</h1>
<pre class="metadata">
Status: ED
Group: WebAppSec
TR: https://www.w3.org/TR/COWL/
ED: https://w3c.github.io/webappsec-cowl/
Shortname: COWL
Level: 1
Editor: Deian Stefan, Intrinsic and UC San Diego, [email protected]
Editor: Abdulrahman Alkhelaifi, UC San Diego, [email protected]
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.
Indent: 2
Version History: https://github.com/w3c/webappsec-cowl/commits/master/index.src.html
Boilerplate: omit conformance, omit feedback-header
!Participate: <a href="https://github.com/w3c/webappsec-cowl/issues/new">File an issue</a> (<a href="https://github.com/w3c/webappsec-cowl/issues">open issues</a>)
Inline Github Issues: true
Markup Shorthands: css off, markdown on
</pre>
<pre class="anchors">
spec: CORS; urlPrefix: https://www.w3.org/TR/cors/
type: dfn
text: CORS
text: Access-Control-Allow-Origin; url: access-control-allow-origin-response-header
spec: IndexedDB; urlPrefix: https://www.w3.org/TR/IndexedDB-2/
type: dfn
text: IndexedDB
spec: WEBMESSAGING; urlPrefix: https://www.w3.org/TR/webmessaging/
type: method
text: postMessage(); url: dom-window-postmessage
type: dfn
text: posting messages; url: posting-messages
text: owner; url: concept-port-owner
text: Message Port; url: messageport
text: MessagePort postMessage(); url: dom-messageport-postmessage
text: cross-document messaging; url: web-messaging
spec: WORKERS; urlPrefix: https://www.w3.org/TR/workers/
type: dfn
text: Worker
text: Web Worker; url: infrastructure
spec: CSP2; urlPrefix: https://www.w3.org/TR/CSP2/
type: dfn
text: content-security-policy
type: dfn
text: host-source; url: host_source
spec: HTML5; urlPrefix: https://www.w3.org/TR/html5/
type: element-attr
urlPrefix: embedded-content-0.html
text: sandbox; for: iframe; url: attr-iframe-sandbox
text: contentDocument; for: iframe; url: dom-iframe-contentdocument
type: dfn
urlPrefix: webappapis.html
text: environment settings object; url: settings-object
text: incumbent settings object; url: incumbent-settings-object
urlPrefix: embedded-content-0.html
text: iframe; url: the-iframe-element
urlPrefix: browsers.html
text: browsing context; url: windows
text: top-level browsing context; url: top-level-browsing-context
text: active sandboxing flag set; url: active-sandboxing-flag-set
text: sandboxing flag set; url: sandboxing-flag-set
text: forced sandboxing flag set; url: forced-sandboxing-flag-set
text: sandboxed plugins browsing context flag;url: sandboxed-plugins-browsing-context-flag
text: sandboxed document.domain browsing context flag;url: sandboxed-document.domain-browsing-context-flag
text: sandboxed origin browsing context flag;url: sandboxed-origin-browsing-context-flag
text: sandboxed navigation browsing context flag;url: sandboxed-navigation-browsing-context-flag
text: sandboxed auxiliary navigation browsing context flag;url: sandboxed-auxiliary-navigation-browsing-context-flag
text: sandboxed top-level navigation browsing context flag;url: sandboxed-top-level-navigation-browsing-context-flag
text: navigating; url: navigate
urlPrefix: infrastructure.html
text: structured clone; url: structured-clone
text: structurally cloned; url: structured-clone
text: structurally clonable; url: structured-clone
text: internal structured cloning algorithm; url: internal-structured-cloning-algorithm
text: strictly split a string
text: skip whitespace
text: collect a sequence of characters
text: strip leading and trailing whitespace
text: strip and collapse whitespace
text: ASCII case-insensitive
text: space characters; url: space-character
urlPrefix: dom.html
text: script from reading from or writing to the document.cookie IDL attribute; url: sandboxCookies
type: interface
urlPrefix: browsers.html
text: Window; url: window
urlPrefix: dom.html
text: Document; url: the-document-object
spec: feature-policy; urlPrefix: https://wicg.github.io/feature-policy/
type: dfn
text: container policy; url: container-policies
spec: RFC6454; urlPrefix: https://tools.ietf.org/html/rfc6454
type: dfn
text: origin; url: section-3.2
text: globally unique identifier; url: section-2.3
spec: RFC4122; urlPrefix: https://tools.ietf.org/html/rfc4122
type: dfn
text: UUID; url: section-3
spec: URL; urlPrefix: https://www.w3.org/TR/url/
type: interface
text: URL; url: concept-url
type: dfn
text: scheme; url: concept-url-scheme
type: attribute
text: host; for: URL; url: concept-url-host
text: path; for: URL; url: concept-url-path
text: port; for: URL; url: concept-url-port
text: scheme; for: URL; url: concept-url-scheme
spec: RFC7159; urlPrefix: https://tools.ietf.org/html/rfc4627
type: dfn
text: JSON; url: section-2
text: JSON object; url: section-2.2
text: JSON array; url: section-2.3
text: JSON stringification; url: section-2
spec: html-comms; urlPrefix: https://html.spec.whatwg.org/multipage/comms.html
type: dfn
text: Server-sent events; url: server-sent-events
spec: whatwg-messaging; urlPrefix: https://html.spec.whatwg.org/multipage/web-messaging.html
type: dfn
text: channel messaging; url: channel-messaging
text: broadcast channels; url: broadcasting-to-other-browsing-contexts
spec: WebRTC; urlPrefix: https://www.w3.org/TR/webrtc/
type: dfn
text: WebRTC
spec: XHR; urlPrefix: https://xhr.spec.whatwg.org/
type: dfn
text: XMLHttpRequest
text: final MIME type; url: final-mime-type
text: author request headers; url: author-request-headers
type: attribute
text: responseType; url: dom-xmlhttprequest-responsetype
text: response; url: dom-xmlhttprequest-responsetype
type: interface
text: XMLHttpRequest; url: xmlhttprequest
type: enum
text: XMLHttpRequestResponseType; url: xmlhttprequestresponsetype
type: method
text: send(); url: the-send()-method
text: open(); url: the-open()-method
spec: FETCH; urlPrefix: https://fetch.spec.whatwg.org/
type: dfn
text: fetching
text: main fetch; url: main-fetch
text: request; url: concept-request
text: response; url: concept-response
text: body; url: concept-response-body
text: client; url: concept-request-client
text: type; url: concept-request-type
text: destination; url: concept-request-destination
text: header; url: concept-header
text: name; url: concept-header-name
text: value; url: concept-header-value
text: header list; url: concept-header-list
text: network error; url: concept-network-error
text: extracting a MIME type; url: concept-header-extract-mime-type
text: navigation request; url: navigation-request
spec: ENCODING; urlPrefix: https://encoding.spec.whatwg.org/
type: dfn
text: utf-8 decode; url: utf-8-decode
spec: WEBSTORAGE; urlPrefix: https://www.w3.org/TR/webstorage/
type: attribute
text: localStorage; url: the-localstorage-attribute
spec: RFC5234; urlPrefix: https://tools.ietf.org/html/rfc5234
type: dfn
text: ALPHA; url: appendix-B.1
text: DIGIT; url: appendix-B.1
text: WSP; url: appendix-B.1
text: VCHAR; url: appendix-B.1
spec: DOM-Parsing; urlPrefix: https://w3c.github.io/DOM-Parsing/
type: dfn
text: serialized; url: dfn-concept-fragment-serializing-algorithm
spec: WEBIDL2; urlPrefix: https://heycam.github.io/webidl/
type: interface
text: object; url: idl-object
text: DOMString; url: idl-DOMString
type: dfn
text: exposed; url: dfn-exposed
text: SecureContext; url: SecureContext
spec: REFERRER-POLICY; urlPrefix: https://w3c.github.io/webappsec-referrer-policy/
type: dfn
text: determine request's referrer algorithm; url: determine-requests-referrer
text: referrer policy; url: referrer-policy
spec: WEBSOCKETS; urlPrefix: https://www.w3.org/TR/websockets/
type: method
text: WebSocket(); url: dom-websocket
type: dfn
text: make disappear; url: make-disappear
</pre>
<!-- BIBLIOGRAPHY -->
<pre class="biblio">
{
"DCLabels": {
"authors": ["Deian Stefan", "Alejandro Russo", "David Mazieres", "John C. Mitchell"],
"title": "Disjunction Category Labels",
"href": "http://www.scs.stanford.edu/~deian/pubs/stefan:2011:dclabels.pdf",
"publisher": "Springer Berlin Heidelberg"
},
"COWL-OSDI": {
"authors": ["Deian Stefan", "Edward Z. Yang", "Petr Marchencko", "Alejandro Russo", "David Herman", "Brad Karp", "David Mazieres", "John C. Mitchell"],
"title": "Protecting Users by Confining JavaScript with COWL",
"href":"https://www.usenix.org/system/files/conference/osdi14/osdi14-paper-stefan.pdf",
"publisher": "USENIX"
},
"URL": {
"authors": [ "Anne van Kesteren", "Sam Ruby" ],
"title": "URL",
"href": "https://www.w3.org/TR/url",
"status": "WD",
"publisher": "W3C"
},
"WEBIDL2": {
"authors": [ "Cameron McCormack", "Boris Zbarsky" ],
"title": "Web IDL (Second Edition)",
"href": "https://heycam.github.io/webidl/",
"status": "ED",
"publisher": "W3C"
}
}
</pre>
<!--
████ ██ ██ ████████ ████████ ███████
██ ███ ██ ██ ██ ██ ██ ██
██ ████ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ████████ ██ ██
██ ██ ████ ██ ██ ██ ██ ██
██ ██ ███ ██ ██ ██ ██ ██
████ ██ ██ ██ ██ ██ ███████
-->
<section>
<h2 id="intro">Introduction</h2>
<em>This section is not normative.</em>
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 <em>mashup</em>). 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 <a>origin labels</a>. These
policies are enforced in a mandatory fashion, transitively, even
once code has access to the data. For example, with COWL, the
author of <code>https://example.com</code> can specify that a
password is confidential to <code>https://example.com</code> (and
thus should only be disclosed to <code>https://example.com</code>)
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 <a>origin</a> other than
<code>https://example.com</code>.
COWL enforces such policies by confining code at the
<a>context</a>-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., <a>iframes</a>).
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 <a>privileges</a>. For example, by default, a
page whose origin is <code>https://example.com</code> has the
privilege for <code>https://example.com</code>. This gives the page
the authority to arbitrarily disseminate data sensitive to
<code>https://example.com</code>; to be backwards-compatible,
COWL does not confine the page when reading data sensitive to
<code>https://example.com</code>. However, COWL allows the author
to run iframes with "weaker" <a>delegated privileges</a> (e.g., one
corresponding the current user at <code>https://example.com</code>)
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.
<section>
<h3 id="goals">Goals</h3>
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 <a><code>Access-Control-Allow-Origin</code></a> header and the
<code>targetOrigin</code> argument to
<a><code>postMessage()</code></a>) provide a way for restricting
which <a>origins</a> 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 <em>least privilege</em>
by restricting the origins the code can communicate with and thus
how it can disseminate sensitive data.
3. Authors should be able to <em>privilege separate</em>
applications by compartmentalizing them into separate contexts that
have <a>delegated privileges</a>.
</section>
<section>
<h3 id="examples">Use Cases/Examples</h3>
<h4 id="examples-checker">Confining untrusted third-party services</h4>
An author wishes to use a service, loaded in the form of an <a>cowl iframe</a>,
without trusting it (or its dependencies) to not leak her
sensitive data. To protect the data, the author associates a
confidentiality <a>label</a> with the data, specifying the origins
allowed to read the data. The author then shares the newly created
<a>labeled object</a> 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).
<div class="example">
The author of <code>https://example.com</code>
wishes to use a third-party password strength checker provided by
<code>https://untrusted.com</code>. To protect the
confidentiality of the password, the
<code>https://example.com</code> application can use COWL to
run the checker code in a <a>cowl iframe</a> and associate a
confidentiality policy, in the form of a <a>label</a>, with the password
before sending it to the untrusted service:
<pre><code>
// Create new policy using <a interface>Label</a>s that specifies that the password is sensitive
// to https://example.com and should only be disclosed to this origin:
var policy = new <a interface>Label</a>(window.location.origin);
// Associate the label with the password:
var labeledPassword = new <a interface>LabeledObject</a>(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.
</code></pre>
Once the checker inspects the label-<a>protected object</a>, i.e., the
password, COWL limits the iframe to communicating with origins that
preserve the password's confidentiality (in this case,
<code>https://example.com</code>). This policy is enforced mandatorily,
even if the <code>https://untrusted.com</code> 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
<code>https://untrusted.com</code>. 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.
</div>
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]].
<h4 id="examples-mashup">Sharing data with third-party mashups</h4>
A server operator wishes to provide third-party mashups access to user data.
In addition to using CORS response headers to restrict the <a>origins</a>
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
<a href="#response-header"><code>Sec-COWL</code></a> (described in
[[#response-header]]) whose value contains the sensitivity of the data in the
form of a serialized confidentiality <a>label</a>. In turn, COWL enforces
the label restrictions on the third-party code.
<div class="example">
The server operator of <code>https://provider.com</code> uses a
CORS response header to grant <code>https://mashup.com</code>
access to a resource. The operator also sets a COWL header to
specify that the resource is confidential to
<code>https://provider.com</code> and should not be disseminated
arbitrarily:
<pre><code>
<a>Access-Control-Allow-Origin</a>: https://mashup.com
<a href="#response-header">Sec-COWL</a>: <a>data-confidentiality</a> https://provider.com
</code></pre>
COWL only allows a <code>https://mashup.com</code> context to read
the sensitive response if the label restrictions of the response
are respected, i.e., if the code can only communicate with
<code>https://provider.com</code>.
Note, COWL only allows the code to inspect the response if the <a>context
labels</a>, 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 <a>labeled JSON response</a>. The <a
href="#mashup-example-xhr">mashup XHR example</a> shows how authors can
accomplish this.
</div>
<h4 id="examples-isolation">Content isolation via privilege separation</h4>
A server operator wishes to isolate content (e.g., of different
users) while serving it from a single physical <a>origin</a>. The
operator can leverage <a>privileges</a> 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 <a>context privilege</a> to a weaker, <a>delegated
privilege</a>. This ensures that the content are privilege
separated.
<div class="example">
Suppose <code>https://university.edu</code> 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
<a href="#response-header"><code>Sec-COWL</code></a>
(see [[#response-header]]) whose value contains
a serialized <a>delegated privilege</a>. For example, for any
content under <code>https://university.edu/~user1</code>, the
following header is set:
<pre><code>
<a href="#response-header">Sec-COWL</a>: <a>ctx-privilege</a> 'self' OR app:user1
</code></pre>
Having this privilege can be understood as having the authority of
<code>user1</code>'s part of the application's origin. COWL ensures that
the content of this page cannot interfere with the content of
<code>https://university.edu</code> or that of another user e.g.,
<code>user2</code>. For example, the content cannot modify
<code>https://university.edu</code> cookies or the DOM of another
<code>https://university.edu</code> page.
This <a>delegated privilege</a> also ensures that the
content cannot disseminate data sensitive to another user (e.g.,
<code>user2</code>) arbitrarily—without being confined,
it can only disseminate <code>user1</code>'s data on
<code>https://university.edu</code>.
Of course, this requires the server operator to label
sensitive data (e.g., when sending it to the user agent) appropriately
(e.g., <code>user2</code>'s data is labeled
<code><a>Label</a>("https://university.edu").or("app:user2")</code>).
The <a href="#university-example-js">sub-origin isolation in
JavaScript</a> example shows how this can be implemented using the
COWL JavaScript APIs.
</div>
<div class="note">
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.
</div>
<h4 id="examples-leastpriv">Running content with least-privileges</h4>
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 <a>dropping privileges</a>
(from the context's <a>default privilege</a>) and then loading the untrusted
library. In dropping privileges, the content (and untrusted library) loses
its implicit authority over the content's origin.
<div class="example">
The author of <code>https://example.com</code> can drop privileges
in JavaScript:
<pre><code>
// Drop privileges, by setting the <a>context privilege</a> to an <a>empty privilege</a>:
COWL.privilege = new <a>Privilege()</a>;
// Load untrusted library
</code></pre>
Or, by setting the content's initial privilege to the <a>empty
privilege</a> using
<a href="#response-header"><code>Sec-COWL</code></a> response header:
<pre><code>
<a href="#response-header">Sec-COWL</a>: <a>ctx-privilege</a> 'none'
</code></pre>
<div class="note">
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.
</div>
</div>
In some cases it is useful for a particular context to have the
privilege to disseminate certain categories of data. (The
<code>or</code> part of <a>labels</a> can be used to easily
categorize differently-sensitive data.) To this end, the author
should run the context with a <a>delegated privilege</a> instead of
the <a>empty privilege</a>. The above [[#examples-isolation]] shows
one such example.
</section>
<section>
<h3 id="security-considerations">Security Considerations</h3>
<h4 id="covert-channels">Information leakage via covert channels</h4>
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.
<h4 id="defense-in-depth">Defense in depth</h4>
COWL has been defined within the context of existing security mechanisms
(CSP, SRI, CORS, and iframe <code><a element-attr>sandbox</a></code>)
and SHOULD be used as an additional layer of defense. The goal of this
specification is not to replace existing discretionary access control
mechanisms.
</section>
<section>
<h3 id="privacy-considerations">Privacy Considerations</h3>
<h4 id="privacy-request-header">Encoding information in labels</h4>
This specification introduces the
<a href="#request-header"><code>Sec-COWL</code> HTTP request header</a> to
provide server operators with information about the context that made the
request (e.g., the <a>context privilege</a>). This header is sent in
accordance to the<a>referrer policy</a> [[REFERRER-POLICY]]. However,
since the request header may contain serialized <a>application-specific
principals</a>, 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.
<h4 id="privacy-protect">Using labels to enhance privacy</h4>
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, <a>labels</a>) to
prevent unwanted or accidental information leaks.
</section>
</section>
<!--
████████ ████████ ████████ ████ ██ ██ ████ ████████ ████ ███████ ██ ██ ██████
██ ██ ██ ██ ██ ███ ██ ██ ██ ██ ██ ██ ███ ██ ██ ██
██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ████ ██ ██
██ ██ ██████ ██████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██████
██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ████ ██
██ ██ ██ ██ ██ ██ ███ ██ ██ ██ ██ ██ ██ ███ ██ ██
████████ ████████ ██ ████ ██ ██ ████ ██ ████ ███████ ██ ██ ██████
-->
<section>
<h2 id="key-concepts">Key Concepts and Terminology</h2>
<h3 id="key-concepts-labels">Labels</h3>
1. An <dfn>origin label</dfn>, or more succinctly a
<dfn>label</dfn>, encodes either a confidentiality or integrity
security policy as conjunctive normal form (AND's and OR's)
formulae over <a>principals</a> (typically <a>origin</a>s.) Labels can
be associated with <a>contexts</a> or with <a>structurally clonable</a>
objects.
When associated with a <a>context</a>, the label restricts the
origins that the context can communicate with, as detailed in
[[#framework-context-labels]].
<div class="example">
The confidentiality label
<code><a interface>Label</a>("https://a.com").or("https://b.com")</code>,
when associated with a context,
restricts the context to sending data to
<code>https://a.com</code> or <code>https://b.com</code>, but
no other origins.
This context label reflects the fact the context may contain data
that is sensitive to either <code>https://a.com</code> or
<code>https://b.com</code>; it is thus only safe for it to
communicate <em>to</em> these origins.
Note, because the context can communicate data to either origin,
another context associated with the more restricting
label <code><a interface>Label</a>("https://a.com")</code> cannot
send it data. Doing so would allow for data confidential
to <code>https://a.com</code> to be leaked to <code>https://b.com</code>.
</div>
<div class="example">
The integrity label
<code><a interface>Label</a>("https://a.com").or("https://b.com")</code>,
when associated with a context, restricts the context to
receiving data from (a context or server) that is at least as
trustworthy as <code>https://a.com</code> or
<code>https://b.com</code>. This context label ensures that
the code running in the context can only be influenced by data
which either <code>https://a.com</code> or
<code>https://b.com</code> endorse.
</div>
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
<dfn>labeled objects</dfn>. [[#object-labels]] defines how
labels are associated with objects.
<div class="example">
Consider an <code>https://example.com</code> page that
receives a labeled object (e.g., via <a>postMessage()</a>)
with the following labels:
* Confidentiality:
<code><a interface>Label</a>("https://example.com")</code>.
This label indicates that the object is sensitive to
<code>https://example.com</code>.
* Integrity:
<code><a interface>Label</a>("https://a.com")</code>. This
label indicates that the object has been endorsed by
<code>https://a.com</code>. If
<code>https://example.com</code> received the message from an
intermediary <code>https://b.com</code> context, this label
reflects the fact that the object (produced by
<code>https://a.com</code>) was not tampered.
</div>
2. A <dfn>principal</dfn> is a string that represents an authoritative
entity. There are three kind of principals:
- An <dfn>origin principal</dfn> is the stringified <a>URL</a>
(scheme/host/port triple) of an origin.
- A <dfn>unique principal</dfn> is a stringified <a>globally unique
identifier</a> that contains the <code>"unique:"</code> string as a
prefix to a <a>UUID</a> (see <a>unique-principal-expression</a>).
- An <dfn>application-specific principal</dfn> is used by authors to
encode application-specific security entities (e.g., users, services);
they are strings prefixed by the <code>"app:"</code> string (see
<a>app-principal-expression</a>). Such principals, when used in
<a>labels</a>, typically only make sense if combined (e.g., as a
disjunction) with <a>origin principals</a> or <a>unique principals</a>.
3. Mathematically, a label is a <em>conjunctive normal form</em>
formula over principals [[DCLabels]].
A label is in <dfn>normal form</dfn> if reducing it according to
the <a>label normal form reduction</a> algorithm produces the
same value.
Two labels are <dfn>equivalent</dfn> if their <a>normal form</a>
values are mathematically equal.
A label <var>A</var> <dfn>subsumes</dfn> (or is more
<dfn>restricting</dfn> than) another label
<var>B</var> if the result of running the <a>label subsumption</a>
algorithm on the <a>normal form</a>s of <var>A</var> and
<var>B</var> returns <code>true</code>. Labels are partially
ordered according to this subsumes relation.
The <dfn>current confidentiality label</dfn> is the
confidentiality label associated with the current context.
[[#framework-context-labels]] specifies how labels are associated with
contexts.
The <dfn>current integrity label</dfn> is the
integrity label associated with the current context.
[[#framework-context-labels]] specifies how labels are associated with
contexts.
When reading a <a>labeled object</a>, a context gets
<dfn>tainted</dfn>, i.e., its <a>context labels</a> are updated by
invoking <a>context tainting</a> algorithm, to reflect that it
has read sensitive data, or data of potentially different
trustworthiness, and should be confined accordingly.
<h3 id="key-concepts-privileges">Privileges</h3>
1. A <dfn>privilege</dfn> is an unforgeable object that corresponds
to a <a>label</a>. 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 <a>internal privilege label</a>.
<div class="example">
Consider a context from <code>https://a.com</code> whose
<a>current confidentiality label</a> is <code><a
interface>Label</a>("https://a.com").and("https://b.com")</code>.
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 <code><a
interface>Label</a>("https://b.com")</code>, since doing
so could leak <code>https://a.com</code> data to
<code>https://b.com</code>. It similarly prevents the context
from communicating with <code>https://a.com</code>.
But, suppose that the context's <a>current privilege</a>
corresponds to <code><a interface>Label</a>("https://a.com")</code>
(afterall, the context originated from <code>https://a.com</code>).
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
<code>https://b.com</code>; the privilege confers it the right
to declassify <code>https://a.com</code> data to
<code>https://b.com</code>. Indeed, when taking this privilege
into consideration, the <a>effective confidentiality label</a>
of the context is <code><a interface>Label</a>("https://b.com")</code>.
Note, the privilege does not allow the context to bypass any
label restrictions. For example, it does not allow the context
to communicate with <code>https://a.com</code> since doing so
could leak <code>https://b.com</code> data.
<div class="note">
To be flexible, COWL uses the context privilege to remove
certain restrictions imposed by the <a>context label</a>.
To avoid accidentally leaking sensitive context data,
authors should use <a interface>LabeledObject</a>s.
</div>
</div>
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
<a>context</a> (or <a>labeled object</a>) as to allow it to
communicate with more trustworthy end-points (another context or
server).
<div class="example">
Consider an <code>https://a.com</code> context whose
<a>current integrity label</a> is
<code><a interface>Label</a>("https://a.com").or("https://b.com")</code>.
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 <a>current integrity
label</a> is
<code><a interface>Label</a>("https://a.com")</code>, since doing
so would potentially corrupt <code>https://a.com</code> data
(e.g., by allowing <code>https://b.com</code> to influence the
computation).
But, if the context's <a>current privilege</a> corresponds
to <code><a interface>Label</a>("https://a.com")</code>, 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
<code><a interface>Label</a>("https://a.com")</code>) since the
privilege confers it the right to endorse (or vouch for) its
context on behalf of <code>https://a.com</code>. Indeed, when
taking privileges into account, the <a>effective integrity
label</a> of the context is <code><a
interface>Label</a>("https://a.com")</code>.
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 <code><a
interface>Label</a>("https://b.com")</code>.
</div>
Note, <a>browsing contexts</a> have a <a>current privilege</a>
that, by default, corresponds to the origin of the context, as
described in [[#framework-context-labels]]. But, authors should set the <a>current
privilege</a> to a <a>delegated privilege</a> to follow
the principle of least privilege.
2. The <dfn>current privilege</dfn> is the privilege associated
with the current context. [[#framework-context-labels]] specifies how
privileges are associated with contexts.
3. The <dfn>effective confidentiality label</dfn> is the label
returned by the <a>label downgrade</a> algorithm when invoked
with the <a>current confidentiality label</a> and <a>current
privilege</a>.
4. The <dfn>effective integrity label</dfn> is the label
returned by the <a>label upgrade</a> algorithm when invoked
with the <a>current integrity label</a> and <a>current
privilege</a>.
5. Code can take <dfn>ownership</dfn> of a <a>privilege</a>
<var>priv</var> by setting the <a>current privilege</a> to the
privilege produced via the <a>combination</a> of the <a>current
privilege</a> and <var>priv</var>. In doing so, it is said
that the context <dfn>owns</dfn> the privilege.
</section>
<!--
████████ ████████ ███ ██ ██ ████████ ██ ██ ███████ ████████ ██ ██
██ ██ ██ ██ ██ ███ ███ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ████ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ████████ ██ ██ ██ ███ ██ ██████ ██ ██ ██ ██ ██ ████████ █████
██ ██ ██ █████████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ██ ██ ████████ ███ ███ ███████ ██ ██ ██ ██
-->
<section>
<h2 id="framework">Framework</h2>
<em>This sub-section is not normative.</em>
In a nut-shell, the COWL framework provides:
<dl>
<dt>Policy specification via <a>labels</a></dt>
<dd>
COWL provides a <a interface>Label</a> interface for specifying
confidentiality and integrity policies in terms of
<a>principals</a> (typically, <a>origins</a>). <a>Labels</a> can be
associated with data and content using the JavaScript <a
interface>LabeledObject</a> and <a interface>COWL</a> interfaces or the
<code>Sec-COWL</code> HTTP header field.
</dd>
<dt>Explicit authority via <a>privileges</a></dt>
<dd>
The COWL framework provides a JavaScript
<a interface>Privilege</a> interface for operating on and minting
new <a>privileges</a>. The <a interface>COWL</a> JavaScript
interface and <code>Sec-COWL</code> HTTP response header can be
used to explicitly control the authority of a context by setting
the <a>context privilege</a>.
</dd>
<dt>Confinement enforcement mechanism</dt>
<dd>
COWL extends <a>browsing contexts</a>, in particular <a>iframes</a>
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.
</dd>
</dl>
<section>
<h3 id="framework-labels">Labels</h3>
Each <a>label</a> is an immutable object represented by a
<a interface>Label</a> object, the interface of which is defined in
this section.
A <a interface>Label</a> MUST have an internal <dfn>label set</dfn>, which is
a non-empty set of <a>disjunction set</a>s.
A <dfn>disjunction set</dfn> is a set of <a>principals</a>.
A label is said to be an <dfn>empty label</dfn> if its <a>label
set</a> contains a single, empty <a>disjunction set</a>.
<pre class="idl">
[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;
};
</pre>
<h4 id="label-constructors">Constructors</h4>
<dl dfn-for="Label">
<dt><dfn constructor>Label()</dfn></dt>
<dd>
When invoking the <a>Label()</a> constructor, the user agent
MUST return a new <a>empty label</a>.
</dd>
<dt><dfn constructor>Label(DOMString principal)</dfn></dt>
<dd>
When invoking the <a>Label(principal)</a> constructor, the user agent
MUST use an algorithm equivalent to the following:
1. If the <a argument for="Label/Label(principal)">principal</a>
argument is not a <a>principal</a>, the constructor MUST throw a
<code>TypeError</code> exception [[!ECMA-262]] and
terminate this algorithm.
2. Else, it MUST return a new <a>Label</a> that contains a
<a>label set</a> of a single <a>disjunction set</a>, which
itself MUST contain the <a>principal</a> corresponding to the
<a argument for="Label/Label(principal)">principal</a> argument.
</dd>
</dl>
<h4 id="label-methods">Methods</h4>
<dl dfn-for="Label">
<dt><dfn method title="equals(other)">equals(Label other)</dfn></dt>
<dd>
The user agent MUST return <code>true</code> if the <a interface>Label</a> on
which the method has been called is <a>equivalent</a> to the
<a argument for="Label/equals(other)">other</a>
parameter; otherwise it MUST return <code>false</code>.
</dd>
<dt><dfn method title="subsumes(other, priv)">subsumes(Label other, optional Privilege priv)</dfn></dt>
<dd>
The user agent MUST use an algorithm equivalent to the
following:
1. Let <var>lab</var> be the <a>Label</a> on which the method
has been called.
2. If the <a argument for="Label/subsumes(other, priv)">priv</a> argument is
provided, let <var>lab</var> be
<code><var>lab</var>.and(priv.<a>asLabel()</a>)</code>.
3. Return <code>true</code> if <var>lab</var> <a>subsumes</a> the
<a argument for="Label/subsumes(other, priv)">other</a>
parameter and <code>false</code> otherwise.
</dd>
<dt><dfn method title="and(other)">and((Label or DOMString) other)</dfn></dt>
<dd>
The user agent MUST use an algorithm equivalent to the following:
1. Let <var>O</var> be the
<a argument for="Label/and(other)">other</a> argument.
1. If the type of <a argument for="Label/and(other)">other</a> is
<code>DOMString</code>, run the following sub-steps:
1. Set <var>O</var> to the result of invoking the
<a>Label(other)</a> constructor with <a argument
for="Label/and(other)">other</a> as an argument, if the
constructor did not raise an exception.
2. Else, re-throw the exception and terminate this algorithm.
2. Return a new <a>normal form</a> <a interface>Label</a>
that is <a>equivalent</a> to a label whose
<a>label set</a> contains the <a>disjunction sets</a> of
<var>O</var> and the <a interface>Label</a> on which
the method was invoked.
</dd>
<dt><dfn method title="or(other)">or((Label or DOMString) other)</dfn></dt>
<dd>
The user agent MUST use an algorithm equivalent to the following:
1. Let <var>O</var> be the
<a argument for="Label/and(other)">other</a> argument.
1. If the type of <a argument for="Label/_or(other)">other</a> is
<code>DOMString</code>, run the following sub-steps:
1. Set <var>O</var> to the result of invoking the
<a>Label(other)</a> constructor with <a argument
for="Label/_or(other)">other</a> as an argument, if the
constructor did not raise an exception.
2. Else, re-throw the exception and terminate this algorithm.
2. Return a new <a interface>Label</a>, in <a>normal form</a>,
which is <a>equivalent</a> to adding each element of each
<a>disjunction set</a> of <var>O</var>'s <a>label set</a> to
each <a>disjunction set</a> of the <a>label set</a> of the
<a interface>Label</a> on which the method was called.
</dd>
</dl>