Skip to content

Commit 83b5bf3

Browse files
Copilotmarkcowl
andauthored
feat(website): add integrity attributes and crossorigin to scripts (#10176)
Computes the SRI integrity hash for `1ds-init.js` dynamically at build time using `node:crypto` and adds `crossorigin="anonymous"` to the consent script. The hash computation is factored into a shared helper used by both layout contexts. **Changes:** - `website/src/utils/sri-hash.ts`: New shared `computeSriHash` helper that computes SHA-384 SRI hashes for files in the `public/` directory - `website/src/layouts/base-layout.astro`: Uses `computeSriHash` to set the SRI integrity hash for `1ds-init.js` at build time; adds `crossorigin` attribute to consent script - `website/astro.config.mjs`: Uses `computeSriHash` to set the SRI integrity hash for `1ds-init.js` at build time for Starlight pages; adds `crossorigin` attribute to consent script <!-- START COPILOT CODING AGENT TIPS --> --- ⌨️ Start Copilot coding agent tasks without leaving your editor — available in [VS Code](https://gh.io/cca-vs-code-docs), [Visual Studio](https://gh.io/cca-visual-studio-docs), [JetBrains IDEs](https://gh.io/cca-jetbrains-docs) and [Eclipse](https://gh.io/cca-eclipse-docs). --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com>
1 parent 1ff1962 commit 83b5bf3

3 files changed

Lines changed: 29 additions & 2 deletions

File tree

website/astro.config.mjs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { resolve } from "pathe";
1111
import rehypeMermaid from "rehype-mermaid";
1212
import remarkHeadingID from "remark-heading-id";
1313
import current from "./src/content/current-sidebar";
14+
import { computeSriHash } from "./src/utils/sri-hash";
1415

1516
/** Scan the release-notes directory and return the slug of the latest release note. */
1617
function getLatestReleaseNoteSlug() {
@@ -43,6 +44,8 @@ const latestReleaseNote = getLatestReleaseNoteSlug();
4344

4445
const base = process.env.TYPESPEC_WEBSITE_BASE_PATH ?? "/";
4546

47+
const initJsIntegrity = computeSriHash("1ds-init.js");
48+
4649
// https://astro.build/config
4750
export default defineConfig({
4851
base,
@@ -98,6 +101,7 @@ export default defineConfig({
98101
tag: "script",
99102
attrs: {
100103
src: "https://consentdeliveryfd.azurefd.net/mscc/lib/v2/wcp-consent.js",
104+
crossorigin: "anonymous",
101105
},
102106
},
103107
{
@@ -106,6 +110,7 @@ export default defineConfig({
106110
type: "module",
107111
async: true,
108112
src: "1ds-init.js",
113+
integrity: initJsIntegrity,
109114
},
110115
},
111116
],

website/src/layouts/base-layout.astro

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@ import "@site/src/css/custom.css";
33
import Header from "@site/src/components/header/header.astro";
44
import Footer from "@site/src/components/footer/footer.astro";
55
import { baseUrl } from "@typespec/astro-utils/utils/base-url";
6+
import { computeSriHash } from "@site/src/utils/sri-hash";
67
78
export interface Props {
89
/** Whether to render the footer @default true */
910
footer?: boolean;
1011
}
1112
const { footer = true } = Astro.props;
13+
14+
const initJsIntegrity = computeSriHash("1ds-init.js");
1215
---
1316

1417
<html lang="en">
@@ -18,9 +21,12 @@ const { footer = true } = Astro.props;
1821
<link rel="og:image" type="image/svg+xml" href={baseUrl("/img/social.svg")} />
1922
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
2023
<title>typespec.io</title>
21-
<script src="https://consentdeliveryfd.azurefd.net/mscc/lib/v2/wcp-consent.js" is:inline
24+
<script
25+
src="https://consentdeliveryfd.azurefd.net/mscc/lib/v2/wcp-consent.js"
26+
crossorigin="anonymous"
27+
is:inline></script>
28+
<script src={import.meta.env.BASE_URL + "1ds-init.js"} integrity={initJsIntegrity} is:inline
2229
></script>
23-
<script src={import.meta.env.BASE_URL + "1ds-init.js"} is:inline></script>
2430
</head>
2531
<body class="body">
2632
<header class="header">

website/src/utils/sri-hash.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { createHash } from "node:crypto";
2+
import { readFileSync } from "node:fs";
3+
import { resolve } from "node:path";
4+
5+
/**
6+
* Compute a SHA-384 subresource integrity (SRI) hash for the given file,
7+
* relative to the website `public/` directory.
8+
*
9+
* Uses `process.cwd()` because Astro always runs from the website root,
10+
* and `import.meta.dirname` is unreliable after bundling during pre-render.
11+
*/
12+
export function computeSriHash(publicRelativePath: string): string {
13+
const absPath = resolve(process.cwd(), "public", publicRelativePath);
14+
const content = readFileSync(absPath);
15+
return `sha384-${createHash("sha384").update(content).digest("base64")}`;
16+
}

0 commit comments

Comments
 (0)