@botfabrik/engine-webclient 4.110.3 → 4.110.4

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.
@@ -8,17 +8,17 @@ import helmet from 'helmet';
8
8
  * @param baseUrl - The server's own base URL (e.g. "http://localhost:3000").
9
9
  */
10
10
  export function applySecurityMiddleware(router, props, baseUrl) {
11
- const { allowedOrigins, trustedResourceOrigins } = props;
11
+ const { allowedEmbedOrigins, allowedResourceOrigins } = props;
12
12
  // CORS
13
- // When allowedOrigins is undefined, all origins are permitted (backward-compatible default).
13
+ // When allowedEmbedOrigins is undefined, all origins are permitted (backward-compatible default).
14
14
  // When it is set (even to an empty array), only the listed origins plus the server's own
15
15
  // base URL are allowed.
16
16
  router.use(cors({
17
- origin: allowedOrigins === undefined
17
+ origin: allowedEmbedOrigins === undefined
18
18
  ? true
19
19
  : (origin, callback) => {
20
20
  // The server's own origin is always allowed.
21
- const effectiveAllowed = [baseUrl, ...allowedOrigins];
21
+ const effectiveAllowed = [baseUrl, ...allowedEmbedOrigins];
22
22
  if (!origin || effectiveAllowed.includes(origin)) {
23
23
  callback(null, true);
24
24
  }
@@ -36,30 +36,30 @@ export function applySecurityMiddleware(router, props, baseUrl) {
36
36
  directives: {
37
37
  defaultSrc: ["'self'"],
38
38
  scriptSrc: ["'self'"],
39
- // stylesheets: allow all HTTPS sources when no trustedResourceOrigins are configured
39
+ // stylesheets: allow all HTTPS sources when no allowedResourceOrigins are configured
40
40
  // (backward-compatible default); otherwise restrict to the listed origins
41
- styleSrc: trustedResourceOrigins === undefined
41
+ styleSrc: allowedResourceOrigins === undefined
42
42
  ? ["'self'", "'unsafe-inline'", 'https:']
43
- : ["'self'", "'unsafe-inline'", ...trustedResourceOrigins],
44
- // images: restrict to trusted resource origins when defined, otherwise allow all HTTPS
45
- imgSrc: trustedResourceOrigins === undefined
43
+ : ["'self'", "'unsafe-inline'", ...allowedResourceOrigins],
44
+ // images: restrict to allowed resource origins when defined, otherwise allow all HTTPS
45
+ imgSrc: allowedResourceOrigins === undefined
46
46
  ? ["'self'", 'data:', 'https:']
47
- : ["'self'", 'data:', ...trustedResourceOrigins],
47
+ : ["'self'", 'data:', ...allowedResourceOrigins],
48
48
  connectSrc: [
49
49
  "'self'",
50
50
  // allow websocket connections back to the same server
51
51
  baseUrl.replace(/^http/, 'ws'),
52
52
  baseUrl.replace(/^http/, 'wss'),
53
53
  ],
54
- // fonts may be loaded from trusted resource origins (e.g. Google Fonts);
55
- // when no trustedResourceOrigins are configured, allow fonts from all origins
56
- fontSrc: trustedResourceOrigins === undefined
54
+ // fonts may be loaded from allowed resource origins (e.g. Google Fonts);
55
+ // when no allowedResourceOrigins are configured, allow fonts from all origins
56
+ fontSrc: allowedResourceOrigins === undefined
57
57
  ? ['*']
58
- : ["'self'", ...trustedResourceOrigins],
59
- // when no allowedOrigins are configured, allow framing from all origins
60
- frameAncestors: allowedOrigins === undefined
58
+ : ["'self'", ...allowedResourceOrigins],
59
+ // when no allowedEmbedOrigins are configured, allow framing from all origins
60
+ frameAncestors: allowedEmbedOrigins === undefined
61
61
  ? ['*']
62
- : ["'self'", ...allowedOrigins],
62
+ : ["'self'", ...allowedEmbedOrigins],
63
63
  // frame-src controls what this page may embed in an iframe.
64
64
  // The /embed page loads the chatbot in an iframe on the same server.
65
65
  // We include both http and https of the server's base URL because a browser
@@ -69,7 +69,7 @@ export function applySecurityMiddleware(router, props, baseUrl) {
69
69
  "'self'",
70
70
  baseUrl,
71
71
  baseUrl.replace(/^http:/, 'https:'),
72
- ...(allowedOrigins ?? []),
72
+ ...(allowedEmbedOrigins ?? []),
73
73
  ],
74
74
  objectSrc: ["'none'"],
75
75
  baseUri: ["'self'"],
@@ -5,47 +5,47 @@ import { applySecurityMiddleware } from './applySecurityMiddleware.js';
5
5
  const BASE_URL = 'http://localhost:3000';
6
6
  describe('security middleware', () => {
7
7
  describe('CORS', () => {
8
- it('allows all origins when allowedOrigins is undefined', async () => {
8
+ it('allows all origins when allowedEmbedOrigins is undefined', async () => {
9
9
  const res = await supertest(makeApp({}))
10
10
  .get('/')
11
11
  .set('Origin', 'http://any-origin.example.com');
12
12
  expect(res.headers['access-control-allow-origin']).toBe('http://any-origin.example.com');
13
13
  });
14
- it('allows the server baseUrl when allowedOrigins is []', async () => {
15
- const res = await supertest(makeApp({ allowedOrigins: [] }))
14
+ it('allows the server baseUrl when allowedEmbedOrigins is []', async () => {
15
+ const res = await supertest(makeApp({ allowedEmbedOrigins: [] }))
16
16
  .get('/')
17
17
  .set('Origin', BASE_URL);
18
18
  expect(res.headers['access-control-allow-origin']).toBe(BASE_URL);
19
19
  });
20
20
  it('allows an explicitly listed origin', async () => {
21
- const res = await supertest(makeApp({ allowedOrigins: ['http://example.com'] }))
21
+ const res = await supertest(makeApp({ allowedEmbedOrigins: ['http://example.com'] }))
22
22
  .get('/')
23
23
  .set('Origin', 'http://example.com');
24
24
  expect(res.headers['access-control-allow-origin']).toBe('http://example.com');
25
25
  });
26
26
  it('rejects an unlisted origin', async () => {
27
- const res = await supertest(makeApp({ allowedOrigins: ['http://example.com'] }))
27
+ const res = await supertest(makeApp({ allowedEmbedOrigins: ['http://example.com'] }))
28
28
  .get('/')
29
29
  .set('Origin', 'http://evil.example.com');
30
30
  // cors package sets the header to false/omits it when rejected
31
31
  expect(res.headers['access-control-allow-origin']).toBeUndefined();
32
32
  });
33
- it('allows no-origin requests (same-origin non-browser) regardless of allowedOrigins', async () => {
34
- const res = await supertest(makeApp({ allowedOrigins: [] })).get('/');
33
+ it('allows no-origin requests (same-origin non-browser) regardless of allowedEmbedOrigins', async () => {
34
+ const res = await supertest(makeApp({ allowedEmbedOrigins: [] })).get('/');
35
35
  expect(res.status).toBe(200);
36
36
  });
37
37
  });
38
38
  describe('CSP frame-ancestors', () => {
39
- it("is '*' when allowedOrigins is undefined", async () => {
39
+ it("is '*' when allowedEmbedOrigins is undefined", async () => {
40
40
  const res = await supertest(makeApp({})).get('/');
41
41
  expect(res.headers['content-security-policy']).toContain('frame-ancestors *');
42
42
  });
43
- it('is "\'self\'" + listed origin when allowedOrigins is set', async () => {
44
- const res = await supertest(makeApp({ allowedOrigins: ['http://example.com'] })).get('/');
43
+ it('is "\'self\'" + listed origin when allowedEmbedOrigins is set', async () => {
44
+ const res = await supertest(makeApp({ allowedEmbedOrigins: ['http://example.com'] })).get('/');
45
45
  expect(res.headers['content-security-policy']).toContain("frame-ancestors 'self' http://example.com");
46
46
  });
47
- it('is "\'self\'" only when allowedOrigins is []', async () => {
48
- const res = await supertest(makeApp({ allowedOrigins: [] })).get('/');
47
+ it('is "\'self\'" only when allowedEmbedOrigins is []', async () => {
48
+ const res = await supertest(makeApp({ allowedEmbedOrigins: [] })).get('/');
49
49
  expect(res.headers['content-security-policy']).toContain("frame-ancestors 'self'");
50
50
  });
51
51
  });
@@ -57,7 +57,7 @@ describe('security middleware', () => {
57
57
  expect(csp).toContain('wss://bot.example.com');
58
58
  });
59
59
  });
60
- describe('CSP trustedResourceOrigins', () => {
60
+ describe('CSP allowedResourceOrigins', () => {
61
61
  it('allows all HTTPS for styleSrc/imgSrc/fontSrc when undefined', async () => {
62
62
  const res = await supertest(makeApp({})).get('/');
63
63
  const csp = res.headers['content-security-policy'];
@@ -66,7 +66,7 @@ describe('security middleware', () => {
66
66
  expect(csp).toContain('font-src *');
67
67
  });
68
68
  it('restricts styleSrc/imgSrc/fontSrc to listed origins when set', async () => {
69
- const res = await supertest(makeApp({ trustedResourceOrigins: ['https://fonts.googleapis.com'] })).get('/');
69
+ const res = await supertest(makeApp({ allowedResourceOrigins: ['https://fonts.googleapis.com'] })).get('/');
70
70
  const csp = res.headers['content-security-policy'];
71
71
  expect(csp).toContain('https://fonts.googleapis.com');
72
72
  expect(csp).not.toContain('font-src *');