mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-08-04 14:57:42 +00:00
fix: replace frame-ancestors instead of merging it
Merging the configured value into the default turned a deliberate CSP_FRAME_ANCESTORS='none' into `frame-ancestors 'self' 'none'`, which browsers resolve back to 'self'. Also bail out if the serialized policy somehow lacks the nonce slot rather than emitting a header the shell cannot match.
This commit is contained in:
parent
05f3a85191
commit
4d5f577e83
2 changed files with 25 additions and 9 deletions
|
|
@ -93,6 +93,13 @@ describe('policy directives', () => {
|
|||
expect(header).toContain("frame-ancestors 'self' https://portal.example.com");
|
||||
});
|
||||
|
||||
it("replaces rather than merges frame-ancestors, so 'none' is not diluted by 'self'", () => {
|
||||
const header = headerFor({ CSP_FRAME_ANCESTORS: "'none'" });
|
||||
|
||||
expect(header).toContain("frame-ancestors 'none'");
|
||||
expect(header).not.toContain("frame-ancestors 'self'");
|
||||
});
|
||||
|
||||
it('appends additional directives and skips malformed ones', () => {
|
||||
const header = serializeCspDirectives(
|
||||
buildCspDirectives({
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ function scriptSources(scriptExtras: string[]): string[] {
|
|||
* `'unsafe-inline'`, which would block every `<style>` element injected at runtime by
|
||||
* the app shell and by third-party components that cannot know our nonce.
|
||||
*/
|
||||
function defaultDirectives(scriptExtras: string[]): CspDirective[] {
|
||||
function defaultDirectives(scriptExtras: string[], frameAncestors: string[]): CspDirective[] {
|
||||
return [
|
||||
['default-src', ["'self'"]],
|
||||
['base-uri', ["'self'"]],
|
||||
|
|
@ -92,7 +92,9 @@ function defaultDirectives(scriptExtras: string[]): CspDirective[] {
|
|||
['worker-src', ["'self'", 'blob:']],
|
||||
['manifest-src', ["'self'"]],
|
||||
['form-action', ["'self'", 'https:']],
|
||||
['frame-ancestors', ["'self'"]],
|
||||
/* Replaced wholesale, not appended: merging would turn a deliberate
|
||||
* `'none'` into `'self' 'none'`, which browsers resolve back to `'self'`. */
|
||||
['frame-ancestors', frameAncestors],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -144,7 +146,11 @@ function mergeDirectives(directives: CspDirective[]): CspDirective[] {
|
|||
|
||||
export function buildCspDirectives(env: NodeJS.ProcessEnv = process.env): CspDirective[] {
|
||||
const scriptExtras = splitSourceList(env.CSP_SCRIPT_SRC_EXTRA);
|
||||
const directives = defaultDirectives(scriptExtras);
|
||||
const frameAncestors = splitSourceList(env.CSP_FRAME_ANCESTORS);
|
||||
const directives = defaultDirectives(
|
||||
scriptExtras,
|
||||
frameAncestors.length > 0 ? frameAncestors : ["'self'"],
|
||||
);
|
||||
|
||||
for (const [directive, envName] of Object.entries(SOURCE_EXTRA_ENV)) {
|
||||
const extraSources = splitSourceList(env[envName]);
|
||||
|
|
@ -153,11 +159,6 @@ export function buildCspDirectives(env: NodeJS.ProcessEnv = process.env): CspDir
|
|||
}
|
||||
}
|
||||
|
||||
const frameAncestors = splitSourceList(env.CSP_FRAME_ANCESTORS);
|
||||
if (frameAncestors.length > 0) {
|
||||
directives.push(['frame-ancestors', frameAncestors]);
|
||||
}
|
||||
|
||||
const reportUri = env.CSP_REPORT_URI?.trim();
|
||||
if (reportUri) {
|
||||
directives.push(['report-uri', [reportUri]]);
|
||||
|
|
@ -184,7 +185,15 @@ export function createCspPolicy(env: NodeJS.ProcessEnv = process.env): CspPolicy
|
|||
return null;
|
||||
}
|
||||
|
||||
const [prefix, suffix] = serializeCspDirectives(buildCspDirectives(env)).split(NONCE_SLOT);
|
||||
const serialized = serializeCspDirectives(buildCspDirectives(env));
|
||||
const [prefix, suffix] = serialized.split(NONCE_SLOT);
|
||||
if (suffix == null) {
|
||||
logger.error(
|
||||
'[CSP] Policy has no nonce slot; refusing to send a policy the shell cannot match.',
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
const reportOnly = isReportOnly(env);
|
||||
logger.info(
|
||||
`[CSP] Content Security Policy enabled in ${reportOnly ? 'report-only' : 'enforcing'} mode.`,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue