Browser Extension Plugins
The TLSN Extension has a plugin system that allows you to safely extend its functionality. The plugin system is based on Extism, which enables you to write plugins in the programming language of your choice. This page focuses on plugins written in TypeScript.
What Can You Do with Plugins?
Plugins can add new custom features to the extension by using built-in host functions, such as:
- Requesting private information from the browser, such as cookies and headers of one or more hostnames.
- Submitting a new notarization request.
- Redirecting a browsing window.
New features and capabilities will be added based on feedback from developers. Please reach out to us on Discord.
Templates and Examples
You can find a boilerplate template at tlsn-plugin-boilerplate, which is a great starting point. This repository explains how to compile and test Typescript plugins.
The examples folder contains more examples of TLSNotary plugins.
Configuration JSON
A plugin must include a configuration JSON file that describes its behavior and permissions.
export type PluginConfig = {
title: string; // The name of the plugin
description: string; // A description of the plugin's purpose
icon?: string; // A base64-encoded image string representing the plugin's icon (optional)
steps?: StepConfig[]; // An array describing the UI steps and behavior (see Step UI below) (optional)
hostFunctions?: string[];// Host functions that the plugin will have access to
cookies?: string[]; // Cookies the plugin will have access to, cached by the extension from specified hosts (optional)
headers?: string[]; // Headers the plugin will have access to, cached by the extension from specified hosts (optional)
requests: { method: string; url: string }[]; // List of requests that the plugin is allowed to make
notaryUrls?: string[]; // List of notary services that the plugin is allowed to use (optional)
proxyUrls?: string[]; // List of websocket proxies that the plugin is allowed to use (optional)
};
Step UI
The plugin system allows customization of the UI and the functionality of the side panel.
Step Configuration
The steps are declared in the JSON configuration:
type StepConfig = {
title: string; // Text for the step's title
description?: string; // OPTIONAL: Text for the step's description
cta: string; // Text for the step's call-to-action button
action: string; // The function name that this step will execute
prover?: boolean; // Boolean indicating if this step outputs a notarization
}
You need to implement the functionality of the steps in src/index.ts
. The function names must match the corresponding step names in the JSON configuration.
Host Functions
Host functions are specific behaviors provided by the extension that the plugin can call. Host function usage may vary depending on the language used to write the plugin.
redirect
Redirects the current tab to a different URL.
Example in JavaScript:
const { redirect } = Host.getFunctions();
const mem = Memory.fromString('https://x.com');
redirect(mem.offset);
notarize
Notarizes a request.
Example in JavaScript:
const { notarize } = Host.getFunctions();
const mem = Memory.fromString(JSON.stringify({
url: "https://...",
method: "GET",
headers: {
"authorization": "Bearer xxx",
"cookie": "lang=en; auth_token=xxx",
},
secretHeaders: [
"authorization: Bearer xxx",
"cookie: lang=en; auth_token=xxx",
],
getSecretBody: "parseResponse" // See redaction example below
}));
const idOffset = notarize(mem.offset);
const id = Memory.find(idOffset).readString();
Host.outputString(JSON.stringify(id)); // Outputs the notarization ID
Redaction
If the getSecretResponse
field of the notarize
host function call is set, the corresponding method will be called to parse the response of the request. Make sure to also export this function in the main
module declaration in index.d.ts
.
function parseResponse() {
const bodyString = Host.inputString();
const params = JSON.parse(bodyString);
const revealed = `"screen_name":"${params.screen_name}"`;
const selectionStart = bodyString.indexOf(revealed);
const selectionEnd = selectionStart + revealed.length;
const secretResps = [
bodyString.substring(0, selectionStart),
bodyString.substring(selectionEnd, bodyString.length),
];
Host.outputString(JSON.stringify(secretResps));
}