|
4e6d36d…
|
wyoung
|
1 |
# The Default Content Security Policy (CSP) |
|
4e6d36d…
|
wyoung
|
2 |
|
|
1c4df5b…
|
wyoung
|
3 |
When Fossil’s web interface generates an HTML page, it normally includes |
|
025a007…
|
drh
|
4 |
a [Content Security Policy][csp] (CSP) in the `<head>`. The CSP specifies |
|
025a007…
|
drh
|
5 |
allowed sources for external resources such as images, |
|
3fec387…
|
drh
|
6 |
CSS, javascript, and so forth. |
|
025a007…
|
drh
|
7 |
The purpose of CSP is to provide an extra layer of protection against |
|
025a007…
|
drh
|
8 |
[cross-site scripting][xss] (XSS) and code injection |
|
025a007…
|
drh
|
9 |
attacks. Compatible web browsers will not use external resources unless |
|
025a007…
|
drh
|
10 |
they are specifically allowed by the CSP, which dramatically reduces |
|
025a007…
|
drh
|
11 |
the attack surface of the application. |
|
025a007…
|
drh
|
12 |
|
|
025a007…
|
drh
|
13 |
Fossil does not rely on CSP for security. |
|
3fec387…
|
drh
|
14 |
A Fossil server should be secure from attack even without CSP. |
|
025a007…
|
drh
|
15 |
Fossil includes built-in server-side content filtering logic. |
|
025a007…
|
drh
|
16 |
For example, Fossil purposely breaks `<script>` tags when it finds |
|
025a007…
|
drh
|
17 |
them in Markdown and Fossil Wiki documents. And the Fossil build |
|
025a007…
|
drh
|
18 |
process scans the source code for potential injection vulnerabilities |
|
025a007…
|
drh
|
19 |
and refuses to compile if any problems are found. |
|
025a007…
|
drh
|
20 |
However, CSP provides an additional layer of defense against undetected |
|
025a007…
|
drh
|
21 |
bugs that might lead to a vulnerability. |
|
366b23a…
|
wyoung
|
22 |
|
|
366b23a…
|
wyoung
|
23 |
## The Default Restrictions |
|
366b23a…
|
wyoung
|
24 |
|
|
025a007…
|
drh
|
25 |
The default CSP used by Fossil is as follows: |
|
23fcd76…
|
wyoung
|
26 |
|
|
025a007…
|
drh
|
27 |
<pre> |
|
8a1ba49…
|
wyoung
|
28 |
default-src 'self' data:; |
|
8a1ba49…
|
wyoung
|
29 |
script-src 'self' 'nonce-$nonce'; |
|
8a1ba49…
|
wyoung
|
30 |
style-src 'self' 'unsafe-inline'; |
|
8a1ba49…
|
wyoung
|
31 |
img-src * data:; |
|
025a007…
|
drh
|
32 |
</pre> |
|
23fcd76…
|
wyoung
|
33 |
|
|
025a007…
|
drh
|
34 |
The default is recommended for most installations. However, |
|
9ce4dd0…
|
mgagnon
|
35 |
the site administrators can overwrite this default CSP using the |
|
c64f28d…
|
drh
|
36 |
[default-csp setting](/help/default-csp). For example, |
|
025a007…
|
drh
|
37 |
CSP restrictions can be completely disabled by setting the default-csp to: |
|
025a007…
|
drh
|
38 |
|
|
8a1ba49…
|
wyoung
|
39 |
default-src *; |
|
025a007…
|
drh
|
40 |
|
|
025a007…
|
drh
|
41 |
The following sections detail the maining of the default CSP setting. |
|
025a007…
|
drh
|
42 |
|
|
93cee1f…
|
wyoung
|
43 |
### <a id="base"></a> default-src 'self' data: |
|
23fcd76…
|
wyoung
|
44 |
|
|
23fcd76…
|
wyoung
|
45 |
This policy means mixed-origin content isn’t allowed, so you can’t refer |
|
23fcd76…
|
wyoung
|
46 |
to resources on other web domains. Browsers will ignore a link like the |
|
23fcd76…
|
wyoung
|
47 |
one in the following Markdown under our default CSP: |
|
23fcd76…
|
wyoung
|
48 |
|
|
8a1ba49…
|
wyoung
|
49 |
 |
|
23fcd76…
|
wyoung
|
50 |
|
|
23fcd76…
|
wyoung
|
51 |
If you look in the browser’s developer console, you should see a CSP |
|
23fcd76…
|
wyoung
|
52 |
error when attempting to render such a page. |
|
23fcd76…
|
wyoung
|
53 |
|
|
e73901f…
|
wyoung
|
54 |
The default policy does allow inline `data:` URIs, which means you could |
|
4e6d36d…
|
wyoung
|
55 |
[data-encode][de] your image content and put it inline within the |
|
4e6d36d…
|
wyoung
|
56 |
document: |
|
4e6d36d…
|
wyoung
|
57 |
|
|
8a1ba49…
|
wyoung
|
58 |
 |
|
4e6d36d…
|
wyoung
|
59 |
|
|
4e6d36d…
|
wyoung
|
60 |
That method is best used for fairly small resources. Large `data:` URIs |
|
23fcd76…
|
wyoung
|
61 |
are hard to read and edit. There are secondary problems as well: if you |
|
23fcd76…
|
wyoung
|
62 |
put a large image into a Fossil forum post this way, anyone subscribed |
|
23fcd76…
|
wyoung
|
63 |
to email alerts will get a copy of the raw URI text, which can amount to |
|
23fcd76…
|
wyoung
|
64 |
pages and pages of [ugly Base64-encoded text][b64]. |
|
23fcd76…
|
wyoung
|
65 |
|
|
58883ec…
|
wyoung
|
66 |
For inline images within [embedded documentation][ed], it suffices to |
|
58883ec…
|
wyoung
|
67 |
store the referred-to files in the repo and then refer to them using |
|
58883ec…
|
wyoung
|
68 |
repo-relative URLs: |
|
58883ec…
|
wyoung
|
69 |
|
|
8a1ba49…
|
wyoung
|
70 |
 |
|
58883ec…
|
wyoung
|
71 |
|
|
58883ec…
|
wyoung
|
72 |
This avoids bloating the doc text with `data:` URI blobs: |
|
58883ec…
|
wyoung
|
73 |
|
|
58883ec…
|
wyoung
|
74 |
There are many other cases, [covered below](#serving). |
|
23fcd76…
|
wyoung
|
75 |
|
|
23fcd76…
|
wyoung
|
76 |
[b64]: https://en.wikipedia.org/wiki/Base64 |
|
23fcd76…
|
wyoung
|
77 |
[svr]: ./server/ |
|
23fcd76…
|
wyoung
|
78 |
|
|
23fcd76…
|
wyoung
|
79 |
|
|
93cee1f…
|
wyoung
|
80 |
### <a id="img"></a> img-src * data: |
|
ab029e4…
|
wyoung
|
81 |
|
|
ad47a44…
|
wyoung
|
82 |
It was not always thus, but after careful consideration, we’ve chosen to |
|
ad47a44…
|
wyoung
|
83 |
leave the source of inline images unrestricted by default in Fossil. |
|
ad47a44…
|
wyoung
|
84 |
This allows you to pull them in from remote systems, to pull them from |
|
ad47a44…
|
wyoung
|
85 |
within the Fossil repository itself, or to use `data:` URIs. |
|
ab029e4…
|
wyoung
|
86 |
|
|
ab029e4…
|
wyoung
|
87 |
If you are certain all images come from only within the repository, you |
|
ab029e4…
|
wyoung
|
88 |
can close off certain risks — tracking pixels, broken image format |
|
ab029e4…
|
wyoung
|
89 |
decoders, system dialog box spoofing, etc. — by changing this to |
|
ab029e4…
|
wyoung
|
90 |
“`img-src 'self'`” possibly followed by “`data:`” if you will also use |
|
ab029e4…
|
wyoung
|
91 |
`data:` URIs. |
|
ab029e4…
|
wyoung
|
92 |
|
|
ab029e4…
|
wyoung
|
93 |
|
|
93cee1f…
|
wyoung
|
94 |
### <a id="style"></a> style-src 'self' 'unsafe-inline' |
|
092eeeb…
|
wyoung
|
95 |
|
|
092eeeb…
|
wyoung
|
96 |
This policy allows CSS information to come from separate files hosted |
|
e73901f…
|
wyoung
|
97 |
under the Fossil repo server’s Internet domain. It also allows inline CSS |
|
e73901f…
|
wyoung
|
98 |
`<style>` tags within the document text. |
|
092eeeb…
|
wyoung
|
99 |
|
|
baecb63…
|
drh
|
100 |
The `'unsafe-inline'` declaration allows CSS within individual HTML |
|
092eeeb…
|
wyoung
|
101 |
elements: |
|
092eeeb…
|
wyoung
|
102 |
|
|
8a1ba49…
|
wyoung
|
103 |
<p style="margin-left: 4em">Indented text.</p> |
|
baecb63…
|
drh
|
104 |
|
|
baecb63…
|
drh
|
105 |
As the "`unsafe-`" prefix on the name implies, the `'unsafe-inline'` |
|
baecb63…
|
drh
|
106 |
feature is suboptimal for security. However, there are |
|
baecb63…
|
drh
|
107 |
a few places in the Fossil-generated HTML that benefit from this |
|
baecb63…
|
drh
|
108 |
flexibility and the work-arounds are verbose and difficult to maintain. |
|
e755561…
|
danield
|
109 |
Furthermore, the harm that can be done with style injections is far |
|
baecb63…
|
drh
|
110 |
less than the harm possible with injected javascript. And so the |
|
baecb63…
|
drh
|
111 |
`'unsafe-inline'` compromise is accepted for now, though it might |
|
baecb63…
|
drh
|
112 |
go away in some future release of Fossil. |
|
baecb63…
|
drh
|
113 |
|
|
ab029e4…
|
wyoung
|
114 |
|
|
93cee1f…
|
wyoung
|
115 |
### <a id="script"></a> script-src 'self' 'nonce-%s' |
|
91377ae…
|
wyoung
|
116 |
|
|
91377ae…
|
wyoung
|
117 |
This policy disables in-line JavaScript and only allows `<script>` |
|
91377ae…
|
wyoung
|
118 |
elements if the `<script>` includes a `nonce` attribute that matches the |
|
91377ae…
|
wyoung
|
119 |
one declared by the CSP. That nonce is a large random number, unique for |
|
91377ae…
|
wyoung
|
120 |
each HTTP page generated by Fossil, so an attacker cannot guess the |
|
91377ae…
|
wyoung
|
121 |
value, so the browser will ignore an attacker’s injected JavaScript. |
|
91377ae…
|
wyoung
|
122 |
|
|
91377ae…
|
wyoung
|
123 |
That nonce can only come from one of three sources, all of which should |
|
91377ae…
|
wyoung
|
124 |
be protected at the system administration level on the Fossil server: |
|
91377ae…
|
wyoung
|
125 |
|
|
91377ae…
|
wyoung
|
126 |
* **Fossil server C code:** All code paths in Fossil that emit |
|
91377ae…
|
wyoung
|
127 |
`<script>` elements include the `nonce` attribute. There are several |
|
91377ae…
|
wyoung
|
128 |
cases, such as the “JavaScript” section of a [custom skin][cs]. |
|
91377ae…
|
wyoung
|
129 |
That text is currently inserted into each HTML page generated by |
|
91377ae…
|
wyoung
|
130 |
Fossil,¹ which means it needs to include a `nonce` attribute to |
|
91377ae…
|
wyoung
|
131 |
allow it to run under this default CSP. We consider JavaScript |
|
91377ae…
|
wyoung
|
132 |
emitted via these paths to be safe because it’s audited by the |
|
91377ae…
|
wyoung
|
133 |
Fossil developers. We assume that you got your Fossil server’s code |
|
91377ae…
|
wyoung
|
134 |
from a trustworthy source and that an attacker cannot replace your |
|
91377ae…
|
wyoung
|
135 |
Fossil server binary. |
|
91377ae…
|
wyoung
|
136 |
|
|
58883ec…
|
wyoung
|
137 |
* **TH1 code:** The Fossil TH1 interpreter pre-defines the |
|
58883ec…
|
wyoung
|
138 |
[`$nonce` variable](./th1.md#nonce) for use in [custom skins][cs]. For |
|
91377ae…
|
wyoung
|
139 |
example, some of the stock skins that ship with Fossil include a |
|
91377ae…
|
wyoung
|
140 |
wall clock feature up in the corner that updates once a minute. |
|
91377ae…
|
wyoung
|
141 |
These paths are safe in the default Fossil configuration because |
|
91377ae…
|
wyoung
|
142 |
only the [all-powerful Setup user][su] can write TH1 code that |
|
91377ae…
|
wyoung
|
143 |
executes in the server’s running context. |
|
91377ae…
|
wyoung
|
144 |
|
|
91377ae…
|
wyoung
|
145 |
There is, however, [a default-disabled path](#xss) to beware of, |
|
91377ae…
|
wyoung
|
146 |
covered in the next section. |
|
91377ae…
|
wyoung
|
147 |
|
|
91377ae…
|
wyoung
|
148 |
* **[CGI server extensions][ext]:** Fossil exports the nonce to the |
|
91377ae…
|
wyoung
|
149 |
CGI in the `FOSSIL_NONCE` environment variable, which it can then |
|
91377ae…
|
wyoung
|
150 |
use in `<script>` elements it generates. Because these extensions |
|
91377ae…
|
wyoung
|
151 |
can only be installed by the Fossil server’s system administrator, |
|
91377ae…
|
wyoung
|
152 |
this path is also considered safe. |
|
91377ae…
|
wyoung
|
153 |
|
|
58883ec…
|
wyoung
|
154 |
[ext]: ./serverext.wiki |
|
779ddef…
|
wyoung
|
155 |
[su]: ./caps/admin-v-setup.md#apsu |
|
91377ae…
|
wyoung
|
156 |
|
|
91377ae…
|
wyoung
|
157 |
|
|
93cee1f…
|
wyoung
|
158 |
#### <a id="xss"></a>Cross-Site Scripting via Ordinary User Capabilities |
|
4e6d36d…
|
wyoung
|
159 |
|
|
4e6d36d…
|
wyoung
|
160 |
We’re so restrictive about how we treat JavaScript because it can lead |
|
8d43bb8…
|
wyoung
|
161 |
to difficult-to-avoid scripting attacks. If we used the same CSP for |
|
8d43bb8…
|
wyoung
|
162 |
`<script>` tags [as for `<style>` tags](#style), anyone with check-in |
|
8d43bb8…
|
wyoung
|
163 |
rights on your repository could add a JavaScript file to your repository |
|
8d43bb8…
|
wyoung
|
164 |
and then refer to it from other content added to the site. Since |
|
8d43bb8…
|
wyoung
|
165 |
JavaScript code can access any data from any URI served under its same |
|
8d43bb8…
|
wyoung
|
166 |
Internet domain, and many Fossil users host multiple Fossil repositories |
|
8d43bb8…
|
wyoung
|
167 |
under a single Internet domain, such a CSP would only be safe if all of |
|
8d43bb8…
|
wyoung
|
168 |
those repositories are trusted equally. |
|
8d43bb8…
|
wyoung
|
169 |
|
|
8d43bb8…
|
wyoung
|
170 |
Consider [the Chisel hosting service](http://chiselapp.com/), which |
|
8d43bb8…
|
wyoung
|
171 |
offers free Fossil repository hosting to anyone on the Internet, all |
|
8d43bb8…
|
wyoung
|
172 |
served under the same `http://chiselapp.com/user/$NAME/$REPO` URL |
|
8d43bb8…
|
wyoung
|
173 |
scheme. Any one of those hundreds of repositories could trick you into |
|
8d43bb8…
|
wyoung
|
174 |
visiting their repository home page, set to [an HTML-formatted embedded |
|
8d43bb8…
|
wyoung
|
175 |
doc page][hfed] via Admin → Configuration → Index Page, with this |
|
8d43bb8…
|
wyoung
|
176 |
content: |
|
8d43bb8…
|
wyoung
|
177 |
|
|
8a1ba49…
|
wyoung
|
178 |
<script src="/doc/trunk/bad.js"></script> |
|
8d43bb8…
|
wyoung
|
179 |
|
|
8d43bb8…
|
wyoung
|
180 |
That script can then do anything allowed in JavaScript to *any other* |
|
e755561…
|
danield
|
181 |
Chisel repository your browser can access. The possibilities for mischief |
|
8d43bb8…
|
wyoung
|
182 |
are *vast*. For just one example, if you have login cookies on four |
|
8d43bb8…
|
wyoung
|
183 |
different Chisel repositories, your attacker could harvest the login |
|
8d43bb8…
|
wyoung
|
184 |
cookies for all of them through this path if we allowed Fossil to serve |
|
8d43bb8…
|
wyoung
|
185 |
JavaScript files under the same CSP policy as we do for CSS files. |
|
8d43bb8…
|
wyoung
|
186 |
|
|
8d43bb8…
|
wyoung
|
187 |
This is why the default configuration of Fossil has no way for [embedded |
|
8d43bb8…
|
wyoung
|
188 |
docs][ed], [wiki articles][wiki], [tickets][tkt], [forum posts][fp], or |
|
8d43bb8…
|
wyoung
|
189 |
[tech notes][tn] to automatically insert a nonce into the page content. |
|
8d43bb8…
|
wyoung
|
190 |
This is all user-provided content, which could link to user-provided |
|
8d43bb8…
|
wyoung
|
191 |
JavaScript via check-in rights, effectively giving all such users a |
|
8d43bb8…
|
wyoung
|
192 |
capability that is usually reserved to the repository’s administrator. |
|
8d43bb8…
|
wyoung
|
193 |
|
|
8d43bb8…
|
wyoung
|
194 |
The default-disabled [TH1 documents feature][edtf] is the only known |
|
8d43bb8…
|
wyoung
|
195 |
path around this restriction. If you are serving a Fossil repository |
|
8d43bb8…
|
wyoung
|
196 |
that has any user you do not implicitly trust to a level that you would |
|
8d43bb8…
|
wyoung
|
197 |
willingly run any JavaScript code they’ve provided, blind, you **must |
|
8d43bb8…
|
wyoung
|
198 |
not** give the `--with-th1-docs` option when configuring Fossil, because |
|
8d43bb8…
|
wyoung
|
199 |
that allows substitution of the [pre-defined `$nonce` TH1 |
|
8d43bb8…
|
wyoung
|
200 |
variable](./th1.md#nonce) into [HTML-formatted embedded docs][hfed]: |
|
8d43bb8…
|
wyoung
|
201 |
|
|
8a1ba49…
|
wyoung
|
202 |
<script src="/doc/trunk/bad.js" nonce="$nonce"></script> |
|
8d43bb8…
|
wyoung
|
203 |
|
|
8d43bb8…
|
wyoung
|
204 |
Even with this feature enabled, you cannot put `<script>` tags into |
|
8d43bb8…
|
wyoung
|
205 |
Fossil Wiki or Markdown-formatted content, because our HTML generators |
|
8d43bb8…
|
wyoung
|
206 |
for those formats purposely strip or disable such tags in the output. |
|
8d43bb8…
|
wyoung
|
207 |
Therefore, if you trust those users with check-in rights to provide |
|
8d43bb8…
|
wyoung
|
208 |
JavaScript but not those allowed to file tickets, append to wiki |
|
8d43bb8…
|
wyoung
|
209 |
articles, etc., you might justify enabling TH1 docs on your repository, |
|
8d43bb8…
|
wyoung
|
210 |
since the only way to create or modify HTML-formatted embedded docs is |
|
8d43bb8…
|
wyoung
|
211 |
through check-ins. |
|
8d43bb8…
|
wyoung
|
212 |
|
|
8d43bb8…
|
wyoung
|
213 |
[ed]: ./embeddeddoc.wiki |
|
8d43bb8…
|
wyoung
|
214 |
[edtf]: ./embeddeddoc.wiki#th1 |
|
8d43bb8…
|
wyoung
|
215 |
[hfed]: ./embeddeddoc.wiki#html |
|
58883ec…
|
wyoung
|
216 |
|
|
58883ec…
|
wyoung
|
217 |
|
|
93cee1f…
|
wyoung
|
218 |
## <a id="serving"></a>Serving Files Within the Limits |
|
58883ec…
|
wyoung
|
219 |
|
|
58883ec…
|
wyoung
|
220 |
There are several ways to serve files within the above restrictions, |
|
58883ec…
|
wyoung
|
221 |
avoiding the need to [override the default CSP](#override). In |
|
58883ec…
|
wyoung
|
222 |
decreasing order of simplicity and preference: |
|
58883ec…
|
wyoung
|
223 |
|
|
58883ec…
|
wyoung
|
224 |
1. Within [embedded documentation][ed] (only!) you can refer to files |
|
58883ec…
|
wyoung
|
225 |
stored in the repo using document-relative file URLs: |
|
58883ec…
|
wyoung
|
226 |
|
|
58883ec…
|
wyoung
|
227 |
 |
|
58883ec…
|
wyoung
|
228 |
|
|
58883ec…
|
wyoung
|
229 |
2. Relative file URLs don’t work from [wiki articles][wiki], |
|
58883ec…
|
wyoung
|
230 |
[tickets][tkt], [forum posts][fp], or [tech notes][tn], but you can |
|
58883ec…
|
wyoung
|
231 |
still refer to them inside the repo with [`/doc`][du] or |
|
58883ec…
|
wyoung
|
232 |
[`/raw`][ru] URLs: |
|
58883ec…
|
wyoung
|
233 |
|
|
58883ec…
|
wyoung
|
234 |
 |
|
58883ec…
|
wyoung
|
235 |
<img src="/raw/logo.png" style="float: right; margin-left: 2em"> |
|
58883ec…
|
wyoung
|
236 |
|
|
58883ec…
|
wyoung
|
237 |
3. Store the files as [unversioned content][uv], referred to using |
|
58883ec…
|
wyoung
|
238 |
[`/uv`][uu] URLs instead: |
|
58883ec…
|
wyoung
|
239 |
|
|
58883ec…
|
wyoung
|
240 |
 |
|
58883ec…
|
wyoung
|
241 |
|
|
58883ec…
|
wyoung
|
242 |
4. Use the [optional CGI server extensions feature](./serverext.wiki) |
|
58883ec…
|
wyoung
|
243 |
to serve such content via `/ext` URLs. |
|
58883ec…
|
wyoung
|
244 |
|
|
58883ec…
|
wyoung
|
245 |
5. Put Fossil behind a [front-end proxy server][svr] as a virtual |
|
58883ec…
|
wyoung
|
246 |
subdirectory within the site, so that our default CSP’s “self” rules |
|
58883ec…
|
wyoung
|
247 |
match static file routes on that same site. For instance, your repo |
|
e755561…
|
danield
|
248 |
might be at `https://example.com/code`, allowing documents in that |
|
58883ec…
|
wyoung
|
249 |
repo to refer to: |
|
58883ec…
|
wyoung
|
250 |
|
|
58883ec…
|
wyoung
|
251 |
* images as `/image/foo.png` |
|
58883ec…
|
wyoung
|
252 |
* JavaScript files as `/js/bar.js` |
|
58883ec…
|
wyoung
|
253 |
* CSS style sheets as `/style/qux.css` |
|
58883ec…
|
wyoung
|
254 |
|
|
58883ec…
|
wyoung
|
255 |
Although those files are all outside the Fossil repo at `/code`, |
|
58883ec…
|
wyoung
|
256 |
keep in mind that it is the browser’s notion of “self” that matters |
|
58883ec…
|
wyoung
|
257 |
here, not Fossil’s. All resources come from the same Internet |
|
58883ec…
|
wyoung
|
258 |
domain, so the browser cannot distinguish Fossil-provided content |
|
58883ec…
|
wyoung
|
259 |
from static content served directly by the proxy server. |
|
58883ec…
|
wyoung
|
260 |
|
|
780b58b…
|
wyoung
|
261 |
This method opens up many other potential benefits, such as |
|
780b58b…
|
wyoung
|
262 |
[TLS encryption][tls], high-performance tuning via custom HTTP |
|
58883ec…
|
wyoung
|
263 |
headers, integration with other web technologies like PHP, etc. |
|
58883ec…
|
wyoung
|
264 |
|
|
58883ec…
|
wyoung
|
265 |
You might wonder why we rank in-repo content as most preferred above. It |
|
58883ec…
|
wyoung
|
266 |
is because the first two options are the only ones that cause such |
|
58883ec…
|
wyoung
|
267 |
resources to be included in an initial clone or in subsequent repo |
|
58883ec…
|
wyoung
|
268 |
syncs. The methods further down the list have a number of undesirable |
|
58883ec…
|
wyoung
|
269 |
properties: |
|
58883ec…
|
wyoung
|
270 |
|
|
58883ec…
|
wyoung
|
271 |
1. Relative links to out-of-repo files break in `fossil ui` when run on |
|
58883ec…
|
wyoung
|
272 |
a clone. |
|
58883ec…
|
wyoung
|
273 |
|
|
58883ec…
|
wyoung
|
274 |
2. Absolute links back to the public repo instance solve that: |
|
58883ec…
|
wyoung
|
275 |
|
|
58883ec…
|
wyoung
|
276 |
 |
|
58883ec…
|
wyoung
|
277 |
|
|
58883ec…
|
wyoung
|
278 |
...but using them breaks some types of failover and load-balancing |
|
58883ec…
|
wyoung
|
279 |
schemes, because it creates a [single point of failure][spof]. |
|
58883ec…
|
wyoung
|
280 |
|
|
58883ec…
|
wyoung
|
281 |
3. Absolute links fail when one’s purpose in using a clone is to |
|
58883ec…
|
wyoung
|
282 |
recover from the loss of a project web site by standing that clone |
|
58883ec…
|
wyoung
|
283 |
up [as a server][svr] elsewhere. You probably forgot to copy such |
|
58883ec…
|
wyoung
|
284 |
external resources in the backup copies, so that when the main repo |
|
58883ec…
|
wyoung
|
285 |
site disappears, so do those files. |
|
58883ec…
|
wyoung
|
286 |
|
|
58883ec…
|
wyoung
|
287 |
Unversioned content is in the middle of the first list above — between |
|
58883ec…
|
wyoung
|
288 |
fully-external content and fully in-repo content — because it isn’t |
|
58883ec…
|
wyoung
|
289 |
included in a clone unless you give the `--unversioned` flag. If you |
|
58883ec…
|
wyoung
|
290 |
then want updates to the unversioned content to be included in syncs, |
|
c64f28d…
|
drh
|
291 |
you have to give the same flag to [a `sync` command](/help/sync). |
|
58883ec…
|
wyoung
|
292 |
There is no equivalent with other commands such as `up` and `pull`, so |
|
58883ec…
|
wyoung
|
293 |
you must then remember to give `fossil uv` commands when necessary to |
|
58883ec…
|
wyoung
|
294 |
pull new unversioned content down. |
|
58883ec…
|
wyoung
|
295 |
|
|
58883ec…
|
wyoung
|
296 |
Thus our recommendation that you refer to in-repo resources exclusively. |
|
58883ec…
|
wyoung
|
297 |
|
|
c64f28d…
|
drh
|
298 |
[du]: /help/www/doc |
|
58883ec…
|
wyoung
|
299 |
[fp]: ./forum.wiki |
|
c64f28d…
|
drh
|
300 |
[ru]: /help/www/raw |
|
58883ec…
|
wyoung
|
301 |
[spof]: https://en.wikipedia.org/wiki/Single_point_of_failure |
|
8d43bb8…
|
wyoung
|
302 |
[tkt]: ./tickets.wiki |
|
8d43bb8…
|
wyoung
|
303 |
[tn]: ./event.wiki |
|
780b58b…
|
wyoung
|
304 |
[tls]: ./server/debian/nginx.md |
|
c64f28d…
|
drh
|
305 |
[uu]: /help/www/uv |
|
58883ec…
|
wyoung
|
306 |
[uv]: ./unvers.wiki |
|
8d43bb8…
|
wyoung
|
307 |
[wiki]: ./wikitheory.wiki |
|
366b23a…
|
wyoung
|
308 |
|
|
58883ec…
|
wyoung
|
309 |
|
|
93cee1f…
|
wyoung
|
310 |
## <a id="override"></a>Overriding the Default CSP |
|
366b23a…
|
wyoung
|
311 |
|
|
366b23a…
|
wyoung
|
312 |
If you wish to relax the default CSP’s restrictions or to tighten them |
|
896aa05…
|
wyoung
|
313 |
further, there are multiple ways to accomplish that. |
|
896aa05…
|
wyoung
|
314 |
|
|
896aa05…
|
wyoung
|
315 |
The following methods are listed in top-down order to give the simplest |
|
896aa05…
|
wyoung
|
316 |
and most straightforward method first. Further methods dig down deeper |
|
896aa05…
|
wyoung
|
317 |
into the stack, which is helpful to understand even if you end up using |
|
896aa05…
|
wyoung
|
318 |
a higher-level method. |
|
896aa05…
|
wyoung
|
319 |
|
|
896aa05…
|
wyoung
|
320 |
|
|
93cee1f…
|
wyoung
|
321 |
### <a id="cspsetting"></a>The `default-csp` Setting |
|
896aa05…
|
wyoung
|
322 |
|
|
c64f28d…
|
drh
|
323 |
If the [`default-csp` setting](/help/default-csp) is defined and is |
|
896aa05…
|
wyoung
|
324 |
not an empty string, its value is injected into the page using |
|
896aa05…
|
wyoung
|
325 |
[TH1](./th1.md) via one or more of the methods below, depending on the |
|
896aa05…
|
wyoung
|
326 |
skin you’re using and local configuration. |
|
896aa05…
|
wyoung
|
327 |
|
|
896aa05…
|
wyoung
|
328 |
Changing this setting is the easiest way to set a nonstandard CSP on |
|
896aa05…
|
wyoung
|
329 |
your site. |
|
896aa05…
|
wyoung
|
330 |
|
|
896aa05…
|
wyoung
|
331 |
Because a blank setting tells Fossil to use its hard-coded default CSP, |
|
896aa05…
|
wyoung
|
332 |
you have to say something like the following to get a repository without |
|
896aa05…
|
wyoung
|
333 |
content security policy restrictions: |
|
896aa05…
|
wyoung
|
334 |
|
|
8a1ba49…
|
wyoung
|
335 |
$ fossil set -R /path/to/served/repo.fossil default-csp 'default-src *' |
|
896aa05…
|
wyoung
|
336 |
|
|
896aa05…
|
wyoung
|
337 |
We recommend that instead of using the command line to change this |
|
896aa05…
|
wyoung
|
338 |
setting that you do it via the repository’s web interface, in |
|
896aa05…
|
wyoung
|
339 |
Admin → Settings. Write your CSP rules in the edit box marked |
|
896aa05…
|
wyoung
|
340 |
"`default-csp`". Do not add hard newlines in that box: the setting needs |
|
896aa05…
|
wyoung
|
341 |
to be on a single long line. Beware that changes take effect |
|
896aa05…
|
wyoung
|
342 |
immediately, so be careful with your edits: you could end up locking |
|
896aa05…
|
wyoung
|
343 |
yourself out of the repository with certain CSP changes! |
|
896aa05…
|
wyoung
|
344 |
|
|
896aa05…
|
wyoung
|
345 |
There are a few reasons why changing this setting via the command line |
|
896aa05…
|
wyoung
|
346 |
is inadvisable, except for very short settings like the example above: |
|
896aa05…
|
wyoung
|
347 |
|
|
896aa05…
|
wyoung
|
348 |
1. You have to be sure to set it on the repository where you want the |
|
896aa05…
|
wyoung
|
349 |
CSP to apply. Changing this setting on your local clone doesn’t |
|
896aa05…
|
wyoung
|
350 |
affect the remote repo you cloned from, which is most likely where |
|
896aa05…
|
wyoung
|
351 |
you want the CSP restrictions. |
|
896aa05…
|
wyoung
|
352 |
|
|
896aa05…
|
wyoung
|
353 |
2. For more complicated CSPs, the quoting rules for your shell and the |
|
896aa05…
|
wyoung
|
354 |
CSP syntax may interact, making it difficult or impossible to set |
|
896aa05…
|
wyoung
|
355 |
your desired CSP via the command line. Setting it via the web UI |
|
896aa05…
|
wyoung
|
356 |
doesn’t have this problem. |
|
896aa05…
|
wyoung
|
357 |
|
|
896aa05…
|
wyoung
|
358 |
|
|
896aa05…
|
wyoung
|
359 |
|
|
93cee1f…
|
wyoung
|
360 |
### <a id="th1"></a>TH1 Setup Hook |
|
896aa05…
|
wyoung
|
361 |
|
|
896aa05…
|
wyoung
|
362 |
Fossil sets [the TH1 variable `$default_csp`][thvar] from the |
|
896aa05…
|
wyoung
|
363 |
`default-csp` setting and uses *that* to inject the value into generated |
|
896aa05…
|
wyoung
|
364 |
HTML pages in its stock configuration. |
|
896aa05…
|
wyoung
|
365 |
|
|
896aa05…
|
wyoung
|
366 |
This means that another way you can override this value is to use |
|
896aa05…
|
wyoung
|
367 |
the [`th1-setup` hook script](./th1-hooks.md), which runs before TH1 |
|
896aa05…
|
wyoung
|
368 |
processing happens during skin processing: |
|
896aa05…
|
wyoung
|
369 |
|
|
8a1ba49…
|
wyoung
|
370 |
$ fossil set th1-setup "set default_csp {default-src 'self'}" |
|
896aa05…
|
wyoung
|
371 |
|
|
896aa05…
|
wyoung
|
372 |
After [the above](#admin-ui), this is the cleanest method. |
|
896aa05…
|
wyoung
|
373 |
|
|
896aa05…
|
wyoung
|
374 |
[thvar]: ./customskin.md#vars |
|
896aa05…
|
wyoung
|
375 |
|
|
896aa05…
|
wyoung
|
376 |
|
|
896aa05…
|
wyoung
|
377 |
|
|
93cee1f…
|
wyoung
|
378 |
### <a id="csrc"></a>Fossil C Source Code |
|
896aa05…
|
wyoung
|
379 |
|
|
896aa05…
|
wyoung
|
380 |
When you do neither of the above things, Fossil uses |
|
896aa05…
|
wyoung
|
381 |
[a hard-coded default](/info?ln=527-530&name=65a555d0d4fb846b). |
|
896aa05…
|
wyoung
|
382 |
|
|
896aa05…
|
wyoung
|
383 |
We tell you about this not to suggest that you hack the Fossil C source |
|
896aa05…
|
wyoung
|
384 |
code to change the CSP but simply to document the next step before we |
|
896aa05…
|
wyoung
|
385 |
move down-stack. |
|
896aa05…
|
wyoung
|
386 |
|
|
896aa05…
|
wyoung
|
387 |
|
|
896aa05…
|
wyoung
|
388 |
|
|
93cee1f…
|
wyoung
|
389 |
### <a id="header"></a>Skin Header |
|
896aa05…
|
wyoung
|
390 |
|
|
896aa05…
|
wyoung
|
391 |
[In the normal case](./customskin.md#override), Fossil injects the CSP |
|
896aa05…
|
wyoung
|
392 |
retrieved by one of the above methods into the header of all HTML |
|
896aa05…
|
wyoung
|
393 |
documents it generates: |
|
896aa05…
|
wyoung
|
394 |
|
|
896aa05…
|
wyoung
|
395 |
```HTML |
|
896aa05…
|
wyoung
|
396 |
<head>... |
|
896aa05…
|
wyoung
|
397 |
<meta http-equiv="Content-Security-Policy" content="..."> |
|
896aa05…
|
wyoung
|
398 |
... |
|
896aa05…
|
wyoung
|
399 |
``` |
|
896aa05…
|
wyoung
|
400 |
|
|
896aa05…
|
wyoung
|
401 |
Fossil skips this when you’re using a custom skin *and* its |
|
896aa05…
|
wyoung
|
402 |
[Header section](./customskin.md#headfoot) includes a `<body>` tag. This |
|
896aa05…
|
wyoung
|
403 |
is because prior to Fossil 2.5, the Header for a custom skin normally |
|
896aa05…
|
wyoung
|
404 |
contained everything from the opening `<html>` tag through the leading |
|
896aa05…
|
wyoung
|
405 |
`<body>` tag. From that version onward, Fossil now generates that header |
|
896aa05…
|
wyoung
|
406 |
when possible, so that the skin’s Header normally provides only the |
|
896aa05…
|
wyoung
|
407 |
opening tags of the document body, rather than the HTML header. |
|
896aa05…
|
wyoung
|
408 |
|
|
896aa05…
|
wyoung
|
409 |
When we added CSP support in Fossil 2.7, we made use of that mechanism |
|
896aa05…
|
wyoung
|
410 |
to inject the CSP into the generated HTML document header. |
|
896aa05…
|
wyoung
|
411 |
|
|
896aa05…
|
wyoung
|
412 |
For backwards compatibility, Fossil skips this when the skin’s Header |
|
896aa05…
|
wyoung
|
413 |
includes a `<body>` tag. Fossil takes that as a hint that it’s dealing |
|
896aa05…
|
wyoung
|
414 |
with a skin made in the pre-Fossil-2.5 days and doesn’t try to blindly |
|
896aa05…
|
wyoung
|
415 |
override it. |
|
896aa05…
|
wyoung
|
416 |
|
|
896aa05…
|
wyoung
|
417 |
The problem then is that you may be a Fossil user from the days before |
|
896aa05…
|
wyoung
|
418 |
Fossil 2.5, and you may be using a custom skin. This includes users who |
|
896aa05…
|
wyoung
|
419 |
selected one of the stock skins, since for the purposes of this section, |
|
896aa05…
|
wyoung
|
420 |
there is no difference between the cases. If you go into Admin → Skins → |
|
896aa05…
|
wyoung
|
421 |
Header and find a `<body>` tag, none of the above will apply to your |
|
896aa05…
|
wyoung
|
422 |
repo since Fossil will not be injecting its CSP into your pages. |
|
896aa05…
|
wyoung
|
423 |
|
|
896aa05…
|
wyoung
|
424 |
If you selected one of the stock skins (e.g. Khaki) prior to upgrading |
|
896aa05…
|
wyoung
|
425 |
to Fossil 2.5+ and didn’t make any changes to it since that time, you |
|
896aa05…
|
wyoung
|
426 |
can take the simplest option, which is to simply revert to the stock |
|
896aa05…
|
wyoung
|
427 |
version of the skin, so your pages will have the CSP injected, at which |
|
896aa05…
|
wyoung
|
428 |
point this document will begin describing what Fossil does with that |
|
896aa05…
|
wyoung
|
429 |
repo. |
|
896aa05…
|
wyoung
|
430 |
|
|
896aa05…
|
wyoung
|
431 |
If you’re using a customized version of one of the stock skins, the |
|
896aa05…
|
wyoung
|
432 |
skinning mechanism has a diff feature to make it easier to fold your |
|
896aa05…
|
wyoung
|
433 |
local changes into the stock version. |
|
896aa05…
|
wyoung
|
434 |
|
|
896aa05…
|
wyoung
|
435 |
If you’re using a fully customized skin, we recommend replicating the |
|
896aa05…
|
wyoung
|
436 |
method that [the Bootstrap skin uses][dcinj].² Alone among the stock |
|
896aa05…
|
wyoung
|
437 |
Fossil skins, Bootstrap still does old-style Header processing, |
|
896aa05…
|
wyoung
|
438 |
providing the entire HTML header and the start of the document body. |
|
896aa05…
|
wyoung
|
439 |
|
|
896aa05…
|
wyoung
|
440 |
We do *not* recommend injecting an explicit `Content-Security-Policy` |
|
896aa05…
|
wyoung
|
441 |
meta tag into a header to override Fossil’s default CSP. That means you |
|
896aa05…
|
wyoung
|
442 |
have to edit the skin every time you want to change the CSP. Use the TH1 |
|
896aa05…
|
wyoung
|
443 |
`$default_csp` variable like the Bootstrap skin does so you can use one |
|
896aa05…
|
wyoung
|
444 |
of the methods above with your custom skin, so the CSP can vary |
|
896aa05…
|
wyoung
|
445 |
independently of the skin. |
|
896aa05…
|
wyoung
|
446 |
|
|
896aa05…
|
wyoung
|
447 |
[dcinj]: /info?ln=7&name=bef080a6929a3e6f |
|
896aa05…
|
wyoung
|
448 |
|
|
896aa05…
|
wyoung
|
449 |
|
|
93cee1f…
|
wyoung
|
450 |
### <a id="fep"></a>Front-End Proxy |
|
896aa05…
|
wyoung
|
451 |
|
|
896aa05…
|
wyoung
|
452 |
If your Fossil repo is behind some sort of HTTP [front-end proxy][svr], |
|
896aa05…
|
wyoung
|
453 |
the [preferred method][pmcsp] for setting the CSP is via a custom HTTP |
|
896aa05…
|
wyoung
|
454 |
header, which most HTTP reverse proxy programs allow. |
|
896aa05…
|
wyoung
|
455 |
|
|
896aa05…
|
wyoung
|
456 |
Beware that if you have a CSP set via both the HTTP and HTML headers |
|
896aa05…
|
wyoung
|
457 |
that the two CSPs [merge](https://stackoverflow.com/a/51153816/142454), |
|
896aa05…
|
wyoung
|
458 |
taking the most restrictive elements of each CSP. If you wish the proxy |
|
896aa05…
|
wyoung
|
459 |
layer’s setting to completely override Fossil’s setting, you will need |
|
896aa05…
|
wyoung
|
460 |
to combine that with one of the methods above to either remove the |
|
896aa05…
|
wyoung
|
461 |
Fossil-provided CSP or to make Fossil provide a no-restrictions CSP |
|
896aa05…
|
wyoung
|
462 |
which the front-end proxy can then tighten down. |
|
896aa05…
|
wyoung
|
463 |
|
|
896aa05…
|
wyoung
|
464 |
[pmcsp]: https://developers.google.com/web/fundamentals/security/csp/#the_meta_tag |
|
896aa05…
|
wyoung
|
465 |
|
|
366b23a…
|
wyoung
|
466 |
|
|
366b23a…
|
wyoung
|
467 |
|
|
366b23a…
|
wyoung
|
468 |
------------ |
|
366b23a…
|
wyoung
|
469 |
|
|
366b23a…
|
wyoung
|
470 |
|
|
366b23a…
|
wyoung
|
471 |
**Asides and Digressions:** |
|
366b23a…
|
wyoung
|
472 |
|
|
91377ae…
|
wyoung
|
473 |
1. Fossil might someday switch to serving the “JavaScript” section of a |
|
91377ae…
|
wyoung
|
474 |
custom skin as a virtual text file, allowing it to be cached by the |
|
91377ae…
|
wyoung
|
475 |
browser, reducing page load times. |
|
91377ae…
|
wyoung
|
476 |
|
|
896aa05…
|
wyoung
|
477 |
2. The stock Bootstrap skin *did* provide redundant CSP text from |
|
896aa05…
|
wyoung
|
478 |
Fossil 2.7 through Fossil 2.9, so setting the CSP via the higher |
|
896aa05…
|
wyoung
|
479 |
level methods did not work with that skin. We fixed this in Fossil |
|
896aa05…
|
wyoung
|
480 |
2.10, but if you selected the Bootstrap skin prior to that, you’re |
|
896aa05…
|
wyoung
|
481 |
now running on a *copy* of it stored in your repo settings table, so |
|
896aa05…
|
wyoung
|
482 |
the change to the stock version of the skin won’t affect that repo |
|
896aa05…
|
wyoung
|
483 |
automatically. You will have to either merge the diffs in with your |
|
896aa05…
|
wyoung
|
484 |
local changes or revert to the stock version of the skin. |
|
4e6d36d…
|
wyoung
|
485 |
|
|
4e6d36d…
|
wyoung
|
486 |
|
|
366b23a…
|
wyoung
|
487 |
[cs]: ./customskin.md |
|
366b23a…
|
wyoung
|
488 |
[csp]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP |
|
366b23a…
|
wyoung
|
489 |
[de]: https://dopiaza.org/tools/datauri/index.php |
|
33a7b8b…
|
drh
|
490 |
[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting |