fix: bind WebSocket and asset webservers only to the loopback address

This commit is contained in:
nekename committed 2026-10-04 14:18:14 +01:00
1 parent 2dd27bb9c1
commit a4cfec6c73
12 files changed
+21 -21

No files matched your search

+1 -1
View File
@@ -89,7 +89,7 @@ An `ActionContext` extends this with an action instance index for nested actions
### Plugin Communication ### Plugin Communication
- **WebSocket protocol**: Plugins/PIs connect to `localhost:PORT_BASE`, send JSON messages with `event` field - **WebSocket protocol**: Plugins/PIs connect to `127.0.0.1:PORT_BASE`, send JSON messages with `event` field
- **Message routing**: `inbound::InboundEventType` enum handles all incoming events, `outbound::` modules send to plugins - **Message routing**: `inbound::InboundEventType` enum handles all incoming events, `outbound::` modules send to plugins
- **Outbound event types**: `willAppear`, `keyDown`, `keyUp`, `dialRotate`, etc. (Stream Deck SDK compatible) - **Outbound event types**: `willAppear`, `keyDown`, `keyUp`, `dialRotate`, etc. (Stream Deck SDK compatible)
- **Authentication**: Context validation ensures plugins can only access their own action instances - **Authentication**: Context validation ensures plugins can only access their own action instances
+7 -7
View File
@@ -334,7 +334,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys 0.61.2", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@@ -897,9 +897,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]] [[package]]
name = "openaction" name = "openaction"
version = "2.6.0" version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14fef1b3f886c87c86633bf200062c4e56e48b12b8c49d35beab29ad0c49b66b" checksum = "336948ccb035d932ca20347c83c549e8dc6ef64a66e6329b2707b9cb010cc133"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"dashmap", "dashmap",
@@ -945,7 +945,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967" checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys 0.61.2", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@@ -1151,7 +1151,7 @@ dependencies = [
"errno", "errno",
"libc", "libc",
"linux-raw-sys 0.11.0", "linux-raw-sys 0.11.0",
"windows-sys 0.61.2", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@@ -1318,7 +1318,7 @@ dependencies = [
"getrandom", "getrandom",
"once_cell", "once_cell",
"rustix 1.1.3", "rustix 1.1.3",
"windows-sys 0.61.2", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@@ -1748,7 +1748,7 @@ version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [ dependencies = [
"windows-sys 0.61.2", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@@ -12,7 +12,7 @@
return; return;
} }
const websocket = new WebSocket("ws://localhost:" + inPort); const websocket = new WebSocket("ws://127.0.0.1:" + inPort);
websocket.onopen = () => { websocket.onopen = () => {
websocket.send( websocket.send(
JSON.stringify({ JSON.stringify({
@@ -5,7 +5,7 @@
let update = () => {}; let update = () => {};
function connectElgatoStreamDeckSocket(inPort, inPropertyInspectorUUID, inRegisterEvent, inInfo, inActionInfo) { function connectElgatoStreamDeckSocket(inPort, inPropertyInspectorUUID, inRegisterEvent, inInfo, inActionInfo) {
const websocket = new WebSocket("ws://localhost:" + inPort); const websocket = new WebSocket("ws://127.0.0.1:" + inPort);
inActionInfo = JSON.parse(inActionInfo); inActionInfo = JSON.parse(inActionInfo);
websocket.onopen = () => { websocket.onopen = () => {
websocket.send( websocket.send(
@@ -5,7 +5,7 @@
let update = () => {}; let update = () => {};
function connectElgatoStreamDeckSocket(inPort, inPropertyInspectorUUID, inRegisterEvent, inInfo, inActionInfo) { function connectElgatoStreamDeckSocket(inPort, inPropertyInspectorUUID, inRegisterEvent, inInfo, inActionInfo) {
const websocket = new WebSocket("ws://localhost:" + inPort); const websocket = new WebSocket("ws://127.0.0.1:" + inPort);
inActionInfo = JSON.parse(inActionInfo); inActionInfo = JSON.parse(inActionInfo);
websocket.onopen = () => { websocket.onopen = () => {
websocket.send( websocket.send(
@@ -5,7 +5,7 @@
let update = () => {}; let update = () => {};
function connectElgatoStreamDeckSocket(inPort, inPropertyInspectorUUID, inRegisterEvent, inInfo, inActionInfo) { function connectElgatoStreamDeckSocket(inPort, inPropertyInspectorUUID, inRegisterEvent, inInfo, inActionInfo) {
const websocket = new WebSocket("ws://localhost:" + inPort); const websocket = new WebSocket("ws://127.0.0.1:" + inPort);
inActionInfo = JSON.parse(inActionInfo); inActionInfo = JSON.parse(inActionInfo);
websocket.onopen = () => { websocket.onopen = () => {
websocket.send( websocket.send(
@@ -5,7 +5,7 @@
let update = () => {}; let update = () => {};
function connectElgatoStreamDeckSocket(inPort, inPropertyInspectorUUID, inRegisterEvent, inInfo, inActionInfo) { function connectElgatoStreamDeckSocket(inPort, inPropertyInspectorUUID, inRegisterEvent, inInfo, inActionInfo) {
const websocket = new WebSocket("ws://localhost:" + inPort); const websocket = new WebSocket("ws://127.0.0.1:" + inPort);
inActionInfo = JSON.parse(inActionInfo); inActionInfo = JSON.parse(inActionInfo);
websocket.onopen = () => { websocket.onopen = () => {
websocket.send( websocket.send(
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"identifier": "corsfetch", "identifier": "corsfetch",
"local": true, "local": true,
"remote": { "urls": ["http://localhost:*"] }, "remote": { "urls": ["http://127.0.0.1:*"] },
"windows": ["*"], "windows": ["*"],
"permissions": ["cors-fetch:default"] "permissions": ["cors-fetch:default"]
} }
+4 -4
View File
@@ -39,8 +39,8 @@ static INSTANCES: LazyLock<Mutex<HashMap<String, PluginInstance>>> = LazyLock::n
pub static PORT_BASE: LazyLock<u16> = LazyLock::new(|| { pub static PORT_BASE: LazyLock<u16> = LazyLock::new(|| {
let mut base = 57116; let mut base = 57116;
loop { loop {
let websocket_result = std::net::TcpListener::bind(format!("0.0.0.0:{}", base)); let websocket_result = std::net::TcpListener::bind(format!("127.0.0.1:{}", base));
let webserver_result = std::net::TcpListener::bind(format!("0.0.0.0:{}", base + 2)); let webserver_result = std::net::TcpListener::bind(format!("127.0.0.1:{}", base + 2));
if websocket_result.is_ok() && webserver_result.is_ok() { if websocket_result.is_ok() && webserver_result.is_ok() {
log::debug!("Using ports {} and {}", base, base + 2); log::debug!("Using ports {} and {}", base, base + 2);
break; break;
@@ -212,7 +212,7 @@ pub async fn initialise_plugin(path: path::PathBuf, spawner_tx: mpsc::Sender<Spa
]; ];
if code_path.to_lowercase().ends_with(".html") || code_path.to_lowercase().ends_with(".htm") || code_path.to_lowercase().ends_with(".xhtml") { if code_path.to_lowercase().ends_with(".html") || code_path.to_lowercase().ends_with(".htm") || code_path.to_lowercase().ends_with(".xhtml") {
let url = format!("http://localhost:{}/", *PORT_BASE + 2) + path.join(code_path).to_str().unwrap(); let url = format!("http://127.0.0.1:{}/", *PORT_BASE + 2) + path.join(code_path).to_str().unwrap();
let window = tauri::WebviewWindowBuilder::new(APP_HANDLE.get().unwrap(), plugin_uuid.replace('.', "_"), tauri::WebviewUrl::External(url.parse()?)) let window = tauri::WebviewWindowBuilder::new(APP_HANDLE.get().unwrap(), plugin_uuid.replace('.', "_"), tauri::WebviewUrl::External(url.parse()?))
.title(manifest.name) .title(manifest.name)
.visible(false) .visible(false)
@@ -516,7 +516,7 @@ pub fn initialise_plugins() {
/// Start the WebSocket server that plugins communicate with. /// Start the WebSocket server that plugins communicate with.
async fn init_websocket_server() { async fn init_websocket_server() {
let listener = match TcpListener::bind(format!("0.0.0.0:{}", *PORT_BASE)).await { let listener = match TcpListener::bind(format!("127.0.0.1:{}", *PORT_BASE)).await {
Ok(listener) => listener, Ok(listener) => listener,
Err(error) => { Err(error) => {
error!("Failed to bind plugin WebSocket server to socket: {}", error); error!("Failed to bind plugin WebSocket server to socket: {}", error);
+1 -1
View File
@@ -18,7 +18,7 @@ fn mime(extension: &str) -> String {
pub async fn init_webserver(prefix: PathBuf) { pub async fn init_webserver(prefix: PathBuf) {
let prefix = prefix.canonicalize().unwrap(); let prefix = prefix.canonicalize().unwrap();
let server = { let server = {
let listener = std::net::TcpListener::bind(format!("0.0.0.0:{}", *super::PORT_BASE + 2)).unwrap(); let listener = std::net::TcpListener::bind(format!("127.0.0.1:{}", *super::PORT_BASE + 2)).unwrap();
#[cfg(windows)] #[cfg(windows)]
{ {
+1 -1
View File
@@ -61,7 +61,7 @@
} }
], ],
"security": { "security": {
"csp": "default-src 'self'; style-src 'self' 'unsafe-inline'; img-src * data:; frame-src http://localhost:*; script-src 'self' 'unsafe-inline'; connect-src ipc: http://ipc.localhost https://openactionapi.github.io https://api.github.com https://raw.githubusercontent.com https://plugins.amankhanna.me;" "csp": "default-src 'self'; style-src 'self' 'unsafe-inline'; img-src * data:; frame-src http://127.0.0.1:*; script-src 'self' 'unsafe-inline'; connect-src ipc: http://ipc.localhost https://openactionapi.github.io https://api.github.com https://raw.githubusercontent.com https://plugins.amankhanna.me;"
}, },
"withGlobalTauri": true "withGlobalTauri": true
} }
+1 -1
View File
@@ -14,5 +14,5 @@ export function getWebSocketPort(): number {
} }
export function getWebserverUrl(path: string = ""): string { export function getWebserverUrl(path: string = ""): string {
return `http://localhost:${portBase + 2}/${path}`; return `http://127.0.0.1:${portBase + 2}/${path}`;
} }