~seirdy/seirdy.one

f6413346af03ad900e1407ba098df06939d99569 — Rohan Kumar 3 months ago d6363e2
Web best practices: add "security" section

Add information on restricting site functionality.

Add some details on accomodating Tor users.
2 files changed, 142 insertions(+), 28 deletions(-)

M content/posts/website-best-practices.gmi
M content/posts/website-best-practices.md
M content/posts/website-best-practices.gmi => content/posts/website-best-practices.gmi +83 -13
@@ 33,6 33,56 @@ Earlier revisions of this post generated some responses I thought I should addre

=> https://lobste.rs/s/akcw1m Lobsters thread

## Security

One of the defining differences between textual websites and advanced Web 2.0 sites/apps is safety. Most browser vulnerabilities are related to modern Web features like JavaScript and WebGL. The simplicity of basic textual websites *should* guarantee some extra safety; however, webmasters need to take some additional measures to ensure limited use of "modern" risky features.

### TLS

All of the simplicity in the world won't protect a page from unsafe content injection by an intermediary. Proper use of TLS protects against page alteration in transit and ensures a limited degree of privacy. Test your TLS setup with these tools:

=> https://testssl.sh/ testssl.sh
=> https://webbkoll.dataskydd.net/ Webbkoll

### Scripts and the Content Security Policy

Consider taking hardening measures to maximize the security benefits made possible by the simplicity of textual websites, starting with script removal.

JavaScript and WebAssembly are responsible for the bulk of modern web exploits. Ideally, a text-oriented site can enforce a scripting ban at the content security policy (CSP) level.

=> https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP CSP on MDN

For example, here's the CSP for https://seirdy.one:

```
default-src 'none';
img-src 'self' data:;
style-src 'sha256-Amup01ZIYjs1kyVZqHYW1tGhvlStSHIoFDKATF7L7VI='; style-src-attr 'none';
frame-ancestors 'none'; base-uri 'none'; form-action 'none';
manifest-src 'self';
upgrade-insecure-requests;
sandbox allow-same-origin
```

"script-src: 'none'" is implied by "default-src: 'none'", causing a compliant browser to forbid the loading of scripts. Furthermore, the "sandbox" CSP directive forbids a wide variety) of potentially insecure actions.

=> https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/sandbox "sandbox" CSP directive on MDN

While "script-src" restricts script loading, "sandbox" can also restrict script execution with stronger defenses against script injection (e.g. by a browser addon).¹ I added the `allow-same-origin` parameter so that these addons will still be able to function.²

### If you must enable scripts

Please use progressive enhancement³ throughout your site; every feature possible should be optional, and scripting is no exception.

I'm sure you're a great person, but your readers might not know that; don't expect them to trust your website. Your scripts should look as safe as possible to an untrusting eye. Avoid requesting permissions or using sensitive APIs:

=> https://browserleaks.com/javascript JavaScript Browser Information (BrowserLeaks)

Finally, consider using your CSP to restrict script loading. If you must use inline scripts, selectively allow them with a hash or nonce. Some recent directives restrict and enforce proper use of trusted types.

=> https://web.dev/trusted-types/ Trusted types
=> https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/trusted-types CSP trusted types on MDN

## About fonts

If you really want, you could use serif instead of sans-serif; however, serif fonts tend to look worse on low-res monitors. Not every screen's DPI has three digits.


@@ 203,11 253,15 @@ For one, Tor users are encouraged to set the Tor Browser Bundle's (TBB) security

=> https://tb-manual.torproject.org/en-US/security-settings/ TBB Security Settings

This disables scripts, MathML, some fonts, SVG images, and other features. If your site has any SVG images, be sure to provide a fallback to raster formats using a "<picture>" element.
This disables scripts, MathML, some fonts, SVG images, and other features:

=> https://gitweb.torproject.org/torbutton.git/tree/modules/security-prefs.js Torbutton security-prefs source code

If your site has any SVG images, be sure to provide a fallback to raster formats using a "<picture>" element.

Additionally, hopping between nodes in Tor circuits incurs latency, worsening the impacts of requiring multiple requests and round-trips. Try to minimise the number of requests to view a page.

If you use a CDN or some overcomplicated website security stack, make sure it doesn't block Tor users or require them to enable JS to complete a CAPTCHA.
If you use a CDN or some overcomplicated website security stack, make sure it doesn't block Tor users or require them to enable JS to complete a CAPTCHA. To go above and beyond, try mirroring your site to an onion service to reduce the need for exit nodes.

## Testing



@@ 221,20 275,21 @@ Your page should easily pass the harshest of tests without any extra effort if i

These tests start out pretty reasonable, but gradually get more insane as you go down. Once again, use your judgement.

1. Test using the Tor browser with the safest security level enabled (disables JS and other features).
2. Load just the HTML. No CSS, no images, etc. Try loading without inline CSS as well for good measure.
3. Print out the site in black-and-white, preferably with a simple laser printer.
4. Test with a screen reader.
5. Test keyboard navigability with the tab key. Even without specifying tab indices, tab selection should follow a logical order if you keep the layout simple.
6. Test in textual browsers: lynx, links, w3m, ELinks, edbrowse, EWW, Netrik, etc.
7. Read the (prettified/indented) HTML source itself and parse it with your brain. See if anything seems illogical or unnecessary. Imagine giving someone a printout of your page's <body> along with a whiteboard. If they have a basic knowledge of HTML tags, would they be able to draw something resembling your website?
8. Test in an online website translator tool.
9. Test on something ridiculous: try your old e-reader's embedded browser, combine an HTML-to-EPUB converter and an EPUB-to-PDF converter, or stack multiple article-extraction utilities on top of each other. Be creative and enjoy breaking your site. When something breaks, examine the breakage and see if you can fix it by simplifying your page.
10. Build a time machine. Travel decades--or perhaps centuries--into the future. Keep going forward until the WWW is breathing its last breath. Test your site on future browsers. Figuring out how to transfer your files onto their computers might take some time, but you have a time machine so that shouldn't be too hard. When you finish, go back in time to meet Benjamin Franklin:
1. Evaluate the heaviness and complexity of your scripts (if any) by testing with your browser's JIT compilation disabled.⁴
2. Test using the Tor browser with the safest security level enabled (disables JS and other features).
3. Load just the HTML. No CSS, no images, etc. Try loading without inline CSS as well for good measure.
4. Print out the site in black-and-white, preferably with a simple laser printer.
5. Test with a screen reader.
6. Test keyboard navigability with the tab key. Even without specifying tab indices, tab selection should follow a logical order if you keep the layout simple.
7. Test in textual browsers: lynx, links, w3m, ELinks, edbrowse, EWW, Netrik, etc.
8. Read the (prettified/indented) HTML source itself and parse it with your brain. See if anything seems illogical or unnecessary. Imagine giving someone a printout of your page's <body> along with a whiteboard. If they have a basic knowledge of HTML tags, would they be able to draw something resembling your website?
9. Test in an online website translator tool.
10. Test on something ridiculous: try your old e-reader's embedded browser, combine an HTML-to-EPUB converter and an EPUB-to-PDF converter, or stack multiple article-extraction utilities on top of each other. Be creative and enjoy breaking your site. When something breaks, examine the breakage and see if you can fix it by simplifying your page.
11. Build a time machine. Travel decades--or perhaps centuries--into the future. Keep going forward until the WWW is breathing its last breath. Test your site on future browsers. Figuring out how to transfer your files onto their computers might take some time, but you have a time machine so that shouldn't be too hard. When you finish, go back in time to meet Benjamin Franklin:

=> https://xkcd.com/567/ xkcd: Urgent Mission

I'm still on step 9, trying to find new ways to break this page. If you come up with a new test, please share it:
I'm still on step 10, trying to find new ways to break this page. If you come up with a new test, please share it:

=> mailto:~seirdy/seirdy.one-comments@lists.sr.ht Mailing list for this website



@@ 268,3 323,18 @@ The WebBS calculator compares a page's size with the size of a PNG screenshot of
One resource I found useful (that eventually featured this article!) was the “Your page content” section of Bill Dietrich’s comprehensive guide to setting up your personal website:

=> https://www.billdietrich.me/YourPersonalWebSite.html#PageContent Your Personal Website

## Notes

¹ Many addons function by injecting content into pages; this significantly weakens many aspects of the browser security model (e.g. site and origin isolation) and should be avoided if at all possible. On sensitive pages with content such as public key fingerprints, I recommend setting a blank `sandbox` directive even if it means breaking these addons.

² Some addons will have reduced functionality; for instance, Tridactyl can't create an <iframe> for its command window. I consider this to be worthwhile since the most important functionality is still available, and because authors shouldn't feel compelled to support security weakening. I say this as someone who uses Tridactyl often.

=> https://github.com/tridactyl/tridactyl Tridactyl

³ Here's an overview of PE and my favorite write-up on the subject.

=> https://en.wikipedia.org/wiki/Progressive_enhancement Progressive Enhancement (Wikipedia)
=> https://whalecoiner.com/articles/progressive-enhancement Yes, progressive enhancement is a fucking moral argument

⁴ Consider disabling the JIT for your normal browsing too; doing so removes whole classes of vulnerabilities. In Firefox, toggle javascript.options.ion, javascript.options.baselinejit, javascript.options.native_regexp, javascript.options.asmjs, and javascript.options.wasm in about:config; in Chromium, run chromium with `--js-flags='--jitless'`; in the Tor Browser, set the security level to "Safer".

M content/posts/website-best-practices.md => content/posts/website-best-practices.md +59 -15
@@ 41,10 41,45 @@ I'd like to re-iterate yet another time that this only applies to websites that 

Earlier revisions of this post generated some responses I thought I should address below. Special thanks to the IRC and [Lobsters](https://lobste.rs/s/akcw1m) users who gave good feedback!

Security
--------

One of the defining differences between textual websites and advanced Web 2.0 sites/apps is safety. Most browser vulnerabilities are related to modern Web features like JavaScript and WebGL. The simplicity of basic textual websites _should_ guarantee some extra safety; however, webmasters need to take some additional measures to ensure limited use of "modern" risky features.

### TLS

All of the simplicity in the world won't protect a page from unsafe content injection by an intermediary. Proper use of TLS protects against page alteration in transit and ensures a limited degree of privacy. Test your TLS setup with [testssl.sh](https://testssl.sh/) and [Webbkoll](https://webbkoll.dataskydd.net/).

### Scripts and the Content Security Policy

Consider taking hardening measures to maximize the security benefits made possible by the simplicity of textual websites, starting with script removal.

JavaScript and WebAssembly are responsible for the bulk of modern web exploits. Ideally, a text-oriented site can enforce a scripting ban at the [<abbr title="content security policy">CSP</abbr>](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) level. For example, here's the CSP for `https://seirdy.one`:

```
default-src 'none';
img-src 'self' data:;
style-src 'sha256-Amup01ZIYjs1kyVZqHYW1tGhvlStSHIoFDKATF7L7VI='; style-src-attr 'none';
frame-ancestors 'none'; base-uri 'none'; form-action 'none';
manifest-src 'self';
upgrade-insecure-requests;
sandbox allow-same-origin
```

`script-src: 'none'` is implied by `default-src: 'none'`, causing a compliant browser to forbid the loading of scripts. Furthermore, the `sandbox` CSP directive forbids a [wide variety](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/sandbox) of potentially insecure actions. While `script-src` restricts script loading, `sandbox` can also restrict script execution with stronger defenses against script injection (e.g. by a browser addon).[^1] I added the `allow-same-origin` parameter so that these addons will still be able to function.[^2]

### If you must enable scripts

Please use progressive enhancement (<abbr title="progressive enhancement">PE</abbr>)[^3] throughout your site; every feature possible should be optional, and scripting is no exception.

I'm sure you're a great person, but your readers might not know that; don't expect them to trust your website. Your scripts should look as safe as possible to an untrusting eye. Avoid requesting permissions or using [sensitive APIs](https://browserleaks.com/javascript).

Finally, consider using your CSP to restrict script loading. If you must use inline scripts, selectively allow them with a hash or nonce. Some [recent directives](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/trusted-types) restrict and enforce proper use of [trusted types](https://web.dev/trusted-types/).

About fonts
-----------

If you really want, you could use serif instead of sans-serif; however, serif fonts tend to look worse on low-res monitors. Not every screen's DPI has three digits.
If you really want, you could use serif instead of sans-serif; however, serif fonts tend to look worse on low-res monitors. Not every screen's <abbr title="Dots Per Inch">DPI</abbr> has three digits.

To ship custom fonts is to assert that branding is more important than user choice. That might very well be a reasonable thing to do; branding isn't evil! That being said, textual websites in particular don't benefit much from branding. Beyond basic layout and optionally supporting dark mode, authors generally shouldn't dictate the presentation of their websites; that should be the job of the user agent. Most websites are not important enough to look completely different from the rest of the user's system.



@@ 77,7 112,7 @@ Users on poor connections have better things to do than idly wait for pages to l

Unfortunately, pages with lazy loading don't finish loading off-screen images in the background. To load this content ahead of time, users need to switch to the loading page and slowly scroll to the bottom to ensure that all the important content appears on-screen and starts loading. Website owners shouldn't expect users to have to jump through these ridiculous hoops.

A similar attribute that I *do* recommend is the [`decoding`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Img#attr-decoding) attribute. I typically use `decoding="async"` so that image decoding can be deferred.
A similar attribute that I _do_ recommend is the [`decoding`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Img#attr-decoding) attribute. I typically use `decoding="async"` so that image decoding can be deferred.

### Wouldn't this be solved by combining lazy loading with pre-loading/pre-fetching?



@@ 189,11 224,11 @@ Tor

Many people use Tor out of necessity. On Tor, additional constraints apply.

For one, Tor users are encouraged to set the Tor Browser Bundle's (<abbr title="Tor Browser Bundle">TBB</abbr>) [security settings](https://tb-manual.torproject.org/en-US/security-settings/) to "safest". This disables scripts, MathML, some fonts, SVG images, and other features. If your site has any SVG images, be sure to provide a fallback to raster formats using a `<picture>` element.
For one, Tor users are encouraged to set the Tor Browser Bundle's (<abbr title="Tor Browser Bundle">TBB</abbr>) [security settings](https://tb-manual.torproject.org/en-US/security-settings/) to "safest". This disables scripts, MathML, some fonts, SVG images, and [other features](https://gitweb.torproject.org/torbutton.git/tree/modules/security-prefs.js). If your site has any SVG images, be sure to provide a fallback to raster formats using a `<picture>` element.

Additionally, hopping between nodes in Tor circuits incurs latency, worsening the impacts of requiring multiple requests and round-trips. Try to minimise the number of requests to view a page.

If you use a CDN or some overcomplicated website security stack, make sure it doesn't block Tor users or require them to enable JS to complete a CAPTCHA.
If you use a CDN or some overcomplicated website security stack, make sure it doesn't block Tor users or require them to enable JS to complete a CAPTCHA. To go above and beyond, try mirroring your site to an onion service to reduce the need for exit nodes.

Testing
-------


@@ 208,18 243,19 @@ Your page should easily pass the harshest of tests without any extra effort if i

These tests start out pretty reasonable, but gradually get more insane as you go down. Once again, use your judgement.

1. Test using the Tor browser with the safest security level enabled (disables JS and other features).
2. Load just the HTML. No CSS, no images, etc. Try loading without inline CSS as well for good measure.
3. Print out the site in black-and-white, preferably with a simple laser printer.
4. Test with a screen reader.
5. Test keyboard navigability with the tab key. Even without specifying tab indices, tab selection should follow a logical order if you keep the layout simple.
6. Test in textual browsers: lynx, links, w3m, ELinks, edbrowse, EWW, Netrik, etc.
7. Read the (prettified/indented) HTML source itself and parse it with your brain. See if anything seems illogical or unnecessary. Imagine giving someone a printout of your page's `<body>` along with a whiteboard. If they have a basic knowledge of HTML tags, would they be able to draw something resembling your website?
8. Test in an online website translator tool.
9. Test on something ridiculous: try your old e-reader's embedded browser, combine an HTML-to-EPUB converter and an EPUB-to-PDF converter, or stack multiple article-extraction utilities on top of each other. Be creative and enjoy breaking your site. When something breaks, examine the breakage and see if you can fix it by simplifying your page.
10. Build a time machine. Travel decades--or perhaps centuries--into the future. Keep going forward until the WWW is breathing its last breath. Test your site on future browsers. Figuring out how to transfer your files onto their computers might take some time, but you have a time machine so that shouldn't be too hard. When you finish, go back in time to [meet Benjamin Franklin](https://xkcd.com/567/).
1. Evaluate the heaviness and complexity of your scripts (if any) by testing with your browser's <abbr title="just-in-time">JIT</abbr> compilation disabled.[^4]
2. Test using the Tor browser with the safest security level enabled (disables JS, SVG, and other features).
3. Load just the HTML. No CSS, no images, etc. Try loading without inline CSS as well for good measure.
4. Print out the site in black-and-white, preferably with a simple laser printer.
5. Test with a screen reader.
6. Test keyboard navigability with the tab key. Even without specifying tab indices, tab selection should follow a logical order if you keep the layout simple.
7. Test in textual browsers: lynx, links, w3m, ELinks, edbrowse, EWW, Netrik, etc.
8. Read the (prettified/indented) HTML source itself and parse it with your brain. See if anything seems illogical or unnecessary. Imagine giving someone a printout of your page's `<body>` along with a whiteboard. If they have a basic knowledge of HTML tags, would they be able to draw something resembling your website?
9. Test in an online website translator tool.
10. Test on something ridiculous: try your old e-reader's embedded browser, combine an HTML-to-EPUB converter and an EPUB-to-PDF converter, or stack multiple article-extraction utilities on top of each other. Be creative and enjoy breaking your site. When something breaks, examine the breakage and see if you can fix it by simplifying your page.
11. Build a time machine. Travel decades--or perhaps centuries--into the future. Keep going forward until the WWW is breathing its last breath. Test your site on future browsers. Figuring out how to transfer your files onto their computers might take some time, but you have a time machine so that shouldn't be too hard. When you finish, go back in time to [meet Benjamin Franklin](https://xkcd.com/567/).

I'm still on step 9, trying to find new ways to break this page. If you come up with a new test, please [share it](mailto:~seirdy/seirdy.one-comments@lists.sr.ht).
I'm still on step 10, trying to find new ways to break this page. If you come up with a new test, please [share it](mailto:~seirdy/seirdy.one-comments@lists.sr.ht).

Other places to check out
-------------------------


@@ 236,3 272,11 @@ The [WebBS calculator](https://www.webbloatscore.com/) compares a page's size wi

One resource I found useful (that eventually featured this article!) was the "Your page content" section of <span class="h-card vcard"><a class="p-name url fn n" href="https://www.billdietrich.me"><span class="p-given-name given-name">Bill</span> <span class="p-family-name family-name">Dietrich</span>'s</a></span> comprehensive guide to [setting up your personal website](https://www.billdietrich.me/YourPersonalWebSite.html#PageContent).


[^1]: Many addons function by injecting content into pages; this significantly weakens many aspects of the browser security model (e.g. site and origin isolation) and should be avoided if at all possible. On sensitive pages with content such as public key fingerprints, I recommend setting a blank `sandbox` directive even if it means breaking these addons.

[^2]: Some addons will have reduced functionality; for instance, [Tridactyl](https://github.com/tridactyl/tridactyl) can't create an `<iframe>` for its command window. I consider this to be worthwhile since the most important functionality is still available, and because authors shouldn't feel compelled to support security weakening. I say this as someone who uses Tridactyl often.

[^3]: Here's an [overview of PE](https://en.wikipedia.org/wiki/Progressive_enhancement) and [my favorite write-up on the subject](https://whalecoiner.com/articles/progressive-enhancement).

[^4]: Consider disabling the JIT for your normal browsing too; doing so removes whole classes of vulnerabilities. In Firefox, toggle `javascript.options.ion`, `javascript.options.baselinejit`, `javascript.options.native_regexp`, `javascript.options.asmjs`, and `javascript.options.wasm` in `about:config`; in Chromium, run chromium with `--js-flags='--jitless'`; in the Tor Browser, set the security level to "Safer".