Skip to content

Commit d899e3c

Browse files
committed
fix: treat index.html as special case for netlify
Signed-off-by: Andres Correa Casablanca <andreu@kindspells.dev>
1 parent de63115 commit d899e3c

File tree

3 files changed

+83
-4
lines changed

3 files changed

+83
-4
lines changed

@kindspells/astro-shield/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@kindspells/astro-shield",
3-
"version": "1.5.1",
3+
"version": "1.5.2",
44
"description": "Astro integration to enhance your website's security with SubResource Integrity hashes, Content-Security-Policy headers, and other techniques.",
55
"private": false,
66
"type": "module",

@kindspells/astro-shield/src/netlify.mts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { readFile, writeFile } from 'node:fs/promises'
33
import type {
44
CSPDirectives,
55
HashesCollection,
6+
PerPageHashes,
67
SecurityHeadersOptions,
78
} from './types.mts'
89
import { serialiseCspDirectives, setSrcDirective } from './headers.mts'
@@ -251,9 +252,16 @@ export const buildNetlifyHeadersConfig = (
251252
entries: [],
252253
}
253254

254-
for (const [page, hashes] of Array.from(
255-
resourceHashes.perPageSriHashes,
256-
).sort()) {
255+
const pagesToIterate: [string, PerPageHashes][] = []
256+
for (const [page, hashes] of resourceHashes.perPageSriHashes) {
257+
if (page === 'index.html' || page.endsWith('/index.html')) {
258+
pagesToIterate.push([page.slice(0, -10), hashes])
259+
}
260+
pagesToIterate.push([page, hashes])
261+
}
262+
pagesToIterate.sort()
263+
264+
for (const [page, hashes] of pagesToIterate) {
257265
const pathEntries: (HeaderEntry | CommentEntry)[] = []
258266

259267
if (securityHeadersOptions.contentSecurityPolicy !== undefined) {

@kindspells/astro-shield/src/tests/netlify.test.mts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,77 @@ describe('buildNetlifyHeadersConfig', () => {
235235
],
236236
} satisfies NetlifyHeadersRawConfig)
237237
})
238+
239+
it('creates a "double entry" for "index.html" files', () => {
240+
const config = buildNetlifyHeadersConfig(
241+
{ contentSecurityPolicy: {} },
242+
{
243+
perPageSriHashes: new Map([
244+
[
245+
'index.html',
246+
{
247+
scripts: new Set([
248+
'sha256-071spvYLMvnwaR0H7M2dfK0enB0cGtydTbgJkdoWq7c=',
249+
]),
250+
styles: new Set(),
251+
},
252+
],
253+
[
254+
'es/index.html',
255+
{
256+
scripts: new Set([
257+
'sha256-071spvYLMvnwaR0H7M2dfK0enB0cGtydTbgJkdoWq7c=',
258+
]),
259+
styles: new Set(),
260+
},
261+
],
262+
[
263+
'fakeindex.html',
264+
{
265+
scripts: new Set([
266+
'sha256-071spvYLMvnwaR0H7M2dfK0enB0cGtydTbgJkdoWq7c=',
267+
]),
268+
styles: new Set(),
269+
},
270+
],
271+
]),
272+
},
273+
)
274+
275+
const testEntries = [
276+
{
277+
headerName: 'content-security-policy',
278+
value:
279+
"script-src 'self' 'sha256-071spvYLMvnwaR0H7M2dfK0enB0cGtydTbgJkdoWq7c='; style-src 'none'",
280+
},
281+
]
282+
283+
expect(config).toEqual({
284+
indentWith: '\t',
285+
entries: [
286+
{
287+
path: '/',
288+
entries: testEntries,
289+
},
290+
{
291+
path: '/es/',
292+
entries: testEntries,
293+
},
294+
{
295+
path: '/es/index.html',
296+
entries: testEntries,
297+
},
298+
{
299+
path: '/fakeindex.html',
300+
entries: testEntries,
301+
},
302+
{
303+
path: '/index.html',
304+
entries: testEntries,
305+
},
306+
],
307+
} satisfies NetlifyHeadersRawConfig)
308+
})
238309
})
239310

240311
describe('mergeNetlifyHeadersConfig', () => {

0 commit comments

Comments
 (0)