Skip to content

Commit cfc66d5

Browse files
committed
feat(web-host): add link to source of plugin, sanitizing plugin name
1 parent f778ab6 commit cfc66d5

File tree

4 files changed

+44
-2
lines changed

4 files changed

+44
-2
lines changed

packages/web-host/src/components/ReplHistory.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,22 @@ export function ReplHistory({
1919
{history.map((entry, index) => (
2020
// biome-ignore lint/suspicious/noArrayIndexKey: no unique key
2121
<Fragment key={index}>
22-
{"stdin" in entry && entry.stdin && (
22+
{"stdin" in entry && entry.stdin && !entry.allowHtml && (
2323
<pre
2424
className="bg-gray-50 whitespace-pre-wrap word-break-word"
2525
data-stdtype="stdin"
2626
>
2727
{entry.stdin}
2828
</pre>
2929
)}
30+
{"stdin" in entry && entry.stdin && entry.allowHtml && (
31+
<pre
32+
className="bg-gray-50 whitespace-pre-wrap word-break-word"
33+
data-stdtype="stdin"
34+
// biome-ignore lint/security/noDangerouslySetInnerHtml: need to pass `allowHtml:true` to the addReplHistoryEntry function - only used for adding links to source of plugins when loaded
35+
dangerouslySetInnerHTML={{ __html: entry.stdin }}
36+
/>
37+
)}
3038
{"stdout" in entry && entry.stdout && (
3139
<pre
3240
className="bg-green-100 whitespace-pre-wrap before:content-[attr(data-status)] relative before:absolute before:right-0 before:top-0 word-break-word"

packages/web-host/src/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ export type ReplHistoryEntry =
1919
}
2020
| {
2121
stdin: string;
22+
allowHtml?: boolean;
2223
};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const pluginSourceUrlMapping = {
2+
echo: "https://github.com/topheman/webassembly-component-model-experiments/tree/master/crates/plugin-echo",
3+
weather:
4+
"https://github.com/topheman/webassembly-component-model-experiments/tree/master/crates/plugin-weather",
5+
greet:
6+
"https://github.com/topheman/webassembly-component-model-experiments/tree/master/crates/plugin-greet",
7+
ls: "https://github.com/topheman/webassembly-component-model-experiments/tree/master/crates/plugin-ls",
8+
cat: "https://github.com/topheman/webassembly-component-model-experiments/tree/master/crates/plugin-cat",
9+
echoc:
10+
"https://github.com/topheman/webassembly-component-model-experiments/blob/master/c_modules/plugin-echo/component.c",
11+
} as const;
12+
13+
export function getPluginSourceUrl(
14+
pluginName: keyof typeof pluginSourceUrlMapping | (string & {}),
15+
) {
16+
if (pluginName in pluginSourceUrlMapping) {
17+
return pluginSourceUrlMapping[
18+
pluginName as keyof typeof pluginSourceUrlMapping
19+
];
20+
}
21+
return null;
22+
}

packages/web-host/src/wasm/engine.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { _setPluginsNames as hostStateSetPluginsNames } from "repl:api/host-state";
22
import type { HostApi, PluginApi, ReplHistoryEntry } from "../types";
3+
import { getPluginSourceUrl } from "../utils/github";
34

45
type AddReplHistoryEntryProp = {
56
addReplHistoryEntry: (entry: ReplHistoryEntry) => void;
@@ -43,8 +44,18 @@ async function loadPlugins({
4344
import("./generated/plugin-echo-c/transpiled/plugin-echo-c.js"),
4445
]).then((plugins) =>
4546
plugins.map((plugin) => {
47+
// Since we `allowHtml`, which will `dangerouslySetInnerHTML`, we need to sanitize the plugin name
48+
// (a plugin author could attack by injecting a script tag)
49+
const sanitizedPluginName = plugin.plugin
50+
.name()
51+
.replace(/[^a-zA-Z0-9_-]/g, "");
52+
const sourceUrl = getPluginSourceUrl(sanitizedPluginName);
53+
const stdin = sourceUrl
54+
? `[Host] Loaded plugin: <a href="${sourceUrl}" title="View source of the plugin on GitHub">${sanitizedPluginName}</a>`
55+
: `[Host] Loaded plugin: ${sanitizedPluginName}`;
4656
addReplHistoryEntry({
47-
stdin: `[Host] Loaded plugin: ${plugin.plugin.name()}`,
57+
stdin,
58+
allowHtml: !!sourceUrl,
4859
});
4960
return plugin.plugin;
5061
}),

0 commit comments

Comments
 (0)