Move bulk to react-sdk and reference it from riot-web land
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
parent
627a4d4ea4
commit
4ed27a4ba6
3 changed files with 88 additions and 0 deletions
27
docs/usercontent.md
Normal file
27
docs/usercontent.md
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# Usercontent
|
||||||
|
|
||||||
|
While decryption itself is safe to be done without a sandbox,
|
||||||
|
letting the browser and user interact with the resulting data may be dangerous,
|
||||||
|
previously `usercontent.riot.im` was used to act as a sandbox on a different origin to close the attack surface,
|
||||||
|
it is now possible to do by using a combination of a sandboxed iframe and some code written into the app which consumes this SDK.
|
||||||
|
|
||||||
|
Usercontent is an iframe sandbox target for allowing a user to safely download a decrypted attachment from a sandboxed origin where it cannot be used to XSS your riot session out from under you.
|
||||||
|
|
||||||
|
Its function is to create an Object URL for the user/browser to use but bound to an origin different to that of the riot instance to protect against XSS.
|
||||||
|
|
||||||
|
It exposes a function over a postMessage API, when sent an object with the matching fields to render a download link with the Object URL:
|
||||||
|
|
||||||
|
```json5
|
||||||
|
{
|
||||||
|
"imgSrc": "", // the src of the image to display in the download link
|
||||||
|
"imgStyle": "", // the style to apply to the image
|
||||||
|
"style": "", // the style to apply to the download link
|
||||||
|
"download": "", // download attribute to pass to the <a/> tag
|
||||||
|
"textContent": "", // the text to put inside the download link
|
||||||
|
"blob": "", // the data blob to wrap in an object url and allow the user to download
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If only imgSrc, imgStyle and style are passed then just update the existing link without overwriting other things about it.
|
||||||
|
|
||||||
|
It is expected that this target be available at `usercontent/` relative to the root of the app, this can be seen in riot-web's webpack config.
|
12
src/usercontent/index.html
Normal file
12
src/usercontent/index.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!--
|
||||||
|
Hello! If you're reading this, perhaps you're wondering what this
|
||||||
|
file is doing and why your Riot is using it.
|
||||||
|
In short, this allows Riot to isolate potentially unsafe encrypted
|
||||||
|
attachments into their own origin, away from your Riot.
|
||||||
|
Stay curious!
|
||||||
|
-->
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
49
src/usercontent/index.js
Normal file
49
src/usercontent/index.js
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
var params = window.location.search.substring(1).split('&');
|
||||||
|
var lockOrigin;
|
||||||
|
for (var i = 0; i < params.length; ++i) {
|
||||||
|
var parts = params[i].split('=');
|
||||||
|
if (parts[0] === 'origin') lockOrigin = decodeURIComponent(parts[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function remoteRender(event) {
|
||||||
|
const data = event.data;
|
||||||
|
|
||||||
|
const img = document.createElement("img");
|
||||||
|
img.id = "img";
|
||||||
|
img.src = data.imgSrc;
|
||||||
|
img.style = data.imgStyle;
|
||||||
|
|
||||||
|
const a = document.createElement("a");
|
||||||
|
a.id = "a";
|
||||||
|
a.rel = "noopener";
|
||||||
|
a.target = "_blank";
|
||||||
|
a.download = data.download;
|
||||||
|
a.style = data.style;
|
||||||
|
a.style.fontFamily = "Arial, Helvetica, Sans-Serif";
|
||||||
|
a.href = window.URL.createObjectURL(data.blob);
|
||||||
|
a.appendChild(img);
|
||||||
|
a.appendChild(document.createTextNode(data.textContent));
|
||||||
|
|
||||||
|
const body = document.body;
|
||||||
|
// Don't display scrollbars if the link takes more than one line to display.
|
||||||
|
body.style = "margin: 0px; overflow: hidden";
|
||||||
|
body.appendChild(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
function remoteSetTint(event) {
|
||||||
|
const data = event.data;
|
||||||
|
|
||||||
|
const img = document.getElementById("img");
|
||||||
|
img.src = data.imgSrc;
|
||||||
|
img.style = data.imgStyle;
|
||||||
|
|
||||||
|
const a = document.getElementById("a");
|
||||||
|
a.style = data.style;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onmessage = function(e) {
|
||||||
|
if (lockOrigin === undefined || e.origin === lockOrigin) {
|
||||||
|
if (e.data.blob) remoteRender(e);
|
||||||
|
else remoteSetTint(e);
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in a new issue