@promptbook/cli 0.112.0-127 → 0.112.0-129

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.
@@ -19,6 +19,7 @@ export async function resolveAccessControlResponse(options: {
19
19
  readonly request: NextRequest;
20
20
  readonly isAccessRestricted: boolean;
21
21
  readonly applyResponseHeaders: ApplyResponseHeaders;
22
+ readonly requestHeaders: Headers;
22
23
  }): Promise<NextResponse | null> {
23
24
  if (options.request.method === 'OPTIONS') {
24
25
  return createOptionsResponse();
@@ -31,7 +32,7 @@ export async function resolveAccessControlResponse(options: {
31
32
  const path = options.request.nextUrl.pathname;
32
33
 
33
34
  if (isAllowedPathWhileRestricted(path)) {
34
- const response = NextResponse.next();
35
+ const response = NextResponse.next({ request: { headers: options.requestHeaders } });
35
36
  await options.applyResponseHeaders(response);
36
37
  return response;
37
38
  }
@@ -39,7 +40,7 @@ export async function resolveAccessControlResponse(options: {
39
40
  if (options.request.headers.get('accept')?.includes('text/html')) {
40
41
  const restrictedUrl = options.request.nextUrl.clone();
41
42
  restrictedUrl.pathname = '/restricted';
42
- const response = NextResponse.rewrite(restrictedUrl);
43
+ const response = NextResponse.rewrite(restrictedUrl, { request: { headers: options.requestHeaders } });
43
44
  await options.applyResponseHeaders(response);
44
45
  return response;
45
46
  }
@@ -23,6 +23,7 @@ export async function resolveMiddlewareResponse(options: {
23
23
  readonly customDomainResolution: CustomDomainResolution | null;
24
24
  readonly isEmbeddingAllowed: boolean;
25
25
  readonly applyResponseHeaders: ApplyResponseHeaders;
26
+ readonly requestHeaders: Headers;
26
27
  }): Promise<NextResponse> {
27
28
  const rootAgentRedirectResponse = createRootAgentRedirectResponse(options.request);
28
29
  if (rootAgentRedirectResponse) {
@@ -33,15 +34,18 @@ export async function resolveMiddlewareResponse(options: {
33
34
  const customDomainRewriteResponse = createCustomDomainRewriteResponse(
34
35
  options.request,
35
36
  options.customDomainResolution,
37
+ options.requestHeaders,
36
38
  );
37
39
  if (customDomainRewriteResponse) {
38
40
  await options.applyResponseHeaders(customDomainRewriteResponse);
39
41
  return customDomainRewriteResponse;
40
42
  }
41
43
 
42
- const response = NextResponse.next();
43
- applyEmbeddingHeader(response, options.request.nextUrl, options.isEmbeddingAllowed);
44
+ const response = NextResponse.next({ request: { headers: options.requestHeaders } });
45
+ // Note: The base Content Security Policy is applied first so the embedding header can append its
46
+ // own `frame-ancestors` directive without dropping the strict `script-src` policy.
44
47
  await options.applyResponseHeaders(response);
48
+ applyEmbeddingHeader(response, options.request.nextUrl, options.isEmbeddingAllowed);
45
49
  return response;
46
50
  }
47
51
 
@@ -78,6 +82,7 @@ function createRootAgentRedirectResponse(request: NextRequest): NextResponse | n
78
82
  *
79
83
  * @param request - Incoming middleware request.
80
84
  * @param customDomainResolution - Resolved custom-domain mapping.
85
+ * @param requestHeaders - Forwarded request headers already carrying the per-request CSP nonce.
81
86
  * @returns Rewrite response, or `null` when no custom-domain mapping exists.
82
87
  *
83
88
  * @private function of resolveMiddlewareResponse
@@ -85,6 +90,7 @@ function createRootAgentRedirectResponse(request: NextRequest): NextResponse | n
85
90
  function createCustomDomainRewriteResponse(
86
91
  request: NextRequest,
87
92
  customDomainResolution: CustomDomainResolution | null,
93
+ requestHeaders: Headers,
88
94
  ): NextResponse | null {
89
95
  if (!customDomainResolution) {
90
96
  return null;
@@ -93,7 +99,6 @@ function createCustomDomainRewriteResponse(
93
99
  const rewriteUrl = request.nextUrl.clone();
94
100
  rewriteUrl.pathname = `/${customDomainResolution.agentName}`;
95
101
 
96
- const requestHeaders = new Headers(request.headers);
97
102
  requestHeaders.set('x-promptbook-server', customDomainResolution.server.domain);
98
103
 
99
104
  return NextResponse.rewrite(rewriteUrl, {
@@ -1,5 +1,10 @@
1
1
  import { NextRequest, NextResponse } from 'next/server';
2
2
  import { applyVisibilityHeaders } from './middleware/applyVisibilityHeaders';
3
+ import {
4
+ applyContentSecurityPolicyHeader,
5
+ applyContentSecurityPolicyToRequestHeaders,
6
+ generateContentSecurityPolicyNonce,
7
+ } from './middleware/contentSecurityPolicy';
3
8
  import { createMiddlewareRequestContext } from './middleware/createMiddlewareRequestContext';
4
9
  import { resolveAccessControlResponse } from './middleware/resolveAccessControlResponse';
5
10
  import { resolveMiddlewareResponse } from './middleware/resolveMiddlewareResponse';
@@ -12,8 +17,15 @@ import { resolveMiddlewareResponse } from './middleware/resolveMiddlewareRespons
12
17
  * @returns Middleware response.
13
18
  */
14
19
  export async function middleware(request: NextRequest): Promise<NextResponse> {
20
+ // Note: A fresh, single-use nonce is issued per request so that only inline scripts explicitly
21
+ // rendered by the server (theme bootstrap, custom JavaScript, analytics) are allowed to run.
22
+ const contentSecurityPolicyNonce = generateContentSecurityPolicyNonce();
23
+ const requestHeaders = new Headers(request.headers);
24
+ applyContentSecurityPolicyToRequestHeaders(requestHeaders, contentSecurityPolicyNonce);
25
+
15
26
  const middlewareRequestContext = await createMiddlewareRequestContext(request);
16
27
  const applyResponseHeaders = async (response: NextResponse): Promise<void> => {
28
+ applyContentSecurityPolicyHeader(response, contentSecurityPolicyNonce);
17
29
  await applyVisibilityHeaders({
18
30
  canQueryServerTables: middlewareRequestContext.canQueryServerTables,
19
31
  request,
@@ -27,6 +39,7 @@ export async function middleware(request: NextRequest): Promise<NextResponse> {
27
39
  applyResponseHeaders,
28
40
  isAccessRestricted: middlewareRequestContext.isAccessRestricted,
29
41
  request,
42
+ requestHeaders,
30
43
  });
31
44
 
32
45
  if (accessControlResponse) {
@@ -38,6 +51,7 @@ export async function middleware(request: NextRequest): Promise<NextResponse> {
38
51
  customDomainResolution: middlewareRequestContext.customDomainResolution,
39
52
  isEmbeddingAllowed: middlewareRequestContext.isEmbeddingAllowed,
40
53
  request,
54
+ requestHeaders,
41
55
  });
42
56
  }
43
57