diff --git a/website/astro.config.mjs b/website/astro.config.mjs index b495713134e..324902b35e3 100644 --- a/website/astro.config.mjs +++ b/website/astro.config.mjs @@ -11,6 +11,7 @@ import { resolve } from "pathe"; import rehypeMermaid from "rehype-mermaid"; import remarkHeadingID from "remark-heading-id"; import current from "./src/content/current-sidebar"; +import { computeSriHash } from "./src/utils/sri-hash"; /** Scan the release-notes directory and return the slug of the latest release note. */ function getLatestReleaseNoteSlug() { @@ -43,6 +44,8 @@ const latestReleaseNote = getLatestReleaseNoteSlug(); const base = process.env.TYPESPEC_WEBSITE_BASE_PATH ?? "/"; +const initJsIntegrity = computeSriHash("1ds-init.js"); + // https://astro.build/config export default defineConfig({ base, @@ -98,6 +101,7 @@ export default defineConfig({ tag: "script", attrs: { src: "https://consentdeliveryfd.azurefd.net/mscc/lib/v2/wcp-consent.js", + crossorigin: "anonymous", }, }, { @@ -106,6 +110,7 @@ export default defineConfig({ type: "module", async: true, src: "1ds-init.js", + integrity: initJsIntegrity, }, }, ], diff --git a/website/src/layouts/base-layout.astro b/website/src/layouts/base-layout.astro index 4d2361eab40..4d22634c126 100644 --- a/website/src/layouts/base-layout.astro +++ b/website/src/layouts/base-layout.astro @@ -3,12 +3,15 @@ import "@site/src/css/custom.css"; import Header from "@site/src/components/header/header.astro"; import Footer from "@site/src/components/footer/footer.astro"; import { baseUrl } from "@typespec/astro-utils/utils/base-url"; +import { computeSriHash } from "@site/src/utils/sri-hash"; export interface Props { /** Whether to render the footer @default true */ footer?: boolean; } const { footer = true } = Astro.props; + +const initJsIntegrity = computeSriHash("1ds-init.js"); --- @@ -18,9 +21,12 @@ const { footer = true } = Astro.props; typespec.io - + -
diff --git a/website/src/utils/sri-hash.ts b/website/src/utils/sri-hash.ts new file mode 100644 index 00000000000..002686ab3d6 --- /dev/null +++ b/website/src/utils/sri-hash.ts @@ -0,0 +1,16 @@ +import { createHash } from "node:crypto"; +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; + +/** + * Compute a SHA-384 subresource integrity (SRI) hash for the given file, + * relative to the website `public/` directory. + * + * Uses `process.cwd()` because Astro always runs from the website root, + * and `import.meta.dirname` is unreliable after bundling during pre-render. + */ +export function computeSriHash(publicRelativePath: string): string { + const absPath = resolve(process.cwd(), "public", publicRelativePath); + const content = readFileSync(absPath); + return `sha384-${createHash("sha384").update(content).digest("base64")}`; +}