Skip to content

Commit 803a608

Browse files
authored
Merge branch 'master' into wasm-file
2 parents 30aff55 + 8a5c633 commit 803a608

16 files changed

Lines changed: 776 additions & 234 deletions

README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,47 @@ to create a `.xdc` file, execute:
1010
```sh
1111
./create-xdc.sh
1212
```
13+
14+
## Testing network isolation
15+
16+
<!-- FYI this section is linked to from
17+
https://github.com/deltachat/deltachat-desktop/blob/main/RELEASE.md. -->
18+
19+
To test whether a webxdc runtime implementation (i.e. a messenger) keeps
20+
the ["apps can't access internet" promise](https://delta.chat/en/2023-05-22-webxdc-security#the-unique-privacy-promise-of-web-apps-without-tracking-or-platforms),
21+
one can utilize this app together with [Wireshark](https://www.wireshark.org/).
22+
23+
1. Launch Wireshark.
24+
2. Start capturing packets on the default "internet" interface.
25+
3. Apply the following packet filter:
26+
27+
```js
28+
ip.addr == 173.194.76.127 ||
29+
ip.addr == 37.218.242.41 ||
30+
udp contains "delta" ||
31+
tcp contains "delta"
32+
```
33+
34+
The first IP is the IP address of a Google STUN server,
35+
used in this app's WebRTC test.
36+
The second IP is the IP address of delta.chat.
37+
38+
4. Open the webxdc runtime (i.e. the Delta Chat client)
39+
and launch this webxdc app.
40+
5. Scroll down to the ["DNS Prefetch" section](https://github.com/webxdc/webxdc-test/blob/db2796226d420535cb1caf9ba29e7d639e9e01f2/index.html#L67).
41+
6. Type in `foobar.delta.chat` and press all the 3 buttons in the section.
42+
7. Go back to Wireshark and verify that
43+
there are 0 packets that match the filter.
44+
45+
Disclaimer: the fact that a webxdc implementation passed all these tests
46+
doesn't mean that it's fool-proof.
47+
48+
Wireshark is required because this webxdc app
49+
might not always be able to receive data back, and thus detect a leak.
50+
For example, this is the case for the
51+
[TURN server test](./js/webrtc.js#L27-L36).
52+
53+
As a bonus step, try building Delta Chat with no CSP set for webxdc apps,
54+
and repeating the test.
55+
Still no network activity should occur,
56+
otherwise we're one misstep away from breaking the promise.

iframe-webrtc-test.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4+
<!-- Putting this inline and at the top level
5+
so that it gets executed as early as possible.
6+
Same in index.html -->
7+
<script>globalThis.__capturedWebRTCObj = RTCPeerConnection;</script>
8+
49
<meta charset="utf-8"/>
510
<script src="js/utils.js"></script>
611
</head>

index.html

Lines changed: 206 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,233 @@
11
<!DOCTYPE html>
22
<html>
3-
<head>
4-
<meta charset="utf-8"/>
5-
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
6-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7-
8-
<link rel="stylesheet" href="styles.css" />
9-
<script src="webxdc.js"></script>
10-
<script src="js/utils.js"></script>
11-
</head>
12-
<body>
13-
<div class="card" id="cookies-output"></div>
14-
<script src="js/cookies.js"></script>
3+
<head>
4+
<!-- Putting this inline and at the top level
5+
so that it gets executed as early as possible.
6+
Same in iframe-webrtc-test.html -->
7+
<script>
8+
globalThis.__capturedWebRTCObj = RTCPeerConnection;
9+
</script>
1510

16-
<div class="card" id="storage-output"></div>
17-
<script src="js/storage.js"></script>
11+
<meta charset="utf-8" />
12+
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
13+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
1814

15+
<link rel="stylesheet" href="styles.css" />
16+
17+
<!-- debugging -->
18+
<script src="js/eruda.min.js"></script>
19+
<script>
20+
eruda.init();
21+
</script>
22+
23+
<script src="webxdc.js"></script>
24+
<script src="js/utils.js"></script>
25+
</head>
26+
<body>
27+
<div class="pages">
28+
<div
29+
class="page active"
30+
id="page-webxdc"
31+
role="tabpanel"
32+
aria-labelledby="tab-webxdc"
33+
>
34+
<div class="card" id="realtime-output"></div>
35+
<script src="js/realtime.js"></script>
1936
<div class="card" id="uploads-output"></div>
2037
<script src="js/uploads.js"></script>
21-
2238
<div class="card" id="import-export-output"></div>
2339
<script src="js/import-export.js"></script>
40+
<div class="card" id="update-api-output"></div>
41+
<script src="js/update-api.js"></script>
2442

25-
<div class="card" id="links-output"></div>
26-
<script src="js/links.js"></script>
43+
<div class="card">
44+
<header class="container"><h2>Webxdc Status Update Tests</h2></header>
45+
<div class="container">
46+
<a href="./duplicated_updates_race.html">
47+
Duplicated Status Updates Race Test
48+
</a>
49+
</div>
50+
</div>
51+
52+
<div class="card" id="webxdc-notify-output"></div>
53+
<script src="js/webxdc-notify.js"></script>
2754

55+
<div class="card" id="info-output"></div>
56+
<script src="js/info.js"></script>
57+
</div>
58+
<div
59+
class="page"
60+
id="page-web-api"
61+
role="tabpanel"
62+
aria-labelledby="tab-web-api"
63+
>
64+
<div class="card" id="storage-output"></div>
65+
<script src="js/storage.js"></script>
2866
<div class="card" id="unload-output"></div>
2967
<script src="js/unload.js"></script>
30-
3168
<div class="card" id="navigator-output"></div>
3269
<script src="js/navigator.js"></script>
3370

34-
<div class="card" id="update-api-output"></div>
35-
<script src="js/update-api.js"></script>
36-
3771
<div class="card" id="races-output"></div>
3872
<script src="js/races.js"></script>
3973

4074
<div class="card" id="wasm-output"></div>
4175
<script src="js/wasm.js"></script>
4276

77+
<div class="card" id="links-output"></div>
78+
<script src="js/links.js"></script>
79+
</div>
80+
<div
81+
class="page"
82+
id="page-sandbox"
83+
role="tabpanel"
84+
aria-labelledby="tab-sandbox"
85+
>
86+
<div class="card" id="cookies-output"></div>
87+
<script src="js/cookies.js"></script>
88+
<div class="card" id="camera-access"></div>
89+
<script src="js/media-access.js"></script>
90+
4391
<iframe id="iframe-regular" style="display: none"></iframe>
44-
<iframe id="iframe-allow-same-origin" sandbox="allow-same-origin" style="display: none"></iframe>
92+
<div id="iframe-container" style="display: none"></div>
93+
<iframe
94+
id="iframe-allow-same-origin"
95+
sandbox="allow-same-origin"
96+
style="display: none"
97+
></iframe>
4598
<div class="card" id="webrtc-output"></div>
46-
<script src="js/webrtc.js"></script>
47-
<iframe src="./iframe-webrtc-test.html" sandbox="allow-scripts" width="100%" height="200"></iframe>
48-
4999
<div class="card">
50-
<header class="container"><h2>Webxdc Status Update Tests</h2></header>
51-
<div class="container">
52-
<a href="./duplicated_updates_race.html">
53-
Duplicated Status Updates Race Test
54-
</a>
55-
</div>
100+
<header class="container">
101+
<h2>webrtc-sidechannel iframe</h2>
102+
</header>
103+
<script src="js/webrtc.js"></script>
104+
<iframe
105+
src="./iframe-webrtc-test.html"
106+
sandbox="allow-scripts"
107+
width="100%"
108+
height="200"
109+
></iframe>
56110
</div>
57111

58-
<!-- debugging -->
59-
<script src="js/eruda.min.js"></script>
60-
<script>window.addEventListener("load", () => eruda.init());</script>
61-
</body>
112+
<div class="card" id="iframe-output"></div>
113+
<script src="js/iframe.js"></script>
114+
115+
<!-- DNS prefetch check, originally developed by Cure53
116+
and distributed as "Cure53 Test App - DNS checker" app.
117+
See https://delta.chat/en/2023-05-22-webxdc-security#dns-prefetching-marks-another-exploit. -->
118+
<div class="card dns-prefetch-output">
119+
<header class="container">
120+
<h2>DNS Prefetch</h2>
121+
</header>
122+
<div class="container">
123+
<section>
124+
<p>Usage instructions:</p>
125+
<ol>
126+
<li>
127+
Navigate to
128+
<a href="https://dig.pm/">https://dig.pm/</a>
129+
and click Get Sub Domain.
130+
</li>
131+
<li>Input the subdomain from Step 1.</li>
132+
<li>Click all 3 of the buttons.</li>
133+
<li>Click Get Results on https://dig.pm/.</li>
134+
<li>Observe the DNS lookup record.</li>
135+
</ol>
136+
<p>
137+
Also see
138+
<a
139+
href="https://public.opentech.fund/documents/XDC-01-report_2_1.pdf"
140+
>the audit</a
141+
>
142+
and
143+
<a href="https://delta.chat/en/2023-05-22-webxdc-security"
144+
>the blog post</a
145+
>.
146+
</p>
147+
</section>
148+
<p>
149+
You can also utilize Wireshark, then https://dig.pm/ is not
150+
needed.
151+
</p>
152+
<input
153+
id="dns-prefetch-domain-input"
154+
type="text"
155+
placeholder="abc.example.com"
156+
required
157+
/>
158+
<br />
159+
<button type="button" onclick="dnsPrefetchUpdateLocation()">
160+
Update top.location
161+
</button>
162+
<br />
163+
<button type="button" onclick="dnsPrefetchAddIframe()">
164+
Add iframe
165+
</button>
166+
<br />
167+
<button type="button" onclick="dnsPrefetchAddPrefetch()">
168+
Add &lt;link dns-prefetch&gt;
169+
</button>
170+
<br />
171+
<iframe id="dns-prefetch-frame"></iframe>
172+
</div>
173+
</div>
174+
<script src="js/dns-prefetch.js"></script>
175+
</div>
176+
</div>
177+
<div class="tabs" role="tablist" aria-orientation="horizontal">
178+
<button
179+
role="tab"
180+
aria-controls="page-webxdc"
181+
class="tab"
182+
aria-selected="true"
183+
id="tab-webxdc"
184+
>
185+
Webxdc
186+
</button>
187+
<button
188+
role="tab"
189+
aria-controls="page-web-api"
190+
aria-selected="false"
191+
class="tab"
192+
id="tab-web-api"
193+
>
194+
Web API
195+
</button>
196+
<button
197+
role="tab"
198+
aria-controls="page-sandbox"
199+
aria-selected="false"
200+
class="tab"
201+
id="tab-sandbox"
202+
>
203+
Sandboxing
204+
</button>
205+
</div>
206+
<script>
207+
var tabs = [
208+
{
209+
page: document.getElementById("page-webxdc"),
210+
tab: document.getElementById("tab-webxdc"),
211+
},
212+
{
213+
page: document.getElementById("page-web-api"),
214+
tab: document.getElementById("tab-web-api"),
215+
},
216+
{
217+
page: document.getElementById("page-sandbox"),
218+
tab: document.getElementById("tab-sandbox"),
219+
},
220+
];
221+
for (const { page, tab } of tabs) {
222+
tab.onclick = () => {
223+
tabs.forEach(({ page, tab }) => {
224+
page.classList.remove("active");
225+
tab.ariaSelected = false;
226+
});
227+
page.classList.add("active");
228+
tab.ariaSelected = true;
229+
};
230+
}
231+
</script>
232+
</body>
62233
</html>

js/dns-prefetch.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const getInput = () => document.getElementById("dns-prefetch-domain-input");
2+
3+
function dnsPrefetchUpdateLocation() {
4+
let domain = getInput().value;
5+
top.location = "https://" + domain
6+
alert('Please check DNS record')
7+
}
8+
9+
function dnsPrefetchAddIframe() {
10+
const domain = getInput().value;
11+
const iframe = document.createElement('iframe')
12+
iframe.src = "https://" + domain
13+
getInput().parentElement.appendChild(iframe)
14+
}
15+
16+
function dnsPrefetchAddPrefetch() {
17+
const domain = getInput().value;
18+
document.getElementById('dns-prefetch-frame').srcdoc =
19+
`<link rel="dns-prefetch" href="https://${domain}" /> dns prefetch: ${domain}`;
20+
}

js/iframe.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
window.addEventListener("load", () => {
2+
const ifrmExplain = h(
3+
"p",
4+
{},
5+
"iframe: should be blocked and not load https://delta.chat from Internet:"
6+
);
7+
const ifrm = h("iframe", { src: "https://delta.chat" });
8+
ifrm.style.width = "100%";
9+
ifrm.style.height = "auto";
10+
11+
document
12+
.getElementById("iframe-output")
13+
.append(
14+
createHeader("Loading website in iframe"),
15+
h("div", { class: "container" }, ifrmExplain, ifrm)
16+
);
17+
});

js/info.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
window.addEventListener("load", () => {
2+
let container = h("div", {class: "container"});
3+
4+
// background is set to spot leading/trailing spaces errors
5+
container.append(h("div", {}, "webxdc.selfName: ", h("span", {style: "background:#DDD;word-wrap: break-word;"}, webxdc.selfName)))
6+
container.append(h("div", {}, "webxdc.selfAddr: ", h("span", {style: "background:#DDD;word-wrap: break-word;"}, webxdc.selfAddr)))
7+
8+
container.append(h("div", {}, "webxdc.sendUpdateInterval: " + webxdc.sendUpdateInterval))
9+
container.append(h("div", {}, "webxdc.sendUpdateMaxSize: " + webxdc.sendUpdateMaxSize))
10+
11+
document.getElementById("info-output").append(createHeader("Info"), container);
12+
});
13+

js/links.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
window.addEventListener("load", () => {
22
let ul = h("ul");
33
ul.append(
4-
h("li", {}, h("a", {href: "https://delta.chat"}, "Normal link: https://delta.chat")),
4+
h("li", {}, h("a", {target:"_blank", href: "https://delta.chat"}, "Normal link: https://delta.chat (should ask to open externally)")),
55
h("li", {}, h("a", {href: "mailto:delta@example.org?body=test+message"}, "Mailto link")),
6-
h("li", {}, h("a", {href: "OPENPGP4FPR:571E6FDC22C1605512A1B0C8F7AC9331B82AFB5B#a=delta%40example.org&n=TestContact&i=pHMb3fRw-JV&s=VcWU-pQSEeB"}, "QR verification link")),
6+
h("li", {}, h("a", {href: "OPENPGP4FPR:571E6FDC22C1605512A1B0C8F7AC9331B82AFB5B#a=delta%40example.org&n=TestContact&i=pHMb3fRw-JV&s=VcWU-pQSEeB"}, "old openpgp4fpr: QR verification link")),
7+
h("li", {}, h("a", {target:"_blank", href: "https://i.delta.chat/#9AF055DB87EC48A1C009B6CA55E3712A6F7D346F&a=botsindex%40nine.testrun.org&n=Public%20Bots&i=QpBSronexvP&s=nAfQ0q_JomN"}, "New i.delta.chat invite link")),
8+
h("li", {}, h("a", {href: "geo:48.844,2.395"}, "geo-url link (geo:)")),
79
h("li", {}, h("a", {href: "cabal://cabal.chat"}, "Custom scheme link")),
810
h("li", {}, h("a", {href: "./page.html"}, "Link to an internal HTML page")),
911
h("li", {}, h("a", {href: "chrome://crash"}, "chrome://crash")),

0 commit comments

Comments
 (0)