Content-Security-Policy (CSP) is a web security feature that allows
servers to declare what loaded content is allowed to do. For example,
a policy can prevent loading of images, JavaScript, CSS, etc unless
the source of that content is whitelisted (by hostname, URI scheme,
hashes of content, etc). It's a nifty security feature that provides
extra mitigation against some attacks, notably XSS.
Mitigation against these attacks is important for Mercurial because
hgweb renders repository data, which is commonly untrusted. While we
make attempts to escape things, etc, there's the possibility that
malicious data could be injected into the site content. If this happens
today, the full power of the web browser is available to that
malicious content. A restrictive CSP policy (defined by the server
operator and sent in an HTTP header which is outside the control of
malicious content), could restrict browser capabilities and mitigate
security problems posed by malicious data.
CSP works by emitting an HTTP header declaring the policy that browsers
should apply. Ideally, this header would be emitted by a layer above
Mercurial (likely the HTTP server doing the WSGI "proxying"). This
works for some CSP policies, but not all.
For example, policies to allow inline JavaScript may require setting
a "nonce" attribute on <script>. This attribute value must be unique
and non-guessable. And, the value must be present in the HTTP header
and the HTML body. This means that coordinating the value between
Mercurial and another HTTP server could be difficult: it is much
easier to generate and emit the nonce in a central location.
This commit introduces support for emitting a
Content-Security-Policy header from hgweb. A config option defines
the header value. If present, the header is emitted. A special
"%nonce%" syntax in the value triggers generation of a nonce and
inclusion in <script> elements in templates. The inclusion of a
nonce does not occur unless "%nonce%" is present. This makes this
commit completely backwards compatible and the feature opt-in.
The nonce is a type 4 UUID, which is the flavor that is randomly
generated. It has 122 random bits, which should be plenty to satisfy
the guarantees of a nonce.
Let's make paper (and coal, since it borrows so much from paper) templates use
symbolic revision in navigation links.
The majority of links (log, filelog, annotate, etc) still use node hashes.
Some pages don't have permanent links to current node hash (so it's not very
easy to go from /rev/tip to /rev/<tip hash>), this will be addressed in future
patches.
Since e902e55c3d0b, column headers are wrapped by <thead> element, so the first
and only <tbody> contains changelog data. I got the following error without
this patch:
Uncaught TypeError: Cannot read property 'lastElementChild' of null
scrollHandler @ mercurial.js:375
Some templates in paper style use <tbody> elements inside <table> to assign a
class to "body" part of that table (in this case, to make rows striped). The
problem is that the <tbody> is preceded by <tr> element, which browsers
understand as an implicit start of table body, so the following exlicit <tbody>
will actually be "nested", which is not valid.
Since that first <tr> contains table headers, wrapping it in <thead> is both
semantically correct and follows the advertised XHTML 1.1 doctype.
The <p> elements were used to create an empty space between the last menu item
(i.e. "help") and the atom feed icon, but they don't have any semantic meaning,
so it is better to use css instead.
The css rule uses top margin of 10px, which is equal to the top margin of the
menu blocks ("help", "changeset, browse", etc). Previously, with <p> elements,
the margin wasn't set explicitly and was browser-dependent.
This change is a "better version" of e028c221db4e, where <p> elements were
simply properly closed.
<p> elements can only contain inline elements, so as soon as browser encounters
a block element (e.g. block <div>) "inside" a <p>, it puts an implicit </p>.
It's better to do this explicitly.
Before the templater got extended for nested expressions, it made
sense to decode string escapes across the whole string. Now we do it
on a piece by piece basis.
Namely, this allows the next page pointer to be not only revision hash given
in page code, but also any value computed from the value for previous page.
Without this, repository paths or names containing e.g. & characters or html
tags yielded strange results, possibly allowing cross-site scripting attacks.
The purpose of this change is to make it much easier to navigate up the
repository tree when the hg web server is used to serve more than one
repository.
A "URL breadcrumb" is a path where each of the path items can be clicked to go
to the corresponding path page.
This lets you go up the folder hierarchy very quickly. For example, when showing
the list of repositories in http://myserver/myteams/myprojects, the following
"breadcrumb" will be shown:
Mercurial > myteams > myprojects
Clicking on "myprojects" reloads the page. Clicking on "myteams" goes up one
folder. Clicking on the leftmost "Mercurial" goes to the server root.
This "breadcrumb" also appears on all repository pages. For example on the
summary page of the repository at http://myserver/myteams/myprojects/myrepo the
following will be shown:
Mercurial > myteams > myprojects > myrepo / summary
This change has been applied to all templates that already had a link to the
main repository page (i.e. gitweb, monoblue, paper and coal) plus to the index
page of the spartan template.
In order to make the breadcumb links stand out the some of the template styles
have been customized.
This change complements the existing web/logourl setting, and lets the user
customize the logo image that is shown on many of the hg server pages.
If this setting is not set, hglogo.png is used.
Clicking on the logo image/text in the hgweb interface brings the
user to the Mercurial project page. The majority of users expect that
this would bring them to the top level index. I have added a new template
variable named `logourl' which allows an administrator to change this
behavior. To stay compatible with existing behavior, `logourl' will
default to http://mercurial.selenic.com/. This change is very useful in
large installations where jumping to the index is common.
Remove the `install_package_data' subclass of `install_data' and use
the `package_data' functionality provided by distutils instead. As
package data must be located within the package directory, the data
files are now generated in the build directory.
To simplify the functionality of this change, the top-level `doc' and
`templates' directories have been moved into the `mercurial' package
directory.