Fossil SCM

More thorough explanation of <script nonce> in www/defcsp.md, and explained the reason why Fossil has no way of providing that nonce in most content types rather than link to the "XSS via check-in rights" forum post. This new presentation of that post's ideas is more detailed and includes discussion of the feature's interaction with the TH1 docs feature.

wyoung 2019-08-21 11:01 trunk
Commit 8d43bb8786772d5737012216aa58982865cfa749d35ba2325a4ccf114ac01a2c
2 files changed +79 -12 +2 -2
+79 -12
--- www/defcsp.md
+++ www/defcsp.md
@@ -89,22 +89,86 @@
8989
9090
### <a name="script"></a> script-src 'self' 'nonce-%s'
9191
9292
This policy means HTML `<script>` tags are only allowed to be emitted
9393
into the output HTML by Fossil C or TH1 code, because only code running
94
-in those contexts can correctly apply the random “nonce” attribute to
95
-the tag that matches the one declared in the CSP, which changes on each
96
-HTTP hit Fossil handles.
97
-
98
-This means the workarounds given above will not work for JavaScript. In
99
-effect, the only JavaScript that Fossil can serve is that which it
100
-directly provided, such as that for the CSS section of the skin and that
101
-behind the default [hamburger menu](./customskin.md#menu).
94
+in those contexts can insert the correct “nonce” tag attribute, matching
95
+the one declared in the CSP.¹ Since the nonce is a very large random
96
+number that changes on each HTTP hit Fossil handles, it is effectively
97
+unguessable, which prevents attackers from inserting `<script>` tags
98
+statically.
99
+
100
+This means the workarounds given above will not work for JavaScript.
101
+Under this policy, the only JavaScript that Fossil can serve is that
102
+which it directly provided.
103
+
104
+Users with the all-powerful Setup capability can insert arbitrary
105
+JavaScript by [defining a custom skin][cs], adding it to the skin’s
106
+“JavaScript” section, which has the random nonce automatically inserted
107
+by Fossil when it serves the page. This is how the JS backing the
108
+default skin’s [hamburger menu](./customskin.md#menu) works.
102109
103110
We’re so restrictive about how we treat JavaScript because it can lead
104
-to [difficult-to-avoid cross-site scripting attacks][xssci].
111
+to difficult-to-avoid scripting attacks. If we used the same CSP for
112
+`<script>` tags [as for `<style>` tags](#style), anyone with check-in
113
+rights on your repository could add a JavaScript file to your repository
114
+and then refer to it from other content added to the site. Since
115
+JavaScript code can access any data from any URI served under its same
116
+Internet domain, and many Fossil users host multiple Fossil repositories
117
+under a single Internet domain, such a CSP would only be safe if all of
118
+those repositories are trusted equally.
119
+
120
+Consider [the Chisel hosting service](http://chiselapp.com/), which
121
+offers free Fossil repository hosting to anyone on the Internet, all
122
+served under the same `http://chiselapp.com/user/$NAME/$REPO` URL
123
+scheme. Any one of those hundreds of repositories could trick you into
124
+visiting their repository home page, set to [an HTML-formatted embedded
125
+doc page][hfed] via Admin → Configuration → Index&nbsp;Page, with this
126
+content:
127
+
128
+ <script src="/doc/trunk/bad.js"></script>
129
+
130
+That script can then do anything allowed in JavaScript to *any other*
131
+Chisel repository your browser can access.The possibilities for mischief
132
+are *vast*. For just one example, if you have login cookies on four
133
+different Chisel repositories, your attacker could harvest the login
134
+cookies for all of them through this path if we allowed Fossil to serve
135
+JavaScript files under the same CSP policy as we do for CSS files.
136
+
137
+This is why the default configuration of Fossil has no way for [embedded
138
+docs][ed], [wiki articles][wiki], [tickets][tkt], [forum posts][fp], or
139
+[tech notes][tn] to automatically insert a nonce into the page content.
140
+This is all user-provided content, which could link to user-provided
141
+JavaScript via check-in rights, effectively giving all such users a
142
+capability that is usually reserved to the repository’s administrator.
143
+
144
+The default-disabled [TH1 documents feature][edtf] is the only known
145
+path around this restriction. If you are serving a Fossil repository
146
+that has any user you do not implicitly trust to a level that you would
147
+willingly run any JavaScript code they’ve provided, blind, you **must
148
+not** give the `--with-th1-docs` option when configuring Fossil, because
149
+that allows substitution of the [pre-defined `$nonce` TH1
150
+variable](./th1.md#nonce) into [HTML-formatted embedded docs][hfed]:
151
+
152
+ <script src="/doc/trunk/bad.js" nonce="$nonce"></script>
153
+
154
+Even with this feature enabled, you cannot put `<script>` tags into
155
+Fossil Wiki or Markdown-formatted content, because our HTML generators
156
+for those formats purposely strip or disable such tags in the output.
157
+Therefore, if you trust those users with check-in rights to provide
158
+JavaScript but not those allowed to file tickets, append to wiki
159
+articles, etc., you might justify enabling TH1 docs on your repository,
160
+since the only way to create or modify HTML-formatted embedded docs is
161
+through check-ins.
105162
163
+[ed]: ./embeddeddoc.wiki
164
+[edtf]: ./embeddeddoc.wiki#th1
165
+[fp]: ./forum.wiki
166
+[hfed]: ./embeddeddoc.wiki#html
167
+[tkt]: ./tickets.wiki
168
+[tn]: ./event.wiki
169
+[wiki]: ./wikitheory.wiki
106170
107171
108172
## <a name="override"></a>Replacing the Default CSP
109173
110174
If you wish to relax the default CSP’s restrictions or to tighten them
@@ -137,11 +201,11 @@
137201
138202
### <a name="header"></a>Custom Skin Header
139203
140204
Fossil only inserts a CSP into the HTML pages it generates when the
141205
[skin’s Header section](./customskin.md#headfoot) doesn’t contain a
142
-`<head>` tag. None of the stock skins include a `<head>` tag,¹ so if you
206
+`<head>` tag. None of the stock skins include a `<head>` tag,² so if you
143207
haven’t [created a custom skin][cs], you should be getting Fossil’s
144208
default CSP.
145209
146210
We say “should” because long-time Fossil users may be hanging onto a
147211
legacy behavior from before Fossil 2.5, when Fossil added this automatic
@@ -172,16 +236,19 @@
172236
------------
173237
174238
175239
**Asides and Digressions:**
176240
177
-1. The stock Bootstrap skin does actually include a `<head>` tag, but
241
+1. There is actually a third context that can correctly insert this
242
+ nonce attribute: [a CGI server extension](./serverext.wiki), by use of
243
+ the `FOSSIL_NONCE` variable sent to the CGI by Fossil.
244
+
245
+2. The stock Bootstrap skin does actually include a `<head>` tag, but
178246
from Fossil 2.7 through Fossil 2.9, it just repeated the same CSP
179247
text that Fossil’s C code inserts into the HTML header for all other
180248
stock skins. With Fossil 2.10, the stock Bootstrap skin uses
181249
`$default_csp` instead, so you can [override it as above](#th1).
182250
183251
184252
[cs]: ./customskin.md
185253
[csp]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
186254
[de]: https://dopiaza.org/tools/datauri/index.php
187
-[xssci]: https://fossil-scm.org/forum/forumpost/e7c386b21f
188255
--- www/defcsp.md
+++ www/defcsp.md
@@ -89,22 +89,86 @@
89
90 ### <a name="script"></a> script-src 'self' 'nonce-%s'
91
92 This policy means HTML `<script>` tags are only allowed to be emitted
93 into the output HTML by Fossil C or TH1 code, because only code running
94 in those contexts can correctly apply the random “nonce” attribute to
95 the tag that matches the one declared in the CSP, which changes on each
96 HTTP hit Fossil handles.
97
98 This means the workarounds given above will not work for JavaScript. In
99 effect, the only JavaScript that Fossil can serve is that which it
100 directly provided, such as that for the CSS section of the skin and that
101 behind the default [hamburger menu](./customskin.md#menu).
 
 
 
 
 
 
 
102
103 We’re so restrictive about how we treat JavaScript because it can lead
104 to [difficult-to-avoid cross-site scripting attacks][xssci].
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
 
 
 
 
 
 
 
106
107
108 ## <a name="override"></a>Replacing the Default CSP
109
110 If you wish to relax the default CSP’s restrictions or to tighten them
@@ -137,11 +201,11 @@
137
138 ### <a name="header"></a>Custom Skin Header
139
140 Fossil only inserts a CSP into the HTML pages it generates when the
141 [skin’s Header section](./customskin.md#headfoot) doesn’t contain a
142 `<head>` tag. None of the stock skins include a `<head>` tag,¹ so if you
143 haven’t [created a custom skin][cs], you should be getting Fossil’s
144 default CSP.
145
146 We say “should” because long-time Fossil users may be hanging onto a
147 legacy behavior from before Fossil 2.5, when Fossil added this automatic
@@ -172,16 +236,19 @@
172 ------------
173
174
175 **Asides and Digressions:**
176
177 1. The stock Bootstrap skin does actually include a `<head>` tag, but
 
 
 
 
178 from Fossil 2.7 through Fossil 2.9, it just repeated the same CSP
179 text that Fossil’s C code inserts into the HTML header for all other
180 stock skins. With Fossil 2.10, the stock Bootstrap skin uses
181 `$default_csp` instead, so you can [override it as above](#th1).
182
183
184 [cs]: ./customskin.md
185 [csp]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
186 [de]: https://dopiaza.org/tools/datauri/index.php
187 [xssci]: https://fossil-scm.org/forum/forumpost/e7c386b21f
188
--- www/defcsp.md
+++ www/defcsp.md
@@ -89,22 +89,86 @@
89
90 ### <a name="script"></a> script-src 'self' 'nonce-%s'
91
92 This policy means HTML `<script>` tags are only allowed to be emitted
93 into the output HTML by Fossil C or TH1 code, because only code running
94 in those contexts can insert the correct “nonce” tag attribute, matching
95 the one declared in the CSP.¹ Since the nonce is a very large random
96 number that changes on each HTTP hit Fossil handles, it is effectively
97 unguessable, which prevents attackers from inserting `<script>` tags
98 statically.
99
100 This means the workarounds given above will not work for JavaScript.
101 Under this policy, the only JavaScript that Fossil can serve is that
102 which it directly provided.
103
104 Users with the all-powerful Setup capability can insert arbitrary
105 JavaScript by [defining a custom skin][cs], adding it to the skin’s
106 “JavaScript” section, which has the random nonce automatically inserted
107 by Fossil when it serves the page. This is how the JS backing the
108 default skin’s [hamburger menu](./customskin.md#menu) works.
109
110 We’re so restrictive about how we treat JavaScript because it can lead
111 to difficult-to-avoid scripting attacks. If we used the same CSP for
112 `<script>` tags [as for `<style>` tags](#style), anyone with check-in
113 rights on your repository could add a JavaScript file to your repository
114 and then refer to it from other content added to the site. Since
115 JavaScript code can access any data from any URI served under its same
116 Internet domain, and many Fossil users host multiple Fossil repositories
117 under a single Internet domain, such a CSP would only be safe if all of
118 those repositories are trusted equally.
119
120 Consider [the Chisel hosting service](http://chiselapp.com/), which
121 offers free Fossil repository hosting to anyone on the Internet, all
122 served under the same `http://chiselapp.com/user/$NAME/$REPO` URL
123 scheme. Any one of those hundreds of repositories could trick you into
124 visiting their repository home page, set to [an HTML-formatted embedded
125 doc page][hfed] via Admin → Configuration → Index&nbsp;Page, with this
126 content:
127
128 <script src="/doc/trunk/bad.js"></script>
129
130 That script can then do anything allowed in JavaScript to *any other*
131 Chisel repository your browser can access.The possibilities for mischief
132 are *vast*. For just one example, if you have login cookies on four
133 different Chisel repositories, your attacker could harvest the login
134 cookies for all of them through this path if we allowed Fossil to serve
135 JavaScript files under the same CSP policy as we do for CSS files.
136
137 This is why the default configuration of Fossil has no way for [embedded
138 docs][ed], [wiki articles][wiki], [tickets][tkt], [forum posts][fp], or
139 [tech notes][tn] to automatically insert a nonce into the page content.
140 This is all user-provided content, which could link to user-provided
141 JavaScript via check-in rights, effectively giving all such users a
142 capability that is usually reserved to the repository’s administrator.
143
144 The default-disabled [TH1 documents feature][edtf] is the only known
145 path around this restriction. If you are serving a Fossil repository
146 that has any user you do not implicitly trust to a level that you would
147 willingly run any JavaScript code they’ve provided, blind, you **must
148 not** give the `--with-th1-docs` option when configuring Fossil, because
149 that allows substitution of the [pre-defined `$nonce` TH1
150 variable](./th1.md#nonce) into [HTML-formatted embedded docs][hfed]:
151
152 <script src="/doc/trunk/bad.js" nonce="$nonce"></script>
153
154 Even with this feature enabled, you cannot put `<script>` tags into
155 Fossil Wiki or Markdown-formatted content, because our HTML generators
156 for those formats purposely strip or disable such tags in the output.
157 Therefore, if you trust those users with check-in rights to provide
158 JavaScript but not those allowed to file tickets, append to wiki
159 articles, etc., you might justify enabling TH1 docs on your repository,
160 since the only way to create or modify HTML-formatted embedded docs is
161 through check-ins.
162
163 [ed]: ./embeddeddoc.wiki
164 [edtf]: ./embeddeddoc.wiki#th1
165 [fp]: ./forum.wiki
166 [hfed]: ./embeddeddoc.wiki#html
167 [tkt]: ./tickets.wiki
168 [tn]: ./event.wiki
169 [wiki]: ./wikitheory.wiki
170
171
172 ## <a name="override"></a>Replacing the Default CSP
173
174 If you wish to relax the default CSP’s restrictions or to tighten them
@@ -137,11 +201,11 @@
201
202 ### <a name="header"></a>Custom Skin Header
203
204 Fossil only inserts a CSP into the HTML pages it generates when the
205 [skin’s Header section](./customskin.md#headfoot) doesn’t contain a
206 `<head>` tag. None of the stock skins include a `<head>` tag,² so if you
207 haven’t [created a custom skin][cs], you should be getting Fossil’s
208 default CSP.
209
210 We say “should” because long-time Fossil users may be hanging onto a
211 legacy behavior from before Fossil 2.5, when Fossil added this automatic
@@ -172,16 +236,19 @@
236 ------------
237
238
239 **Asides and Digressions:**
240
241 1. There is actually a third context that can correctly insert this
242 nonce attribute: [a CGI server extension](./serverext.wiki), by use of
243 the `FOSSIL_NONCE` variable sent to the CGI by Fossil.
244
245 2. The stock Bootstrap skin does actually include a `<head>` tag, but
246 from Fossil 2.7 through Fossil 2.9, it just repeated the same CSP
247 text that Fossil’s C code inserts into the HTML header for all other
248 stock skins. With Fossil 2.10, the stock Bootstrap skin uses
249 `$default_csp` instead, so you can [override it as above](#th1).
250
251
252 [cs]: ./customskin.md
253 [csp]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
254 [de]: https://dopiaza.org/tools/datauri/index.php
 
255
--- www/embeddeddoc.wiki
+++ www/embeddeddoc.wiki
@@ -80,11 +80,11 @@
8080
Wiki, markdown, and plain text documentation files
8181
are rendered with the standard fossil header and footer added.
8282
Most other mimetypes are delivered directly to the requesting
8383
web browser without interpretation, additions, or changes.
8484
85
-Files with the mimetype "text/html" (the .html or .htm suffix) are
85
+<a name="html"></a>Files with the mimetype "text/html" (the .html or .htm suffix) are
8686
usually rendered directly to the browser without interpretation.
8787
However, if the file begins with a &lt;div&gt; element like this:
8888
8989
<b>&lt;div class='fossil-doc' data-title='<i>Title Text</i>'&gt;</b>
9090
@@ -131,11 +131,11 @@
131131
As you can see, this happens for all source document types that end up
132132
rendering as HTML, not just source documents in the HTML
133133
<tt>fossil-doc</tt> format described at the end of the prior section.
134134
135135
136
-<h3>2. TH1 Documents</h3>
136
+<h3 id="th1">2. TH1 Documents</h3>
137137
138138
Fossil will substitute the value of [./th1.md | TH1 expressions] within
139139
<tt>{</tt> curly braces <tt>}</tt> into the output HTML if you have
140140
configured it with the <tt>--with-th1-docs</tt> option, which is
141141
disabled by default.
142142
--- www/embeddeddoc.wiki
+++ www/embeddeddoc.wiki
@@ -80,11 +80,11 @@
80 Wiki, markdown, and plain text documentation files
81 are rendered with the standard fossil header and footer added.
82 Most other mimetypes are delivered directly to the requesting
83 web browser without interpretation, additions, or changes.
84
85 Files with the mimetype "text/html" (the .html or .htm suffix) are
86 usually rendered directly to the browser without interpretation.
87 However, if the file begins with a &lt;div&gt; element like this:
88
89 <b>&lt;div class='fossil-doc' data-title='<i>Title Text</i>'&gt;</b>
90
@@ -131,11 +131,11 @@
131 As you can see, this happens for all source document types that end up
132 rendering as HTML, not just source documents in the HTML
133 <tt>fossil-doc</tt> format described at the end of the prior section.
134
135
136 <h3>2. TH1 Documents</h3>
137
138 Fossil will substitute the value of [./th1.md | TH1 expressions] within
139 <tt>{</tt> curly braces <tt>}</tt> into the output HTML if you have
140 configured it with the <tt>--with-th1-docs</tt> option, which is
141 disabled by default.
142
--- www/embeddeddoc.wiki
+++ www/embeddeddoc.wiki
@@ -80,11 +80,11 @@
80 Wiki, markdown, and plain text documentation files
81 are rendered with the standard fossil header and footer added.
82 Most other mimetypes are delivered directly to the requesting
83 web browser without interpretation, additions, or changes.
84
85 <a name="html"></a>Files with the mimetype "text/html" (the .html or .htm suffix) are
86 usually rendered directly to the browser without interpretation.
87 However, if the file begins with a &lt;div&gt; element like this:
88
89 <b>&lt;div class='fossil-doc' data-title='<i>Title Text</i>'&gt;</b>
90
@@ -131,11 +131,11 @@
131 As you can see, this happens for all source document types that end up
132 rendering as HTML, not just source documents in the HTML
133 <tt>fossil-doc</tt> format described at the end of the prior section.
134
135
136 <h3 id="th1">2. TH1 Documents</h3>
137
138 Fossil will substitute the value of [./th1.md | TH1 expressions] within
139 <tt>{</tt> curly braces <tt>}</tt> into the output HTML if you have
140 configured it with the <tt>--with-th1-docs</tt> option, which is
141 disabled by default.
142

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button