You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+13Lines changed: 13 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,6 +9,11 @@
9
9
* Shared WASM compilation module `tests/build_utils.py` to enforce `--allow-undefined` linker flags globally across all plugin builds.
10
10
* Automated target binary copying and caching for Linux production builds.
11
11
* Custom structured issue templates (Bug Report, Feature Request, Plugin Submission) and a Pull Request template in `.github/`.
12
+
* Platform-agnostic OS detection FFI `host_get_platform` returning compile-time host platform evaluation (0 for Windows, 1 for Linux) to eliminate brittle environment variable parsing.
13
+
* Linux shell executor backend (`sh.rs`) executing `/bin/sh -c` queries for the `pTerm` plugin.
14
+
* Shell blacklisting security reinforcement: added `dash` shell to the banned executable list in the sandbox to block unauthorized access by untrusted plugins.
15
+
* Shared `get_plugins_dir()` utility in `utils.rs` for consistent cross-platform plugin storage path resolution (`$HOME/.plug/plugins` on Linux, `%SystemDrive%\.plug\plugins` on Windows).
16
+
* Permission gates for `get_env` and `net_post` WASM host imports — load-time import validation and runtime call-time enforcement against `plugin.toml` declarations.
12
17
13
18
### Fixed
14
19
* Linux CI cross-compilation failure (`x86_64-pc-windows-gnu` target) — removed orphaned `.cargo/config.toml` that forced incorrect target resolution on Linux runners.
@@ -21,6 +26,14 @@
21
26
* Linux production linker `undefined reference to 'g_headless_mode'` — guarded `extern "C"` declaration in `main_l.cpp` under `#ifdef PLUG_ENABLE_HEADLESS_MODE`; production builds now use `static constexpr bool g_headless_mode = false` with zero runtime cost.
* Process hang on `/e` exit in headless mode — `g_cmd_thread` was blocking indefinitely on `g_cmd_cv.wait()`; `main_l_cleanup()` now sets `g_cmd_thread_running = false`, notifies the CV, and joins the thread before returning so the process exits cleanly within the test timeout window.
29
+
* Headless CI broken pipe (`test_cli_lifecycle`) — moved `g_cmd_thread` and `g_headless_stdin_thread` startup from `on_tick()` frame-clock callback to `on_activate()` so stdin reader is live before any test data arrives; frame-clock callbacks are not guaranteed to fire before GApplication idle-hold expires under `xvfb-run`.
30
+
* Linux `test_sandbox_rules` 120s timeout — plugin directory was hardcoded to `C:\.plug\plugins` (Windows-only); corrected to `$HOME/.plug/plugins` matching `proc.rs``c_init()` runtime logic.
31
+
* FFI Windows-centric symbol leakage — renamed `main_w_add_tab` to platform-neutral `host_add_tab` across `plugin_mgr.rs`, pTerm manifests, source plugin files, and test mocks (`ok_plugin.rs`, `rogue_plugin.rs`, `rogue_plugin_runtime.rs`) to prevent load-time link failures.
32
+
*`pTerm` Linux shell execution compatibility — resolved execution errors on Linux hosts by adding `/sh` routing to the command parser, introducing the Linux shell backend, defaulting shell mode dynamically on Unix targets, and mapping E2E test assertions to platform-specific outputs.
33
+
* Linux plugin install/delete path mismatch — `/plug` and `/plug-` handlers in `c_plug/mod.rs` and `c_plug/del/mod.rs` were hardcoded to `%SystemDrive%\.plug\plugins` (Windows-only); aligned with `c_init()` using shared `get_plugins_dir()` so Linux installs to `$HOME/.plug/plugins`.
34
+
* Plugin dispatch race condition — `dispatch_plugin_cmd()` no longer removes the plugin instance from the in-memory registry during async execution; per-plugin execution locks serialize concurrent invocations instead.
35
+
* README and startup banner exit command typo — corrected `/e-` references to `/e` in `main.cpp` and `main_l.cpp`.
36
+
* FFI input sanitization — `c_parse()` routes command arguments through `to_c_string()` to strip embedded null bytes before CString conversion.
Copy file name to clipboardExpand all lines: docs/ARCHITECTURE.md
+3-35Lines changed: 3 additions & 35 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -18,46 +18,14 @@ The framework splits operations into two layers connected via C FFI:
18
18
19
19
### C++ Functions (Called by Rust / Plugins)
20
20
-`main_*_print_info(str)` / `main_*_print_error(str)`: Output logs to active text buffers.
21
-
-`main_*_add_tab(name)`: Spawns a new tab context.
21
+
-`main_*_add_tab(name)`: Spawns a new tab context. Note that the WASM FFI layer exposes a platform-neutral import named `host_add_tab` which the host runtime routes to these platform-specific functions.
22
22
-`main_*_set_prompt_visibility(visible)`: Controls standard input prompt fields.
-`main_*_get_tab_owner(idx, buf, max_len)` / `main_*_set_tab_owner(idx, name)`: Syncs tab ownership state. The `get` function writes the owner string into `buf` up to `max_len` to ensure buffer safety and avoid ABI crashes.
24
24
25
25
---
26
26
27
27
## Command Routing & Permissions
28
28
29
29
Inputs starting with `/` invoke built-in commands (e.g., `/tab` or `/plug`). Other inputs are dispatched to the WASM plugin owning the active tab.
30
30
31
-
If a plugin requests access to sensitive FFI imports (such as `host_exec` to run local shell subprocesses), the runtime validates its manifest permissions list (`plugin.toml`) before delegating the call to the host OS.
32
-
33
-
---
34
-
35
-
## Security Model & Sandbox Limits
36
-
37
-
### 1. The FFI Gate Architecture
38
-
The WebAssembly sandbox isolates memory space and prevents direct OS API execution. System capabilities are exposed exclusively through imported FFI functions. The core runtime acts as a **binary gate**:
39
-
- When a plugin attempts an operation (e.g., `host_exec`), the host runtime checks if the permission is listed in the plugin's manifest.
40
-
-**Escape Vector by Design**: If a plugin is granted `host_exec` permission, the WASM boundary is crossed. A plugin with `host_exec` can potentially launch processes and interact with the host OS, making it a critical capability.
41
-
42
-
### 2. Execution Containment for Untrusted Plugins
43
-
For third-party or untrusted plugins that require `host_exec` to run specific external tasks, the host runtime applies strict validation checks:
44
-
-**Interpreter / LOLBin Ban**: Common shell binaries (`cmd.exe`, `powershell.exe`, `bash`, `python`) and code-execution LOLBins (`rundll32.exe`, `regsvr32.exe`) are explicitly banned.
45
-
-**Canonical-Path Allowlist**: The target binary's canonical path must be explicitly mapped in the plugin manifest's `allowed_commands`.
46
-
-**Regex Argument Filtering**: The command line arguments are evaluated against a linear-time regex pattern declared in the manifest.
47
-
48
-
### 3. Trust Tiers & Shell Emulator Bypass
49
-
Core system utilities (like the shell terminal emulator `pTerm`) require execution of host shells to operate:
50
-
-**Compile-Time Hash Pinning**: During compilation, the builder script computes the SHA-256 hash of the compiled `pTerm.wasm` binary and embeds it directly into the host Rust library (`plugin_mgr.rs` via `pterm_hash.txt`).
51
-
-**Trust Bypass**: If a plugin's SHA-256 matches this hardcoded trust list (`TRUSTED_PLUGIN_HASHES`), it is marked as `is_trusted`. Trusted plugins bypass the interpreter bans and allowlist validations inside `host_exec`.
52
-
-**Tamper Protection**: If a trusted plugin is modified, its hash changes. It falls back to the standard flow, requiring an `.integrity` file, and is blocked if tampered.
53
-
54
-
### 4. Cryptographic Integrity Validation
55
-
-**Single-Read Verification**: To mitigate TOCTOU (Time-of-Check to Time-of-Use) filesystem attacks, plugin binaries are read into memory in a single syscall. The runtime computes the SHA-256 hash of this memory buffer and verifies it against the sidecar before Wasmer compiles it.
56
-
-**Atomic Sidecar Writes**: Plugin installations write both the WASM binary and `.integrity` file to temporary files, followed by an atomic rename to prevent corrupted states.
57
-
-**Registry Hash Pinning**: Remote plugin downloads are validated against SHA-256 hashes pinned in the official registry (`pluglists.json`) to prevent MITM attacks.
58
-
-**Global Migration**: Pre-existing plugins are backfilled with `.integrity` files on startup, and a global marker is written. Post-migration, any loaded plugin lacking a valid `.integrity` sidecar is blocked.
- The unsoundness vulnerability in `memmap2` (`RUSTSEC-2026-0186` for versions `< 0.9.11`) is currently ignored in [.cargo/audit.toml](file:///O:/prj/p01/.wip/plug/plug.app/rt/.cargo/audit.toml) because our current Wasmer version does not invoke the unsound functions (`advise_range` or `flush_range`).
63
-
-**Upgrade Checklist**: Every time `wasmer` is upgraded, the developers must audit if the new Wasmer version invokes these `memmap2` range advising/flushing routines. If it does, `memmap2` must be upgraded to a safe patched version (e.g. `>= 0.9.11`) or Wasmer must be configured to bypass those calls to maintain full system safety.
31
+
If a plugin requests access to sensitive FFI imports (such as `host_exec` to run local shell subprocesses, `get_env` to read environment variables, or `net_post` for outbound HTTP), the runtime validates its manifest permissions list (`plugin.toml`) at load time and again at call time before delegating to the host OS.
Copy file name to clipboardExpand all lines: docs/TESTING_SYSTEM.md
+7-7Lines changed: 7 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -29,15 +29,15 @@ tests/
29
29
30
30
To distinguish target environment mismatches from code failures, `preflight.py` executes before the orchestrator to verify requirements:
31
31
-**Rust Target**: Verifies `wasm32-unknown-unknown` target is installed via `rustup target list --installed`. If missing, installs it or halts with setup instructions.
32
-
-**Version Ranges**: Checks that `cargo`and `wasmer` match the verified toolchain versions (defined as hardcoded constants inside `preflight.py`) to prevent flaky behavior.
32
+
-**Version Ranges**: Checks that `cargo`is present and reports the configured minimum cargo version from `preflight.py`.
33
33
-**Zero-Dependency Path-Based Orphan Cleanup**:
34
34
- To avoid installing third-party Python modules like `psutil` in CI/dev setups, path lookup uses native command utilities.
35
35
-**Windows**: Invokes `powershell "Get-Process plug -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Path"` to retrieve the executable path of matching active processes.
36
36
-**Linux**: Reads `/proc/<pid>/exe` using `os.readlink()` for processes owned by the current user.
37
37
- If a process matches the exact absolute target path of our compiled build binary in the workspace, it is terminated.
- Binary names: `plug.exe` (Windows) vs `plug` (Linux).
40
-
-Executable permissions: Performs `chmod +x` on Unix targets.
39
+
- Binary names: `plug-{arch}.exe` (Windows) vs `plug-{arch}` (Linux).
40
+
-Release directories: `plug.cross/release/{arch}` on Windows and `plug.cross/release/x86_64` for Linux x64.
41
41
- Path separator configurations.
42
42
-**Output**: Generates a unified `EnvContext` JSON object containing all pathing and platform context, which is forwarded to subsequent test scripts.
43
43
@@ -65,7 +65,7 @@ Manifest configurations (`plugin.toml`) define the permission scope of the WASM
65
65
```toml
66
66
[[plugin]]
67
67
name = "ok_plugin"
68
-
permissions = ["main_w_add_tab", "host_exec"]
68
+
permissions = ["host_add_tab", "host_exec"]
69
69
```
70
70
-**`rogue_plugin` Manifest (Load-time)**:
71
71
```toml
@@ -76,7 +76,7 @@ Manifest configurations (`plugin.toml`) define the permission scope of the WASM
76
76
77
77
WASM files check:
78
78
-**`ok_plugin.rs`**: Baseline plugin using permitted FFI calls. Verifies normal operations and prevents false-positive test results.
79
-
-**`rogue_plugin.rs`** (Load-time check): A plugin containing host imports not declared in its `plugin.toml` manifest permissions. Verifies that the Wasmer runtime successfully rejects module initialization.
79
+
-**`rogue_plugin.rs`** (Load-time check): A plugin containing host imports not declared in its `plugin.toml` manifest permissions (e.g. `host_add_tab`, `get_env`, `net_post`). Verifies that the Wasmer runtime successfully rejects module initialization.
80
80
-**`rogue_plugin_runtime.rs`** (Runtime check): A plugin with valid import declarations that calls `host_exec` with arguments exceeding its permission scope (or attempts prohibited actions). Verifies that the runtime correctly catches and traps the thread during runtime execution.
-`ok_plugin integrity mismatch check` (tampered WASM with stale `.integrity` sidecar is blocked).
96
96
-`Global migration and post-migration bypass checks` (**Plan Cases A & B**: one-time global migration backfill validation and post-migration missing sidecar blocking).
97
-
-`Trusted plugin bypass integrity file check` (**Plan Case C**: verifies `pTerm` with valid compiled hash loads successfully without sidecar and executes a real `dir` command via `host_exec`).
98
-
-`Tampered trusted plugin block check` (**Plan Case D**: verifies tampered `pTerm` is blocked and fails-closed).
97
+
-`Trusted plugin bypass integrity file check`
98
+
-`Tampered trusted plugin block check`
99
99
100
100
### 3.5 End-to-End Tests (`tests/e2e/`)
101
101
-**`test_cli_lifecycle.py`**: Spawns the production compiled `plug` executable under test scenarios using `subprocess.Popen` with `HIDE_CONSOLE=ON` (the standard production build configuration to ensure we test the identical binary shipped).
-**Trust Tier**: Recognized as a trusted core utility by matching the compile-time hardcoded SHA-256 hash list. Bypasses the sandbox interpreter bans (shells block) and canonical-path allowlist checks.
12
12
13
13
---
@@ -27,9 +27,9 @@ The diagram below illustrates the exact control flow when a user runs a shell co
0 commit comments