🌩️ feat: Strict CloudFront signed cookie enforcement via requireSignedAccess#13078
Conversation
…cess Introduces cloudfront.requireSignedAccess (default false). When enabled, initializeCloudFront requires both CLOUDFRONT_KEY_PAIR_ID and CLOUDFRONT_PRIVATE_KEY, rejects the unimplemented imageSigning="url" mode, and initializeFileStorage throws to block startup on any CloudFront init failure. OSS path is unchanged: missing keys still log-and-continue when requireSignedAccess is false. Adds low-noise startup and cookie-issuance logs without leaking signed URLs, policies, signatures, private keys, or cookie values.
…ookies" Previously requireSignedAccess=true was accepted with imageSigning="none" or "url", but setCloudFrontCookies() only runs for "cookies" — leaving strict mode toothless: CloudFront stayed publicly accessible, or image delivery broke on a distribution that actually requires signed access. Adds a Zod refinement plus a runtime guard in initializeCloudFront so the only currently-functional strict configuration is imageSigning "cookies". Signed URL mode can lift this restriction once implemented.
|
@codex review |
|
@upman please resolve failing typescript checks |
|
Codex Review: Didn't find any major issues. 🎉 ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@codex review |
|
Codex Review: Didn't find any major issues. Keep them coming! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@codex review |
|
Codex Review: Didn't find any major issues. Bravo. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
requireSignedAccess
…edAccess` (danny-avila#13078) * feat(cloudfront): add requireSignedAccess to enforce strict signed access Introduces cloudfront.requireSignedAccess (default false). When enabled, initializeCloudFront requires both CLOUDFRONT_KEY_PAIR_ID and CLOUDFRONT_PRIVATE_KEY, rejects the unimplemented imageSigning="url" mode, and initializeFileStorage throws to block startup on any CloudFront init failure. OSS path is unchanged: missing keys still log-and-continue when requireSignedAccess is false. Adds low-noise startup and cookie-issuance logs without leaking signed URLs, policies, signatures, private keys, or cookie values. * fix(cloudfront): reject requireSignedAccess unless imageSigning is "cookies" Previously requireSignedAccess=true was accepted with imageSigning="none" or "url", but setCloudFrontCookies() only runs for "cookies" — leaving strict mode toothless: CloudFront stayed publicly accessible, or image delivery broke on a distribution that actually requires signed access. Adds a Zod refinement plus a runtime guard in initializeCloudFront so the only currently-functional strict configuration is imageSigning "cookies". Signed URL mode can lift this restriction once implemented. * fix(cloudfront): resolve strict access type checks * chore(cloudfront): reduce strict startup log noise --------- Co-authored-by: Danny Avila <danny@librechat.ai>
…edAccess` (danny-avila#13078) * feat(cloudfront): add requireSignedAccess to enforce strict signed access Introduces cloudfront.requireSignedAccess (default false). When enabled, initializeCloudFront requires both CLOUDFRONT_KEY_PAIR_ID and CLOUDFRONT_PRIVATE_KEY, rejects the unimplemented imageSigning="url" mode, and initializeFileStorage throws to block startup on any CloudFront init failure. OSS path is unchanged: missing keys still log-and-continue when requireSignedAccess is false. Adds low-noise startup and cookie-issuance logs without leaking signed URLs, policies, signatures, private keys, or cookie values. * fix(cloudfront): reject requireSignedAccess unless imageSigning is "cookies" Previously requireSignedAccess=true was accepted with imageSigning="none" or "url", but setCloudFrontCookies() only runs for "cookies" — leaving strict mode toothless: CloudFront stayed publicly accessible, or image delivery broke on a distribution that actually requires signed access. Adds a Zod refinement plus a runtime guard in initializeCloudFront so the only currently-functional strict configuration is imageSigning "cookies". Signed URL mode can lift this restriction once implemented. * fix(cloudfront): resolve strict access type checks * chore(cloudfront): reduce strict startup log noise --------- Co-authored-by: Danny Avila <danny@librechat.ai>
Summary
Adds an opt-in
cloudfront.requireSignedAccessconfig flag that turns the existing CloudFront signed-cookie support into a hard startup contract. Today the cookie strategy is best-effort: misconfigured deployments silently fall back to public OAC or to broken image delivery. Operators who put CloudFront in front of LibreChat specifically to keep private images private have no way to assert that signing is actually wired up — strict mode closes that gap.When
requireSignedAccess: true:imageSigningmust equal"cookies"(signed URL mode is not implemented yet). Enforced both by a Zod refinement oncloudfrontConfigSchemaand by a runtime guard ininitializeCloudFront, so misconfiguration fails fast with a clear message.CLOUDFRONT_KEY_PAIR_IDandCLOUDFRONT_PRIVATE_KEYmust be set. Missing either one fails initialization.initializeFileStoragethrows on CloudFront init failure to block startup rather than logging and continuing.When the flag is unset /
false, existing OSS behavior is unchanged: missing keys still log-and-continue, and the cookie strategy stays best-effort.Also adds low-noise logs at startup (strict mode enabled, strict failure reasons) and a single success log on cookie issuance with only path count + expiry seconds — no signed URLs, policies, signatures, private keys, or cookie values are ever logged.
Change Type
Testing
Unit-tested via Jest in the affected workspaces. From the repo root:
New coverage:
cloudfront-config.spec.ts: schema rejectsrequireSignedAccess=truewhenimageSigningis"none"or"url", accepts it with"cookies"+cookieDomain.cloudfront.test.ts: runtime guard returns false (and logs the strict-failure reason) for missing keys,imageSigning="none", andimageSigning="url"; logs strict-mode-enabled info when configured correctly.cdn.test.ts:initializeFileStoragethrows when CloudFront init fails andrequireSignedAccess=true; does not throw whenfalse.Test Configuration:
No special configuration. Tests use
jest.mockfor the AWS SDK and logger — no live CloudFront, no real keys.Checklist