Subresource integrity ftw!
This commit is contained in:
parent
b1936c31af
commit
5ee34ce082
3 changed files with 44 additions and 8 deletions
|
@ -1,5 +1,3 @@
|
||||||
import __INDEX__ from "./index.html";
|
|
||||||
|
|
||||||
import make_router from './js/routes_client.mjs';
|
import make_router from './js/routes_client.mjs';
|
||||||
|
|
||||||
window.addEventListener("load", (_event) => {
|
window.addEventListener("load", (_event) => {
|
||||||
|
|
|
@ -1,21 +1,45 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import crypto from 'crypto';
|
||||||
|
|
||||||
import esbuild from 'esbuild';
|
import esbuild from 'esbuild';
|
||||||
|
|
||||||
const __dirname = import.meta.url.slice(7, import.meta.url.lastIndexOf("/"));
|
const __dirname = import.meta.url.slice(7, import.meta.url.lastIndexOf("/"));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hashes the contents of a file.
|
||||||
|
* @ref https://stackoverflow.com/a/44643479/1460422
|
||||||
|
* @param {string} hashName The name of the hash algorithm to use.
|
||||||
|
* @param {string} path The path to the file to hash.
|
||||||
|
* @return {string} The resulting hash as a hexadecimal string.
|
||||||
|
*/
|
||||||
|
function hash_file(hashName, path) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const hash = crypto.createHash(hashName);
|
||||||
|
const stream = fs.createReadStream(path);
|
||||||
|
stream.once("error", reject);
|
||||||
|
stream.on("data", chunk => hash.update(chunk));
|
||||||
|
stream.once("end", () => {
|
||||||
|
stream.off("error", reject);
|
||||||
|
resolve(hash.digest('base64'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
const outdir = path.resolve(__dirname, "../static-dist");
|
||||||
|
|
||||||
const result = await esbuild.build({
|
const result = await esbuild.build({
|
||||||
entryPoints: [
|
entryPoints: [
|
||||||
"./app.mjs",
|
"./app.mjs",
|
||||||
"./app.css"
|
"./app.css"
|
||||||
].map(filepath => path.resolve(__dirname, filepath)),
|
].map(filepath => path.resolve(__dirname, filepath)),
|
||||||
outdir: path.resolve(__dirname, "../static-dist"),
|
outdir,
|
||||||
bundle: true,
|
bundle: true,
|
||||||
minify: true,
|
minify: true,
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
|
@ -28,9 +52,23 @@ const __dirname = import.meta.url.slice(7, import.meta.url.lastIndexOf("/"));
|
||||||
".ttf": "file"
|
".ttf": "file"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if(result.errors.length > 0 || result.warnings.length > 0)
|
||||||
console.log(result);
|
console.log(result);
|
||||||
|
|
||||||
|
// We *would* use SHA3 here, but we need to use SHA2 for subresource integrity
|
||||||
|
let algorithm = "sha256";
|
||||||
|
let css_hash = await hash_file(algorithm, path.join(outdir, "app.css"));
|
||||||
|
let js_hash = await hash_file(algorithm, path.join(outdir, "app.js"));
|
||||||
|
|
||||||
|
let html = (await fs.promises.readFile(path.join(__dirname, "index.html"), "utf-8"))
|
||||||
|
.replace(/\{JS_HASH\}/g, js_hash)
|
||||||
|
.replace(/\{CSS_HASH\}/g, css_hash)
|
||||||
|
.replace(/\{JS_HASH_SHORT\}/g, js_hash.substring(0, 7).replace(/[+/=]/, ""))
|
||||||
|
.replace(/\{CSS_HASH_SHORT\}/g, css_hash.substring(0, 7).replace(/[+/=]/, ""))
|
||||||
|
.replace(/\{ALGO\}/g, algorithm);
|
||||||
// TODO: Use fs.promises.copyFile() for index.html here, and also maybe find & replace for css/js filenames that we can then randomise?
|
// TODO: Use fs.promises.copyFile() for index.html here, and also maybe find & replace for css/js filenames that we can then randomise?
|
||||||
|
|
||||||
|
await fs.promises.writeFile(path.join(outdir, "index.html"), html);
|
||||||
|
|
||||||
// console.log(await esbuild.analyzeMetafile(result.metafile));
|
// console.log(await esbuild.analyzeMetafile(result.metafile));
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<!---------------->
|
<!---------------->
|
||||||
<link rel="stylesheet" href="/static/app.css" />
|
<link rel="stylesheet" href="/static/app.css?hash={CSS_HASH_SHORT}" integrity="{ALGO}-{CSS_HASH}" />
|
||||||
<script src="/static/app.js" charset="utf-8"></script>
|
<script src="/static/app.js?hash={JS_HASH_SHORT}" integrity="{ALGO}-{JS_HASH}" charset="utf-8"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Loading…
Reference in a new issue