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