refactor(examples): improve security when rendering HTML strings [TRI-003] (#14)

This commit is contained in:
Lucas Nogueira 2022-01-09 14:35:30 -03:00
parent 680554de3e
commit 2a7bf6d912
No known key found for this signature in database
GPG Key ID: 2714B66BCFB01F7F
7 changed files with 105 additions and 86 deletions

View File

@ -90,25 +90,28 @@
let selected = views[0];
let responses = writable([]);
let response = ''
function select(view) {
selected = view;
}
function onMessage(value) {
responses.update(r => [`[${new Date().toLocaleTimeString()}]` + ': ' + (typeof value === "string" ? value : JSON.stringify(value)), ...r])
responses.update(r => [{ text: `[${new Date().toLocaleTimeString()}]` + ': ' + (typeof value === "string" ? value : JSON.stringify(value)) }, ...r])
}
// this function is renders HTML without sanitizing it so it's insecure
// we only use it with our own input data
function insecureRenderHtml(html) {
responses.update(r => [{ html }, ...r])
}
function clear() {
responses.update(() => []);
}
function onLogoClick() {
open("https://tauri.studio/");
}
onMount(() => {
responses.subscribe(r => {
response = r.join('\n')
})
})
</script>
<main>
@ -136,16 +139,20 @@
{/each}
</div>
<div class="content">
<svelte:component this={selected.component} {onMessage} />
<svelte:component this={selected.component} {onMessage} {insecureRenderHtml} />
</div>
</div>
<div id="response" style="white-space: pre-line">
<p class="flex row just-around">
<strong>Tauri Console</strong>
<span class="nv" on:click={()=> {
responses.update(() => []);
}}>clear</span>
<span class="nv" on:click={clear}>clear</span>
</p>
{@html response}
{#each $responses as r}
{#if r.text}
<p>{r.text}</p>
{:else}
{@html r.html}
{/if}
{/each}
</div>
</main>

View File

@ -3,6 +3,7 @@
import { readBinaryFile } from "@tauri-apps/api/fs";
export let onMessage;
export let insecureRenderHtml;
let defaultPath = null;
let filter = null;
let multiple = false;
@ -51,7 +52,7 @@
new Uint8Array(response),
function (base64) {
var src = "data:image/png;base64," + base64;
onMessage('<img src="' + src + '"></img>');
insecureRenderHtml('<img src="' + src + '"></img>');
}
);
} else {

View File

@ -3,6 +3,7 @@
import { convertFileSrc } from "@tauri-apps/api/tauri";
export let onMessage;
export let insecureRenderHtml;
let pathToRead = "";
let img;
@ -42,11 +43,11 @@
if (pathToRead.includes(".png") || pathToRead.includes(".jpg")) {
arrayBufferToBase64(new Uint8Array(response), function (base64) {
const src = "data:image/png;base64," + base64;
onMessage('<img src="' + src + '"></img>');
insecureRenderHtml('<img src="' + src + '"></img>');
});
} else {
const value = String.fromCharCode.apply(null, response);
onMessage(
insecureRenderHtml(
'<textarea id="file-response" style="height: 400px"></textarea><button id="file-save">Save</button>'
);
setTimeout(() => {

View File

@ -1,5 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<style>
#response {
white-space: pre-wrap;
}
</style>
</head>
<body>
<div id="window-label"></div>
<div id="container"></div>
@ -10,14 +19,14 @@
var thisTauriWindow = window.__TAURI__.window.getCurrent()
var windowLabel = thisTauriWindow.label
var windowLabelContainer = document.getElementById('window-label')
windowLabelContainer.innerHTML = 'This is the ' + windowLabel + ' window.'
windowLabelContainer.innerText = 'This is the ' + windowLabel + ' window.'
var container = document.getElementById('container')
function createWindowMessageBtn(label) {
var tauriWindow = WebviewWindow.getByLabel(label)
var button = document.createElement('button')
button.innerHTML = 'Send message to ' + label
button.innerText = 'Send message to ' + label
button.addEventListener('click', function () {
tauriWindow.emit('clicked', 'message from ' + windowLabel)
})
@ -27,7 +36,7 @@
// global listener
window.__TAURI__.event.listen('clicked', function (event) {
responseContainer.innerHTML +=
'Got ' + JSON.stringify(event) + ' on global listener<br><br>'
'Got ' + JSON.stringify(event) + ' on global listener\n\n'
})
window.__TAURI__.event.listen('tauri://window-created', function (event) {
createWindowMessageBtn(event.payload.label)
@ -36,8 +45,8 @@
var responseContainer = document.getElementById('response')
// listener tied to this window
thisTauriWindow.listen('clicked', function (event) {
responseContainer.innerHTML +=
'Got ' + JSON.stringify(event) + ' on window listener<br><br>'
responseContainer.innerText +=
'Got ' + JSON.stringify(event) + ' on window listener\n\n'
})
var createWindowButton = document.createElement('button')
@ -71,4 +80,5 @@
}
</script>
</body>
</html>

View File

@ -13,7 +13,7 @@
const div = document.querySelector('div')
window.__TAURI__.event.listen('message', (event) => {
const p = document.createElement('p')
p.innerHTML = event.payload
p.innerText = event.payload
div.appendChild(p)
})
</script>

View File

@ -13,7 +13,7 @@
const div = document.querySelector('div')
window.__TAURI__.event.listen('message', (event) => {
const p = document.createElement('p')
p.innerHTML = event.payload
p.innerText = event.payload
div.appendChild(p)
})
</script>

View File

@ -31,7 +31,7 @@
const responseContainer = document.querySelector('#response')
function updateResponse(response) {
responseContainer.innerHTML =
responseContainer.innerText =
typeof response === 'string' ? response : JSON.stringify(response)
}