@growth-labs/conformance 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/README.md +64 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/policy.d.ts +33 -1
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +91 -5
- package/dist/policy.js.map +1 -1
- package/dist/runner.js +74 -4
- package/dist/runner.js.map +1 -1
- package/dist/schema.d.ts +326 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +75 -0
- package/dist/schema.js.map +1 -1
- package/fixtures/negative/required-negative-fixtures.json +11 -0
- package/fixtures/valid/public-article.json +1 -1
- package/package.json +12 -1
- package/src/index.ts +6 -0
- package/src/policy.ts +138 -6
- package/src/runner.ts +93 -4
- package/src/schema.ts +83 -0
package/dist/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,uBAAuB,+BAA+B,CAAA;AACnE,eAAO,MAAM,+BAA+B,6EAOlC,CAAA;AAEV,eAAO,MAAM,+BAA+B
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/schema.js
CHANGED
|
@@ -16,6 +16,7 @@ export const REQUIRED_NEGATIVE_FIXTURE_CODES = {
|
|
|
16
16
|
'csp-wildcard-default-src': 'security.csp.default_src_wildcard',
|
|
17
17
|
'csp-unsafe-eval': 'security.csp.unsafe_eval',
|
|
18
18
|
'csp-inline-executable-without-nonce-or-hash': 'security.csp.inline_executable_without_nonce_or_hash',
|
|
19
|
+
'csp-style-attr-inline-without-inventory': 'security.csp.style_attr_inline_inventory_missing',
|
|
19
20
|
'conflicting-duplicate-security-header': 'security.header.conflicting_values',
|
|
20
21
|
'missing-functional-probe-receipt': 'security.functional_probe.missing',
|
|
21
22
|
'missing-csp-report-receipt': 'security.csp_report.missing',
|
|
@@ -83,10 +84,19 @@ export const cspReportReceiptSchema = z.object({
|
|
|
83
84
|
endpoint: z.string().min(1).optional(),
|
|
84
85
|
capabilityBoundary: z.string().min(1).optional(),
|
|
85
86
|
});
|
|
87
|
+
export const inlineStyleAttributeInventorySchema = z.object({
|
|
88
|
+
commitSha: z.string().regex(/^[0-9a-f]{40}$/),
|
|
89
|
+
occurrenceCount: z.number().int().positive(),
|
|
90
|
+
evidence: z.object({
|
|
91
|
+
tool: z.string().regex(/^[a-z0-9][a-z0-9:@/._-]*$/i),
|
|
92
|
+
outputHash: z.string().regex(/^sha256:[0-9a-f]{64}$/),
|
|
93
|
+
}),
|
|
94
|
+
});
|
|
86
95
|
export const securityReceiptsSchema = z
|
|
87
96
|
.object({
|
|
88
97
|
functionalProbes: z.array(securityFunctionalProbeReceiptSchema).default([]),
|
|
89
98
|
cspReports: z.array(cspReportReceiptSchema).default([]),
|
|
99
|
+
inlineStyleAttributes: inlineStyleAttributeInventorySchema.optional(),
|
|
90
100
|
})
|
|
91
101
|
.default({ functionalProbes: [], cspReports: [] });
|
|
92
102
|
export const buildEvidenceSchema = z.object({
|
|
@@ -97,10 +107,75 @@ export const buildEvidenceSchema = z.object({
|
|
|
97
107
|
staticHeaderPolicy: z.boolean().default(false),
|
|
98
108
|
ssrHeaderPolicy: z.boolean().default(false),
|
|
99
109
|
});
|
|
110
|
+
const frameAncestorSourceSchema = z.string().superRefine((source, context) => {
|
|
111
|
+
if (source === "'none'" || source === "'self'" || source === 'https:')
|
|
112
|
+
return;
|
|
113
|
+
let parsed;
|
|
114
|
+
try {
|
|
115
|
+
parsed = new URL(source);
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
context.addIssue({
|
|
119
|
+
code: z.ZodIssueCode.custom,
|
|
120
|
+
message: "Expected 'none', 'self', https:, or an exact HTTPS origin.",
|
|
121
|
+
});
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (parsed.protocol !== 'https:' ||
|
|
125
|
+
parsed.username !== '' ||
|
|
126
|
+
parsed.password !== '' ||
|
|
127
|
+
parsed.search !== '' ||
|
|
128
|
+
parsed.hash !== '' ||
|
|
129
|
+
source !== parsed.origin) {
|
|
130
|
+
context.addIssue({
|
|
131
|
+
code: z.ZodIssueCode.custom,
|
|
132
|
+
message: "Expected 'none', 'self', https:, or an exact HTTPS origin.",
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
const framePolicySchema = z
|
|
137
|
+
.object({
|
|
138
|
+
ancestors: z
|
|
139
|
+
.array(frameAncestorSourceSchema)
|
|
140
|
+
.min(1)
|
|
141
|
+
.refine((sources) => new Set(sources).size === sources.length, {
|
|
142
|
+
message: 'Frame ancestor sources must be unique.',
|
|
143
|
+
}),
|
|
144
|
+
legacyHeader: z.enum(['DENY', 'SAMEORIGIN', 'omit']),
|
|
145
|
+
})
|
|
146
|
+
.superRefine((policy, context) => {
|
|
147
|
+
if (policy.ancestors.includes("'none'") && policy.ancestors.length !== 1) {
|
|
148
|
+
context.addIssue({
|
|
149
|
+
code: z.ZodIssueCode.custom,
|
|
150
|
+
path: ['ancestors'],
|
|
151
|
+
message: "The 'none' frame ancestor cannot be combined with other sources.",
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
if (policy.legacyHeader === 'DENY' &&
|
|
155
|
+
(policy.ancestors.length !== 1 || policy.ancestors[0] !== "'none'")) {
|
|
156
|
+
context.addIssue({
|
|
157
|
+
code: z.ZodIssueCode.custom,
|
|
158
|
+
path: ['legacyHeader'],
|
|
159
|
+
message: "DENY is compatible only with frame-ancestors 'none'.",
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
if (policy.legacyHeader === 'SAMEORIGIN' &&
|
|
163
|
+
(policy.ancestors.length !== 1 || policy.ancestors[0] !== "'self'")) {
|
|
164
|
+
context.addIssue({
|
|
165
|
+
code: z.ZodIssueCode.custom,
|
|
166
|
+
path: ['legacyHeader'],
|
|
167
|
+
message: "SAMEORIGIN is compatible only with frame-ancestors 'self'.",
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
});
|
|
100
171
|
export const conformanceExpectedSchema = z.object({
|
|
101
172
|
canonicalUrl: z.string().url().optional(),
|
|
102
173
|
schemaTypes: z.array(z.string().min(1)).default([]),
|
|
103
174
|
discoverEligible: z.boolean().default(true),
|
|
175
|
+
framePolicy: framePolicySchema.default({
|
|
176
|
+
ancestors: ["'none'"],
|
|
177
|
+
legacyHeader: 'DENY',
|
|
178
|
+
}),
|
|
104
179
|
});
|
|
105
180
|
export const conformanceFixtureSchema = z.object({
|
|
106
181
|
id: z.string().min(1),
|
package/dist/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -93,6 +93,17 @@
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
},
|
|
96
|
+
{
|
|
97
|
+
"name": "csp-style-attr-inline-without-inventory",
|
|
98
|
+
"expectedFailingCode": "security.csp.style_attr_inline_inventory_missing",
|
|
99
|
+
"patch": {
|
|
100
|
+
"response": {
|
|
101
|
+
"headers": {
|
|
102
|
+
"content-security-policy": "default-src 'self'; script-src 'self' 'nonce-fixture'; style-src 'self' 'nonce-fixture'; style-src-attr 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https:; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; upgrade-insecure-requests"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
96
107
|
{
|
|
97
108
|
"name": "conflicting-duplicate-security-header",
|
|
98
109
|
"expectedFailingCode": "security.header.conflicting_values",
|
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
"artifactId": "fixture-build-001",
|
|
122
122
|
"generatedAt": "2026-07-15T23:30:00Z",
|
|
123
123
|
"packageVersions": {
|
|
124
|
-
"@growth-labs/conformance": "0.
|
|
124
|
+
"@growth-labs/conformance": "0.3.0",
|
|
125
125
|
"@growth-labs/seo": "0.9.0"
|
|
126
126
|
},
|
|
127
127
|
"staticHeaderPolicy": true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@growth-labs/conformance",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Reusable fleet publication conformance harness for Growth Labs sites: headers, cache, metadata, structured data, images, publication surfaces, and evidence bundles.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -32,9 +32,20 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"zod": "^3.25.0"
|
|
34
34
|
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"astro": "^7.1.0"
|
|
37
|
+
},
|
|
38
|
+
"peerDependenciesMeta": {
|
|
39
|
+
"astro": {
|
|
40
|
+
"optional": true
|
|
41
|
+
}
|
|
42
|
+
},
|
|
35
43
|
"devDependencies": {
|
|
36
44
|
"@cloudflare/workers-types": "^4.20260402.1",
|
|
45
|
+
"@types/node": "^25.5.0",
|
|
46
|
+
"astro": "7.1.0",
|
|
37
47
|
"typescript": "^5.7.0",
|
|
48
|
+
"vite": "7.3.5",
|
|
38
49
|
"vitest": "^4.1.8"
|
|
39
50
|
},
|
|
40
51
|
"scripts": {
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export {
|
|
2
|
+
type AstroCspConfig,
|
|
3
|
+
type AstroCspPolicyOptions,
|
|
4
|
+
type AstroCspResource,
|
|
5
|
+
buildAstroCspConfig,
|
|
2
6
|
buildCacheControl,
|
|
3
7
|
buildContentSecurityPolicy,
|
|
4
8
|
buildSharedPublicationHeaders,
|
|
@@ -42,6 +46,8 @@ export {
|
|
|
42
46
|
type HeaderMap,
|
|
43
47
|
headerMapSchema,
|
|
44
48
|
headerValueSchema,
|
|
49
|
+
type InlineStyleAttributeInventory,
|
|
50
|
+
inlineStyleAttributeInventorySchema,
|
|
45
51
|
type PublicationSurfaceEvidence,
|
|
46
52
|
parseConformanceFixture,
|
|
47
53
|
publicationSurfaceSchema,
|
package/src/policy.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AstroConfig } from 'astro'
|
|
2
|
+
import {
|
|
3
|
+
type Audience,
|
|
4
|
+
type HeaderMap,
|
|
5
|
+
type InlineStyleAttributeInventory,
|
|
6
|
+
inlineStyleAttributeInventorySchema,
|
|
7
|
+
type RenderMode,
|
|
8
|
+
} from './schema.js'
|
|
2
9
|
|
|
3
10
|
export const REQUIRED_SECURITY_HEADERS = [
|
|
4
11
|
'content-security-policy',
|
|
@@ -32,12 +39,42 @@ export interface HeaderPolicyOptions {
|
|
|
32
39
|
nonce?: string
|
|
33
40
|
cspReportUri?: string
|
|
34
41
|
cspReportTo?: string
|
|
42
|
+
contentSecurityPolicy?: false | ContentSecurityPolicyOptions
|
|
35
43
|
strictTransportSecurity?: StrictTransportSecurityOptions
|
|
36
44
|
crossOriginOpenerPolicy?: CrossOriginOpenerPolicy
|
|
37
45
|
crossOriginResourcePolicy?: CrossOriginResourcePolicy
|
|
38
46
|
markdownTwinUrl?: string
|
|
39
47
|
}
|
|
40
48
|
|
|
49
|
+
export interface AstroCspPolicyOptions {
|
|
50
|
+
scriptSources?: readonly string[]
|
|
51
|
+
styleSources?: readonly string[]
|
|
52
|
+
inlineStyleAttributes?: InlineStyleAttributeInventory
|
|
53
|
+
imgSources?: readonly string[]
|
|
54
|
+
fontSources?: readonly string[]
|
|
55
|
+
connectSources?: readonly string[]
|
|
56
|
+
mediaSources?: readonly string[]
|
|
57
|
+
frameSources?: readonly string[]
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
type AstroNativeCspConfig = Exclude<
|
|
61
|
+
NonNullable<NonNullable<AstroConfig['security']>['csp']>,
|
|
62
|
+
boolean
|
|
63
|
+
>
|
|
64
|
+
|
|
65
|
+
type AstroCspDirective = NonNullable<AstroNativeCspConfig['directives']>[number]
|
|
66
|
+
|
|
67
|
+
export type AstroCspResource = NonNullable<
|
|
68
|
+
NonNullable<AstroNativeCspConfig['styleDirective']>['resources']
|
|
69
|
+
>[number]
|
|
70
|
+
|
|
71
|
+
export interface AstroCspConfig {
|
|
72
|
+
algorithm: 'SHA-256'
|
|
73
|
+
directives: AstroCspDirective[]
|
|
74
|
+
scriptDirective: { resources: string[] }
|
|
75
|
+
styleDirective: { resources: AstroCspResource[] }
|
|
76
|
+
}
|
|
77
|
+
|
|
41
78
|
export interface CachePolicyOptions {
|
|
42
79
|
renderMode: RenderMode
|
|
43
80
|
audience: Audience
|
|
@@ -47,11 +84,6 @@ export function buildSharedPublicationHeaders(
|
|
|
47
84
|
options: HeaderPolicyOptions,
|
|
48
85
|
): Record<string, string> {
|
|
49
86
|
const headers: Record<string, string> = {
|
|
50
|
-
'Content-Security-Policy': buildContentSecurityPolicy({
|
|
51
|
-
nonce: options.nonce,
|
|
52
|
-
reportUri: options.cspReportUri,
|
|
53
|
-
reportTo: options.cspReportTo,
|
|
54
|
-
}),
|
|
55
87
|
'Strict-Transport-Security': buildStrictTransportSecurity(options.strictTransportSecurity),
|
|
56
88
|
'Cross-Origin-Opener-Policy': options.crossOriginOpenerPolicy ?? 'same-origin',
|
|
57
89
|
'Cross-Origin-Resource-Policy': options.crossOriginResourcePolicy ?? 'same-origin',
|
|
@@ -62,6 +94,15 @@ export function buildSharedPublicationHeaders(
|
|
|
62
94
|
'accelerometer=(), camera=(), geolocation=(), gyroscope=(), microphone=(), payment=(), usb=()',
|
|
63
95
|
'Cache-Control': buildCacheControl(options),
|
|
64
96
|
}
|
|
97
|
+
if (options.contentSecurityPolicy !== false) {
|
|
98
|
+
headers['Content-Security-Policy'] = buildContentSecurityPolicy(
|
|
99
|
+
options.contentSecurityPolicy ?? {
|
|
100
|
+
nonce: options.nonce,
|
|
101
|
+
reportUri: options.cspReportUri,
|
|
102
|
+
reportTo: options.cspReportTo,
|
|
103
|
+
},
|
|
104
|
+
)
|
|
105
|
+
}
|
|
65
106
|
|
|
66
107
|
if (options.markdownTwinUrl) {
|
|
67
108
|
headers.Link = `<${options.markdownTwinUrl}>; rel="alternate"; type="text/markdown"`
|
|
@@ -70,6 +111,97 @@ export function buildSharedPublicationHeaders(
|
|
|
70
111
|
return headers
|
|
71
112
|
}
|
|
72
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Build framework-owned CSP configuration for Astro 7.1+.
|
|
116
|
+
* Astro hashes every script and style it emits, while this helper keeps the
|
|
117
|
+
* consumer's external source inventory exact and fail-closed.
|
|
118
|
+
*/
|
|
119
|
+
export function buildAstroCspConfig(options: AstroCspPolicyOptions = {}): AstroCspConfig {
|
|
120
|
+
const inlineStyleAttributes = options.inlineStyleAttributes
|
|
121
|
+
? inlineStyleAttributeInventorySchema.parse(options.inlineStyleAttributes)
|
|
122
|
+
: undefined
|
|
123
|
+
const scriptSources = exactCspSources(options.scriptSources)
|
|
124
|
+
const styleSources = exactCspSources(options.styleSources)
|
|
125
|
+
const imgSources = exactCspSources(options.imgSources)
|
|
126
|
+
const fontSources = exactCspSources(options.fontSources)
|
|
127
|
+
const connectSources = exactCspSources(options.connectSources)
|
|
128
|
+
const mediaSources = exactCspSources(options.mediaSources)
|
|
129
|
+
const frameSources = exactCspSources(options.frameSources)
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
algorithm: 'SHA-256',
|
|
133
|
+
directives: [
|
|
134
|
+
"default-src 'self'",
|
|
135
|
+
cspDirective('img-src', ["'self'", 'data:', 'blob:', ...imgSources]),
|
|
136
|
+
cspDirective('font-src', ["'self'", 'data:', ...fontSources]),
|
|
137
|
+
cspDirective('connect-src', ["'self'", ...connectSources]),
|
|
138
|
+
cspDirective('media-src', ["'self'", 'blob:', ...mediaSources]),
|
|
139
|
+
cspDirective('frame-src', ["'self'", ...frameSources]),
|
|
140
|
+
"object-src 'none'",
|
|
141
|
+
"base-uri 'self'",
|
|
142
|
+
"frame-ancestors 'none'",
|
|
143
|
+
"form-action 'self'",
|
|
144
|
+
'upgrade-insecure-requests',
|
|
145
|
+
],
|
|
146
|
+
scriptDirective: {
|
|
147
|
+
resources: uniqueCspSources(["'self'", ...scriptSources]),
|
|
148
|
+
},
|
|
149
|
+
styleDirective: {
|
|
150
|
+
resources: inlineStyleAttributes
|
|
151
|
+
? [
|
|
152
|
+
...uniqueCspSources(["'self'", ...styleSources]).map((resource) => ({
|
|
153
|
+
resource,
|
|
154
|
+
kind: 'element' as const,
|
|
155
|
+
})),
|
|
156
|
+
{ resource: "'unsafe-inline'", kind: 'attribute' as const },
|
|
157
|
+
]
|
|
158
|
+
: uniqueCspSources(["'self'", ...styleSources]),
|
|
159
|
+
},
|
|
160
|
+
} satisfies AstroNativeCspConfig
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function uniqueCspSources(sources: readonly string[]): string[] {
|
|
164
|
+
return [...new Set(sources)]
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function cspDirective(name: string, sources: readonly string[]): AstroCspDirective {
|
|
168
|
+
return `${name} ${[...new Set(sources)].join(' ')}` as AstroCspDirective
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function exactCspSources(sources: readonly string[] | undefined): string[] {
|
|
172
|
+
return [...new Set(sources ?? [])].map((source) => {
|
|
173
|
+
const normalized = source.trim()
|
|
174
|
+
if (normalized === "'self'") return normalized
|
|
175
|
+
if (
|
|
176
|
+
normalized === '' ||
|
|
177
|
+
normalized.includes('*') ||
|
|
178
|
+
normalized === 'https:' ||
|
|
179
|
+
normalized === 'http:' ||
|
|
180
|
+
normalized.startsWith("'unsafe-")
|
|
181
|
+
) {
|
|
182
|
+
throw new Error(`Astro CSP sources must be exact and cannot use ${source}`)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
let parsed: URL
|
|
186
|
+
try {
|
|
187
|
+
parsed = new URL(normalized)
|
|
188
|
+
} catch {
|
|
189
|
+
throw new Error(`Astro CSP sources must be exact HTTPS/WSS origins: ${source}`)
|
|
190
|
+
}
|
|
191
|
+
if (
|
|
192
|
+
(parsed.protocol !== 'https:' && parsed.protocol !== 'wss:') ||
|
|
193
|
+
parsed.username !== '' ||
|
|
194
|
+
parsed.password !== '' ||
|
|
195
|
+
parsed.search !== '' ||
|
|
196
|
+
parsed.hash !== '' ||
|
|
197
|
+
(parsed.pathname !== '' && parsed.pathname !== '/')
|
|
198
|
+
) {
|
|
199
|
+
throw new Error(`Astro CSP sources must be exact HTTPS/WSS origins: ${source}`)
|
|
200
|
+
}
|
|
201
|
+
return parsed.origin
|
|
202
|
+
})
|
|
203
|
+
}
|
|
204
|
+
|
|
73
205
|
export function buildContentSecurityPolicy(input?: string | ContentSecurityPolicyOptions): string {
|
|
74
206
|
const options = typeof input === 'string' ? { nonce: input } : (input ?? {})
|
|
75
207
|
const scriptSources = ["'self'"]
|
package/src/runner.ts
CHANGED
|
@@ -113,7 +113,10 @@ function checkSecurityHeaders(fixture: ConformanceFixture, html: string): Confor
|
|
|
113
113
|
const headerEntries = collectHeaders(fixture.response.headers)
|
|
114
114
|
const headers = normalizeHeaders(fixture.response.headers)
|
|
115
115
|
const findings: ConformanceFinding[] = []
|
|
116
|
-
const
|
|
116
|
+
const requiredSecurityHeaders = REQUIRED_SECURITY_HEADERS.filter(
|
|
117
|
+
(name) => name !== 'x-frame-options' || fixture.expected.framePolicy.legacyHeader !== 'omit',
|
|
118
|
+
)
|
|
119
|
+
const missingSecurityHeaders = requiredSecurityHeaders.filter((name) => {
|
|
117
120
|
const values = headerEntries[name] ?? []
|
|
118
121
|
return !values.some((value) => value.trim().length > 0)
|
|
119
122
|
})
|
|
@@ -161,7 +164,33 @@ function checkSecurityHeaders(fixture: ConformanceFixture, html: string): Confor
|
|
|
161
164
|
}
|
|
162
165
|
|
|
163
166
|
const csp = headers['content-security-policy']
|
|
164
|
-
if (csp) findings.push(...validateContentSecurityPolicy(csp, html))
|
|
167
|
+
if (csp) findings.push(...validateContentSecurityPolicy(csp, html, fixture))
|
|
168
|
+
|
|
169
|
+
const xFrameOptions = headers['x-frame-options']
|
|
170
|
+
const expectedLegacyFrameHeader = fixture.expected.framePolicy.legacyHeader
|
|
171
|
+
if (expectedLegacyFrameHeader === 'omit' && xFrameOptions) {
|
|
172
|
+
findings.push({
|
|
173
|
+
code: 'security.frame_legacy_conflict',
|
|
174
|
+
severity: 'error',
|
|
175
|
+
message: 'X-Frame-Options conflicts with the declared embeddable frame-ancestors policy.',
|
|
176
|
+
path: 'response.headers.x-frame-options',
|
|
177
|
+
evidence: xFrameOptions,
|
|
178
|
+
remediation:
|
|
179
|
+
'Omit the legacy header only on the explicitly declared embeddable route and retain the exact CSP frame-ancestors directive.',
|
|
180
|
+
})
|
|
181
|
+
} else if (
|
|
182
|
+
expectedLegacyFrameHeader !== 'omit' &&
|
|
183
|
+
xFrameOptions &&
|
|
184
|
+
xFrameOptions.toUpperCase() !== expectedLegacyFrameHeader
|
|
185
|
+
) {
|
|
186
|
+
findings.push({
|
|
187
|
+
code: 'security.header.invalid',
|
|
188
|
+
severity: 'error',
|
|
189
|
+
message: `X-Frame-Options must be ${expectedLegacyFrameHeader} for this response class.`,
|
|
190
|
+
path: 'response.headers.x-frame-options',
|
|
191
|
+
evidence: xFrameOptions,
|
|
192
|
+
})
|
|
193
|
+
}
|
|
165
194
|
|
|
166
195
|
const coop = headers['cross-origin-opener-policy']
|
|
167
196
|
if (coop && !VALID_COOP_VALUES.has(coop.toLowerCase())) {
|
|
@@ -387,10 +416,37 @@ interface InlineExecutableScript {
|
|
|
387
416
|
path: string
|
|
388
417
|
}
|
|
389
418
|
|
|
390
|
-
function validateContentSecurityPolicy(
|
|
419
|
+
function validateContentSecurityPolicy(
|
|
420
|
+
csp: string,
|
|
421
|
+
html: string,
|
|
422
|
+
fixture: ConformanceFixture,
|
|
423
|
+
): ConformanceFinding[] {
|
|
391
424
|
const findings: ConformanceFinding[] = []
|
|
392
425
|
const { directives, findings: parseFindings } = parseContentSecurityPolicy(csp)
|
|
393
426
|
findings.push(...parseFindings)
|
|
427
|
+
const frameAncestors = directives.get('frame-ancestors')
|
|
428
|
+
const expectedFrameAncestors = fixture.expected.framePolicy.ancestors
|
|
429
|
+
if (!frameAncestors) {
|
|
430
|
+
findings.push({
|
|
431
|
+
code: 'security.csp.frame_ancestors_missing',
|
|
432
|
+
severity: 'error',
|
|
433
|
+
message: 'Content-Security-Policy must declare frame-ancestors.',
|
|
434
|
+
path: 'response.headers.content-security-policy.frame-ancestors',
|
|
435
|
+
})
|
|
436
|
+
} else if (
|
|
437
|
+
normalizeCspSources(frameAncestors.sources) !== normalizeCspSources(expectedFrameAncestors)
|
|
438
|
+
) {
|
|
439
|
+
findings.push({
|
|
440
|
+
code: 'security.csp.frame_ancestors_mismatch',
|
|
441
|
+
severity: 'error',
|
|
442
|
+
message:
|
|
443
|
+
'Content-Security-Policy frame-ancestors does not match the declared response class.',
|
|
444
|
+
path: 'response.headers.content-security-policy.frame-ancestors',
|
|
445
|
+
evidence: frameAncestors.raw,
|
|
446
|
+
remediation:
|
|
447
|
+
'Emit only the exact declared frame ancestors and keep embeddable routes explicitly bounded.',
|
|
448
|
+
})
|
|
449
|
+
}
|
|
394
450
|
|
|
395
451
|
const defaultSources = lowerSources(directives.get('default-src')?.sources ?? [])
|
|
396
452
|
if (defaultSources.includes('*')) {
|
|
@@ -425,6 +481,39 @@ function validateContentSecurityPolicy(csp: string, html: string): ConformanceFi
|
|
|
425
481
|
const directive = directives.get(directiveName)
|
|
426
482
|
if (!directive) continue
|
|
427
483
|
if (lowerSources(directive.sources).includes("'unsafe-inline'")) {
|
|
484
|
+
if (directiveName === 'style-src-attr') {
|
|
485
|
+
const inventory = fixture.securityReceipts.inlineStyleAttributes
|
|
486
|
+
if (!inventory) {
|
|
487
|
+
findings.push({
|
|
488
|
+
code: 'security.csp.style_attr_inline_inventory_missing',
|
|
489
|
+
severity: 'error',
|
|
490
|
+
message:
|
|
491
|
+
"style-src-attr 'unsafe-inline' requires a commit-bound inline-style-attribute inventory receipt.",
|
|
492
|
+
path: 'securityReceipts.inlineStyleAttributes',
|
|
493
|
+
evidence: directive.raw,
|
|
494
|
+
remediation:
|
|
495
|
+
'Remove the allowance or attach the exact consumer commit SHA, positive occurrence count, and scan evidence.',
|
|
496
|
+
})
|
|
497
|
+
continue
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
if (
|
|
501
|
+
!fixture.buildEvidence?.commitSha ||
|
|
502
|
+
fixture.buildEvidence.commitSha !== inventory.commitSha
|
|
503
|
+
) {
|
|
504
|
+
findings.push({
|
|
505
|
+
code: 'security.csp.style_attr_inline_inventory_stale',
|
|
506
|
+
severity: 'error',
|
|
507
|
+
message:
|
|
508
|
+
'The inline-style-attribute inventory must match the exact commit in build evidence.',
|
|
509
|
+
path: 'securityReceipts.inlineStyleAttributes.commitSha',
|
|
510
|
+
evidence: `inventory=${inventory.commitSha}; build=${fixture.buildEvidence?.commitSha ?? 'missing'}`,
|
|
511
|
+
remediation:
|
|
512
|
+
'Rescan the exact build commit before retaining the style attribute allowance.',
|
|
513
|
+
})
|
|
514
|
+
}
|
|
515
|
+
continue
|
|
516
|
+
}
|
|
428
517
|
findings.push({
|
|
429
518
|
code: 'security.csp.unsafe_inline',
|
|
430
519
|
severity: 'error',
|
|
@@ -535,7 +624,7 @@ function inlineExecutableScriptAllowed(script: InlineExecutableScript, sources:
|
|
|
535
624
|
}
|
|
536
625
|
|
|
537
626
|
function hashSourceMatchesInlineScript(source: string, content: string): boolean {
|
|
538
|
-
const match = /^'(sha256|sha384|sha512)-([^']+)'
|
|
627
|
+
const match = /^'(sha256|sha384|sha512)-([^']+)'$/.exec(source)
|
|
539
628
|
if (!match) return false
|
|
540
629
|
const algorithm = match[1]?.toLowerCase()
|
|
541
630
|
const expected = match[2]
|