Skip to content

Commit 1c4fe5d

Browse files
authored
Content Security Policy: add img-src data: (#5648)
* Add img-src data: to CSP * Add entry
1 parent 7285139 commit 1c4fe5d

File tree

7 files changed

+104
-38
lines changed

7 files changed

+104
-38
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,8 @@ Notes: web developers are advised to use [`~` (tilde range)](https://github.com/
330330
- Fixed `botframework-webchat/decorator` import in legacy CommonJS environments, in [#5616](https://github.com/microsoft/BotFramework-WebChat/pull/5616), by [@OEvgeny](https://github.com/OEvgeny)
331331
- Fixed `npm start` for efficiency and reliability, in PR [#5621](https://github.com/microsoft/BotFramework-WebChat/pull/5621) and [#5629](https://github.com/microsoft/BotFramework-WebChat/pull/5629), by [@compulim](https://github.com/compulim)
332332
- Fixed activity sorting introduced in PR [#5622](https://github.com/microsoft/BotFramework-WebChat/pull/5622), part grouping, and livestreaming, by [@compulim](https://github.com/compulim) in PR [#5635](https://github.com/microsoft/BotFramework-WebChat/pull/5635)
333+
- Fixed Content Security Policy documentation and sample in PR, by [@compulim](https://github.com/compulim) in PR [#5648](https://github.com/microsoft/BotFramework-WebChat/pull/5648)
334+
- Added `img-src data:`, required for icons
333335

334336
### Removed
335337

18.5 KB
Loading
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<!doctype html>
2+
<html lang="en-US">
3+
<head>
4+
<link href="/assets/index.css" nonce="TEST_PAGE_NONCE" rel="stylesheet" type="text/css" />
5+
<script crossorigin="anonymous" nonce="TEST_PAGE_NONCE" src="/test-harness.js"></script>
6+
<script crossorigin="anonymous" nonce="TEST_PAGE_NONCE" src="/test-page-object.js"></script>
7+
<script crossorigin="anonymous" nonce="TEST_PAGE_NONCE" src="/__dist__/webchat-es5.js"></script>
8+
<!--
9+
Outside of the CSP defined in our /docs/CONTENT_SECURITY_POLICY.md, this test added limited number rules to enable the test case.
10+
11+
- connect-src
12+
- https://hawo-mockbot4-token-app.blueriver-ce85e8f0.westus.azurecontainerapps.io/api/token/directline to fetching Direct Line token
13+
- script-src
14+
- 'nonce-TEST_PAGE_NONCE' to loading test related assets
15+
- style-src
16+
- 'nonce-TEST_PAGE_NONCE' to loading test related assets
17+
-->
18+
<meta
19+
http-equiv="Content-Security-Policy"
20+
content="default-src 'none'; base-uri 'none'; connect-src blob: https://directline.botframework.com https://hawo-mockbot4-token-app.blueriver-ce85e8f0.westus.azurecontainerapps.io/api/token/directline wss://directline.botframework.com; img-src blob: data:; script-src 'strict-dynamic' 'nonce-TEST_PAGE_NONCE'; style-src 'nonce-WEB_CHAT_NONCE' 'nonce-TEST_PAGE_NONCE'"
21+
/>
22+
</head>
23+
<body>
24+
<main id="webchat"></main>
25+
<script nonce="TEST_PAGE_NONCE">
26+
run(async function () {
27+
WebChat.renderWebChat(
28+
{
29+
directLine: WebChat.createDirectLine({
30+
token: await testHelpers.token.fetchDirectLineToken()
31+
}),
32+
nonce: 'WEB_CHAT_NONCE',
33+
store: testHelpers.createStore()
34+
},
35+
document.getElementById('webchat')
36+
);
37+
38+
await pageConditions.uiConnected();
39+
40+
await pageObjects.sendMessageViaSendBox('card breakfast');
41+
42+
await pageConditions.numActivitiesShown(2);
43+
44+
await host.snapshot();
45+
});
46+
</script>
47+
</body>
48+
</html>

docs/CONTENT_SECURITY_POLICY.md

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,29 @@
22

33
Starting from 4.10.1, [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) is supported.
44

5-
> In this article, we are using a nonce of `a1b2c3d`. In a production system, it should be a random and unguessable value that changes every time a policy is applied.
5+
> In this article, we are using a nonce of `a1b2c3d`. In production environment, it should be a value generated by random number generator (RNG) with high entropy. The value should change every time the policy is applied.
6+
7+
> New in 4.19.0: `img-src data:` is required for display icons used in Web Chat.
68
79
To enable Web Chat in a CSP-enforced environment, the following directives must be configured:
810

911
```
10-
connect-src https://directline.botframework.com wss://directline.botframework.com; img-src blob:; script-src 'strict-dynamic'; style-src 'nonce-a1b2c3d'
12+
img-src blob: data:; script-src 'strict-dynamic'; style-src 'nonce-a1b2c3d'
13+
```
14+
15+
If Web Chat is used to connect to Azure Bot Services, the following additional directives must be configured:
16+
17+
```
18+
connect-src https://directline.botframework.com wss://directline.botframework.com;
1119
```
1220

13-
For example, in a strict CSP environment, the basic policy should be:
21+
For example, in a strict CSP environment, the basic policy to connect to Azure Bot Services should be:
1422

1523
<!-- prettier-ignore-start -->
1624
```html
1725
<meta
1826
http-equiv="Content-Security-Policy"
19-
content="default-src 'none'; base-uri 'none'; connect-src blob: https://directline.botframework.com wss://directline.botframework.com; img-src blob:; script-src 'strict-dynamic'; style-src 'nonce-a1b2c3d'"
27+
content="default-src 'none'; base-uri 'none'; connect-src blob: https://directline.botframework.com wss://directline.botframework.com; img-src blob: data:; script-src 'strict-dynamic'; style-src 'nonce-a1b2c3d'"
2028
/>
2129
```
2230
<!-- prettier-ignore-end -->
@@ -27,43 +35,44 @@ Additional directives may be needed to operate the bot properly. For example, if
2735

2836
## Explanation of directives
2937

30-
- `default-src 'none'`
31-
- For strict CSP: deny access unless otherwise specified
32-
- `base-uri 'none'`
33-
- For strict CSP: deny rebasing URIs using the [`<base>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base)
34-
- `connect-src blob: https://directline.botframework.com wss://directline.botframework.com`
35-
- `blob:` is used for uploading attachments
36-
- REST call to https://directline.botframework.com for starting conversation, posting activities, etc.
37-
- Web Socket connection to wss://directline.botframework.com for receiving activities
38-
- When using protocols other than Direct Line or Web Chat channel, the source will be different
39-
- `img-src blob:`
40-
- `blob:` will allow images in Web Chat to be loaded via `blob:` scheme. Types of images using `blob:` scheme:
41-
- Inlined assets. For example, connectivity status spinner and typing indicator
42-
- You can use `styleOptions` to load these images from your source and modify this directive as needed
43-
- Bot attached images using data URI, will be converted to URL with scheme of `blob:`
44-
- User uploaded images are downscaled as thumbnails with scheme of `blob:`
45-
- `script-src 'strict-dynamic'`
46-
- (Optional) `strict-dynamic` will allow Web Chat to use Web Worker to downscale image on upload
47-
- If `strict-dynamic` is not provided, Web Chat will fallback to main thread to downscale image
48-
- `style-src 'nonce-a1b2c3d'`
49-
- `'nonce-a1b2c3d'` will allow CSS injection through this nonce. This should be a per-policy, unique, and unguessable value
50-
- Web Chat inject `<style>` element using [`emotion`](https://emotion.sh/) with `nonce` attribute
51-
- You will need to pass this nonce when rendering Web Chat
38+
- `default-src 'none'`
39+
- For strict CSP: deny access unless otherwise specified
40+
- `base-uri 'none'`
41+
- For strict CSP: deny rebasing URIs using the [`<base>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base)
42+
- `connect-src blob: https://directline.botframework.com wss://directline.botframework.com`
43+
- `blob:` is used for uploading attachments
44+
- REST call to https://directline.botframework.com for starting conversation, posting activities, etc.
45+
- Web Socket connection to wss://directline.botframework.com for receiving activities
46+
- When using protocols other than Direct Line or Web Chat channel, the source will be different
47+
- `img-src blob:`
48+
- `blob:` will allow images in Web Chat to be loaded via `blob:` scheme. Types of images using `blob:` scheme:
49+
- Bot attached images using data URI, will be converted to URL with scheme of `blob:`
50+
- User uploaded images are downscaled as thumbnails with scheme of `blob:`
51+
- `img-src data:`
52+
- `data:` will allow images in Web Chat to be loaded via `data:` scheme. Types of images using `data:` scheme:
53+
- Inlined assets. For example, connectivity status spinner and typing indicator
54+
- `script-src 'strict-dynamic'`
55+
- (Optional) `strict-dynamic` will allow Web Chat to use Web Worker to downscale image on upload
56+
- If `strict-dynamic` is not provided, Web Chat will fallback to main thread to downscale image
57+
- `style-src 'nonce-a1b2c3d'`
58+
- `'nonce-a1b2c3d'` will allow CSS injection through this nonce. This should be a per-policy, unique, and unguessable value
59+
- Web Chat inject `<style>` element using [`emotion`](https://emotion.sh/) with `nonce` attribute
60+
- You will need to pass this nonce when rendering Web Chat
5261

5362
## Setting up the nonce
5463

5564
When rendering Web Chat, pass the nonce as a prop named `nonce`.
5665

5766
```js
5867
WebChat.renderWebChat({
59-
directLine: createDirectLine({ token }),
60-
nonce: 'a1b2c3d'
68+
directLine: createDirectLine({ token }),
69+
nonce: 'a1b2c3d'
6170
});
6271
```
6372

6473
## Limitations
6574

66-
Currently, the nonce is used for injecting `<style>` elements only. It is not used for other elements, including `<img>` and other media elements. For details, please see [#3445](https://github.com/microsoft/BotFramework-WebChat/issues/3445.
75+
Currently, the nonce is used for injecting `<style>` elements only. It is not used for other elements, including `<img>` and other media elements. For details, please see [#3445](https://github.com/microsoft/BotFramework-WebChat/issues/3445).
6776

6877
## Nonce exposure
6978

packages/test/harness/src/browser/globals/imageAsLog.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1-
async function getBlobURL(base64) {
2-
const res = await fetch(`data:image/png;base64,${base64}`);
3-
const blob = await res.blob();
1+
function getBlobURL(base64) {
2+
const byteString = atob(base64);
3+
const arrayBuffer = new ArrayBuffer(byteString.length);
4+
const uint8Array = new Uint8Array(arrayBuffer);
5+
6+
for (let index = 0; index < byteString.length; index++) {
7+
uint8Array[+index] = byteString.charCodeAt(index);
8+
}
9+
10+
const blob = new Blob([uint8Array], { type: 'image/png' });
411

512
return URL.createObjectURL(blob);
613
}
@@ -17,7 +24,7 @@ function getImageSize(url) {
1724
}
1825

1926
async function imageAsLog(base64, scale = 1) {
20-
const url = await getBlobURL(base64);
27+
const url = getBlobURL(base64);
2128
const { height, width } = await getImageSize(url);
2229

2330
const scaledHeight = height * scale;

samples/01.getting-started/j.bundle-with-content-security-policy/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ The only change needed in this sample is to configure a strict Content Security
4141
<head>
4242
+ <meta
4343
+ http-equiv="Content-Security-Policy"
44-
+ content="default-src 'none'; base-uri 'none'; connect-src https://directline.botframework.com wss://directline.botframework.com https://webchat-mockbot.azurewebsites.net; img-src blob:; script-src 'nonce-a1b2c3d' 'strict-dynamic'; style-src 'nonce-a1b2c3d'"
44+
+ content="default-src 'none'; base-uri 'none'; connect-src https://directline.botframework.com wss://directline.botframework.com https://webchat-mockbot.azurewebsites.net; img-src blob: data:; script-src 'nonce-a1b2c3d' 'strict-dynamic'; style-src 'nonce-a1b2c3d'"
4545
+ />
4646
- <script crossorigin="anonymous" src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
4747
+ <script crossorigin="anonymous" nonce="a1b2c3d" src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
@@ -78,10 +78,10 @@ Here is the finished `index.html`:
7878
<!DOCTYPE html>
7979
<html lang="en-US">
8080
<head>
81-
<title>Web Chat: Minimal bundle</title>
81+
<title>Web Chat: Content Security Policy</title>
8282
<meta
8383
http-equiv="Content-Security-Policy"
84-
content="default-src 'none'; base-uri 'none'; connect-src https://directline.botframework.com wss://directline.botframework.com https://webchat-mockbot.azurewebsites.net; img-src blob:; script-src 'nonce-a1b2c3d' 'strict-dynamic'; style-src 'nonce-a1b2c3d'"
84+
content="default-src 'none'; base-uri 'none'; connect-src https://directline.botframework.com wss://directline.botframework.com https://webchat-mockbot.azurewebsites.net; img-src blob: data:; script-src 'nonce-a1b2c3d' 'strict-dynamic'; style-src 'nonce-a1b2c3d'"
8585
/>
8686
<script crossorigin="anonymous" nonce="a1b2c3d" src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
8787
<style nonce="a1b2c3d">

samples/01.getting-started/j.bundle-with-content-security-policy/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
<!doctype html>
22
<html lang="en-US">
33
<head>
4-
<title>Web Chat: Full-featured bundle</title>
4+
<title>Web Chat: Content Security Policy</title>
55
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
66
<!--
77
This CDN points to the latest official release of Web Chat. If you need to test against Web Chat's latest bits, please refer to using Web Chat's latest bits:
88
https://github.com/microsoft/BotFramework-WebChat#how-to-test-with-web-chats-latest-bits
99
-->
1010
<meta
1111
http-equiv="Content-Security-Policy"
12-
content="default-src 'none'; base-uri 'none'; connect-src blob: https://directline.botframework.com wss://directline.botframework.com https://webchat-mockbot.azurewebsites.net; img-src blob:; script-src 'nonce-a1b2c3d' 'strict-dynamic' 'unsafe-eval'; style-src 'nonce-a1b2c3d'"
12+
content="default-src 'none'; base-uri 'none'; connect-src blob: https://directline.botframework.com wss://directline.botframework.com https://hawo-mockbot4-token-app.blueriver-ce85e8f0.westus.azurecontainerapps.io; img-src blob: data:; script-src 'nonce-a1b2c3d' 'strict-dynamic'; style-src 'nonce-a1b2c3d'"
1313
/>
1414
<script
1515
crossorigin="anonymous"

0 commit comments

Comments
 (0)