diff options
| -rw-r--r-- | nginx/nginx.conf | 11 | ||||
| -rw-r--r-- | nginx/snippets/security-headers-base.conf | 13 | ||||
| -rw-r--r-- | nginx/snippets/security-headers.conf | 15 | ||||
| -rw-r--r-- | static/js/web-install.js | 32 | ||||
| -rw-r--r-- | static/web-install.html | 65 | ||||
| -rwxr-xr-x | validate_static | 2 |
6 files changed, 124 insertions, 14 deletions
diff --git a/nginx/nginx.conf b/nginx/nginx.conf index a2ec0406..ca9d3f9e 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -223,6 +223,17 @@ http { internal; } + location = /web-install { + include /etc/nginx/snippets/security-headers-base.conf; + add_header Permissions-Policy "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), display-capture=(), document-domain=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), xr-spatial-tracking=()" always; + # Feature-Policy is being replaced by Permissions-Policy + add_header Feature-Policy "accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; battery 'none'; camera 'none'; display-capture 'none'; document-domain 'none'; encrypted-media 'none'; fullscreen 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; payment 'none'; picture-in-picture 'none'; publickey-credentials-get 'none'; screen-wake-lock 'none'; sync-xhr 'none'; xr-spatial-tracking 'none'" always; + add_header Cache-Control "public, max-age=1800"; + add_header X-Robots-Tag "none"; + try_files $uri.html =404; + http2_push /grapheneos.css?29; + } + location / { include /etc/nginx/snippets/security-headers.conf; add_header Cache-Control "public, max-age=1800"; diff --git a/nginx/snippets/security-headers-base.conf b/nginx/snippets/security-headers-base.conf new file mode 100644 index 00000000..b5559fe7 --- /dev/null +++ b/nginx/snippets/security-headers-base.conf @@ -0,0 +1,13 @@ +add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; +add_header X-Content-Type-Options "nosniff" always; +add_header Referrer-Policy "no-referrer" always; +add_header Expect-CT "enforce, max-age=63072000" always; +add_header Cross-Origin-Opener-Policy "same-origin" always; +add_header Cross-Origin-Embedder-Policy "require-corp" always; +add_header Content-Security-Policy "default-src 'none'; connect-src 'self' https://releases.grapheneos.org/; font-src 'self'; img-src 'self'; manifest-src 'self'; script-src 'self'; style-src 'self'; form-action 'none'; frame-ancestors 'none'; block-all-mixed-content; base-uri 'none'; require-trusted-types-for 'script'" always; + +# obsolete and replaced with Content-Security-Policy frame-ancestors 'none' +add_header X-Frame-Options "DENY" always; + +# obsolete and replaced with strong Content-Security-Policy +add_header X-XSS-Protection "1; mode=block" always; diff --git a/nginx/snippets/security-headers.conf b/nginx/snippets/security-headers.conf index fc9fbb47..5ead941c 100644 --- a/nginx/snippets/security-headers.conf +++ b/nginx/snippets/security-headers.conf @@ -1,17 +1,6 @@ -add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; -add_header X-Content-Type-Options "nosniff" always; -add_header Referrer-Policy "no-referrer" always; -add_header Expect-CT "enforce, max-age=63072000" always; -add_header Cross-Origin-Opener-Policy "same-origin" always; -add_header Cross-Origin-Embedder-Policy "require-corp" always; -add_header Content-Security-Policy "default-src 'none'; connect-src 'self' https://releases.grapheneos.org/; font-src 'self'; img-src 'self'; manifest-src 'self'; script-src 'self'; style-src 'self'; form-action 'none'; frame-ancestors 'none'; block-all-mixed-content; base-uri 'none'; require-trusted-types-for 'script'" always; +include snippets/security-headers-base.conf; + add_header Permissions-Policy "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), display-capture=(), document-domain=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), xr-spatial-tracking=()" always; # Feature-Policy is being replaced by Permissions-Policy add_header Feature-Policy "accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; battery 'none'; camera 'none'; display-capture 'none'; document-domain 'none'; encrypted-media 'none'; fullscreen 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; payment 'none'; picture-in-picture 'none'; publickey-credentials-get 'none'; screen-wake-lock 'none'; sync-xhr 'none'; usb 'none'; xr-spatial-tracking 'none'" always; - -# obsolete and replaced with Content-Security-Policy frame-ancestors 'none' -add_header X-Frame-Options "DENY" always; - -# obsolete and replaced with strong Content-Security-Policy -add_header X-XSS-Protection "1; mode=block" always; diff --git a/static/js/web-install.js b/static/js/web-install.js new file mode 100644 index 00000000..5899fc9b --- /dev/null +++ b/static/js/web-install.js @@ -0,0 +1,32 @@ +// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT + +async function doConnect() { + const webusb = await Adb.open("WebUSB"); + + console.log("connected"); + + if (webusb.isAdb()) { + console.log("adb"); + const adb = await webusb.connectAdb("host::"); + await adb.reboot("bootloader"); + return; + } + + if (webusb.isFastboot()) { + console.log("fastboot"); + const fastboot = await webusb.connectFastboot(); + await fastboot.send("flashing unlock"); + await fastboot.receive(); + } +} + +if ("usb" in navigator) { + console.log("WebUSB available"); + + const connect = document.getElementById("connect"); + connect.onclick = doConnect; +} else { + console.log("WebUSB unavailable"); +} + +// @license-end diff --git a/static/web-install.html b/static/web-install.html new file mode 100644 index 00000000..b7a70440 --- /dev/null +++ b/static/web-install.html @@ -0,0 +1,65 @@ +<!DOCTYPE html> +<html lang="en" prefix="og: https://ogp.me/ns#"> + <head> + <meta charset="utf-8"/> + <title>Web install | GrapheneOS</title> + <meta name="description" content="Web-based installer for GrapheneOS"/> + <meta name="theme-color" content="#212121"/> + <meta name="msapplication-TileColor" content="#ffffff"/> + <meta name="viewport" content="width=device-width, initial-scale=1"/> + <meta name="twitter:site" content="@GrapheneOS"/> + <meta name="twitter:creator" content="@GrapheneOS"/> + <meta property="og:title" content="GrapheneOS web install"/> + <meta property="og:description" content="Web-based installer for GrapheneOS"/> + <meta property="og:type" content="website"/> + <meta property="og:image" content="https://grapheneos.org/opengraph.png"/> + <meta property="og:image:width" content="512"/> + <meta property="og:image:height" content="512"/> + <meta property="og:image:alt" content="GrapheneOS logo"/> + <meta property="og:url" content="https://grapheneos.org/web-install"/> + <meta property="og:site_name" content="GrapheneOS"/> + <link rel="icon" sizes="16x16 24x24 32x32 48x48 64x64" type="image/vnd.microsoft.icon" href="/favicon.ico"/> + <link rel="icon" sizes="any" type="image/svg+xml" href="/mask-icon.svg"/> + <link rel="mask-icon" href="/mask-icon.svg" color="#1a1a1a"/> + <link rel="apple-touch-icon" href="/apple-touch-icon.png"/> + <link rel="stylesheet" href="/grapheneos.css?29"/> + <link rel="manifest" href="/manifest.webmanifest"/> + <link rel="canonical" href="https://grapheneos.org/web-install"/> + <link rel="license" href="/LICENSE.txt"/> + <script defer="defer" src="/js/webadb.js?0"></script> + <script defer="defer" src="/js/web-install.js?0"></script> + </head> + <body> + <header> + <nav id="site-menu"> + <ul> + <li><a href="/">GrapheneOS</a></li> + <li><a href="/features">Features</a></li> + <li><a href="/install">Install</a></li> + <li><a href="/build">Build</a></li> + <li><a href="/usage">Usage</a></li> + <li><a href="/faq">FAQ</a></li> + <li><a href="/releases">Releases</a></li> + <li><a href="/source">Source</a></li> + <li><a href="/articles/">Articles</a></li> + <li><a href="/donate">Donate</a></li> + <li><a href="/contact">Contact</a></li> + </ul> + </nav> + </header> + <main id="web-install"> + <h1><a href="#web-install">Web install</a></h1> + + <button id="connect">Connect</button> + </main> + <footer> + <a href="/"><img src="/logo.png" width="512" height="512" alt=""/>GrapheneOS</a> + <ul id="social"> + <li><a href="https://twitter.com/GrapheneOS">Twitter</a></li> + <li><a href="https://github.com/GrapheneOS">GitHub</a></li> + <li><a href="https://reddit.com/r/GrapheneOS">Reddit</a></li> + <li><a href="https://www.linkedin.com/company/grapheneos/">LinkedIn</a></li> + </ul> + </footer> + </body> +</html> diff --git a/validate_static b/validate_static index bb46fc00..a54c8897 100755 --- a/validate_static +++ b/validate_static @@ -10,6 +10,6 @@ for file in static/**/*.@(json|webmanifest); do done xmllint --noout static/**/*.@(html|svg|xml) -eslint static/**/!(webadb).js +eslint static/**/!(web-install|webadb).js stylelint static/**/*.css validatornu --Werror --also-check-css --also-check-svg static/**/*.@(css|html|svg) |
