@djangocfg/nextjs 2.1.480 → 2.1.482
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/dist/config/index.d.mts +54 -20
- package/dist/config/index.mjs +8 -3
- package/dist/config/index.mjs.map +1 -1
- package/dist/index.mjs +8 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
- package/src/config/createNextConfig.ts +26 -18
- package/src/config/csp.ts +42 -9
package/dist/config/index.d.mts
CHANGED
|
@@ -108,15 +108,43 @@ type CspVendor = keyof typeof CSP_VENDOR_PRESETS;
|
|
|
108
108
|
/**
|
|
109
109
|
* Vendors applied to every app unless explicitly disabled.
|
|
110
110
|
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
* 2026-07-22: all six DjangoCFG-served hosts were violating their own CSP.)
|
|
111
|
+
* The rule for this list: an origin belongs here when the app CANNOT DECLARE IT
|
|
112
|
+
* FROM `next.config.ts`, because whatever turns the script on lives somewhere
|
|
113
|
+
* the config file cannot read. Leaving such a vendor opt-in does not produce a
|
|
114
|
+
* build error or a dev warning — it produces a production-only console error
|
|
115
|
+
* that nobody sees until a user reports a broken page.
|
|
117
116
|
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
117
|
+
* - `cloudflare` — the Web Analytics beacon is rewritten into the HTML AT THE
|
|
118
|
+
* EDGE, after Next.js has already sent the CSP header. Nothing in the source
|
|
119
|
+
* tree reveals it. (Observed 2026-07-22: all six DjangoCFG-served hosts were
|
|
120
|
+
* violating their own CSP.)
|
|
121
|
+
*
|
|
122
|
+
* - `google-analytics` — gtag.js is injected AT RUNTIME by `@djangocfg/layouts`
|
|
123
|
+
* (`BaseApp analytics={{ googleTrackingId }}` → the lazy `ga4()` transport).
|
|
124
|
+
* That id is an ordinary TS value in the app's `settings.ts`, not an env var,
|
|
125
|
+
* so `next.config.ts` — a different module, evaluated in a different process,
|
|
126
|
+
* before any of that code runs — has no way to see whether GA is on. The app
|
|
127
|
+
* author enables analytics in one file and silently breaks CSP in another.
|
|
128
|
+
* (Observed 2026-07-23: cmdop `apps/web` blocked on
|
|
129
|
+
* `googletagmanager.com/gtag/js?id=G-YJ0F48S83F`.)
|
|
130
|
+
*
|
|
131
|
+
* - `youtube` / `vimeo` — `VideoPlayer` (`@djangocfg/ui-tools`) mounts these
|
|
132
|
+
* iframes AT RUNTIME from a URL inside a chat message (see
|
|
133
|
+
* `chat/messages/blocks/renderers/VideoBlock.tsx`). The app author enables a
|
|
134
|
+
* chat; whether any user ever pastes a YouTube link is not knowable at build
|
|
135
|
+
* time, so no `next.config.ts` can declare it honestly.
|
|
136
|
+
*
|
|
137
|
+
* Note what these have in common: the script/frame is turned on by the RUNTIME
|
|
138
|
+
* (the edge, a package, or an end user), never by the app author editing the
|
|
139
|
+
* config. Stripe is the counter-example and deliberately NOT here — a developer
|
|
140
|
+
* decides to mount a payment form, knows they did, and can say `vendors:
|
|
141
|
+
* ['stripe']`; putting it in the baseline would hand `frame-src js.stripe.com`
|
|
142
|
+
* to marketing sites that never take a payment.
|
|
143
|
+
*
|
|
144
|
+
* Do NOT add ordinary third parties here — anything an app knowingly mounts and
|
|
145
|
+
* can name in its own config belongs in `csp.vendors`, so unrelated apps keep
|
|
146
|
+
* the tighter policy. The cost of an entry here is that every app permits these
|
|
147
|
+
* hosts; that is only worth paying when the alternative is silent breakage.
|
|
120
148
|
*/
|
|
121
149
|
declare const CSP_BASELINE_VENDORS: CspVendor[];
|
|
122
150
|
/**
|
|
@@ -208,18 +236,19 @@ interface BaseNextConfigOptions {
|
|
|
208
236
|
* additive; omit a key to leave that directive untouched.
|
|
209
237
|
* - omitted — tightest default (`frame-src 'self'`, etc.), same as today.
|
|
210
238
|
*
|
|
211
|
-
* **
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
239
|
+
* **Scripts nothing in this file can see are already handled.** Cloudflare
|
|
240
|
+
* Web Analytics (injected at the edge) and Google Analytics (injected at
|
|
241
|
+
* runtime by `BaseApp analytics={{ googleTrackingId }}`) are both switched on
|
|
242
|
+
* outside `next.config.ts`, so their origins are in the baseline and you do
|
|
243
|
+
* NOT need to list them — see `CSP_BASELINE_VENDORS`. Turn them off with
|
|
244
|
+
* `baseline: false`.
|
|
217
245
|
*
|
|
218
246
|
* @example
|
|
219
247
|
* ```ts
|
|
220
248
|
* // Declare the third parties this app actually uses — origins come from
|
|
221
249
|
* // the shared registry, so a vendor host change is fixed in one place.
|
|
222
|
-
*
|
|
250
|
+
* // (Cloudflare + GA are already in the baseline; no need to list them.)
|
|
251
|
+
* createBaseNextConfig({ csp: { vendors: ['stripe'] } })
|
|
223
252
|
*
|
|
224
253
|
* // Escape hatch for something not in the registry yet
|
|
225
254
|
* createBaseNextConfig({ csp: { frameSrc: ['https://www.youtube-nocookie.com'] } })
|
|
@@ -237,13 +266,18 @@ interface BaseNextConfigOptions {
|
|
|
237
266
|
*/
|
|
238
267
|
vendors?: (CspVendor | (string & {}))[];
|
|
239
268
|
/**
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
269
|
+
* Drop the baseline vendors (see `CSP_BASELINE_VENDORS`: Cloudflare Web
|
|
270
|
+
* Analytics + Google Analytics). They are on by default because each is
|
|
271
|
+
* switched on somewhere `next.config.ts` cannot read — the Cloudflare
|
|
272
|
+
* beacon is injected at the edge, and gtag.js is injected at runtime by
|
|
273
|
+
* `BaseApp analytics={{ googleTrackingId }}` — so an opt-in flag would
|
|
274
|
+
* only ever be discovered as a production console error.
|
|
275
|
+
*
|
|
276
|
+
* Set `false` for an app you know mounts neither, to get back the
|
|
277
|
+
* tightest `script-src`.
|
|
244
278
|
* @default true
|
|
245
279
|
*/
|
|
246
|
-
|
|
280
|
+
baseline?: boolean;
|
|
247
281
|
/** Extra `frame-src` origins (iframes this app embeds). */
|
|
248
282
|
frameSrc?: string[];
|
|
249
283
|
/** Extra `script-src` origins (third-party SDK scripts). */
|
package/dist/config/index.mjs
CHANGED
|
@@ -14,7 +14,7 @@ var require_package = __commonJS({
|
|
|
14
14
|
"package.json"(exports, module) {
|
|
15
15
|
module.exports = {
|
|
16
16
|
name: "@djangocfg/nextjs",
|
|
17
|
-
version: "2.1.
|
|
17
|
+
version: "2.1.482",
|
|
18
18
|
description: "Next.js server utilities: sitemap, health, OG images, contact forms, navigation, config",
|
|
19
19
|
keywords: [
|
|
20
20
|
"nextjs",
|
|
@@ -355,7 +355,12 @@ var CSP_VENDOR_PRESETS = {
|
|
|
355
355
|
imgSrc: ["https://i.vimeocdn.com"]
|
|
356
356
|
}
|
|
357
357
|
};
|
|
358
|
-
var CSP_BASELINE_VENDORS = [
|
|
358
|
+
var CSP_BASELINE_VENDORS = [
|
|
359
|
+
"cloudflare",
|
|
360
|
+
"google-analytics",
|
|
361
|
+
"youtube",
|
|
362
|
+
"vimeo"
|
|
363
|
+
];
|
|
359
364
|
function resolveCspVendors(vendors, warnUnknown = true) {
|
|
360
365
|
const merged = {
|
|
361
366
|
scriptSrc: [],
|
|
@@ -1500,7 +1505,7 @@ function createBaseNextConfig(options = {}) {
|
|
|
1500
1505
|
const cspDisabled = options.csp === false;
|
|
1501
1506
|
const cspExtra = typeof options.csp === "object" ? options.csp : void 0;
|
|
1502
1507
|
const vendorNames = [
|
|
1503
|
-
...cspExtra?.
|
|
1508
|
+
...cspExtra?.baseline === false ? [] : CSP_BASELINE_VENDORS,
|
|
1504
1509
|
...options.stripe ? ["stripe"] : [],
|
|
1505
1510
|
...cspExtra?.vendors ?? []
|
|
1506
1511
|
];
|