-
Notifications
You must be signed in to change notification settings - Fork 0
feat(windows): platform-aware title bar + WSL hooks #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| # Shell scripts must keep LF endings — a CRLF in the shebang breaks them under | ||
| # bash/WSL ("bad interpreter"). Applies to all hooks and shell helpers. | ||
| *.sh text eol=lf | ||
| *.zsh text eol=lf | ||
| *.bash text eol=lf | ||
|
|
||
| # Python hooks (e.g. mitmproxy addon) also run under Unix interpreters. | ||
| *.py text eol=lf |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,172 @@ | ||||||
| # Windows & WSL Setup | ||||||
|
|
||||||
| Setup, packaging, and WSL integration for running RedLog on Windows — plus how | ||||||
| to keep an operator's private activity out of the engagement record. | ||||||
|
|
||||||
| --- | ||||||
|
|
||||||
| ## 1. Prerequisites | ||||||
|
|
||||||
| RedLog uses the native module `better-sqlite3`, which must be compiled for | ||||||
| Electron's ABI (`npm run rebuild`). That needs a C/C++ toolchain. | ||||||
|
|
||||||
| | Requirement | Notes | | ||||||
| |---|---| | ||||||
| | **Node.js 20 or 22 (LTS)** | **Not 24+** — newer Node has no prebuilt `better-sqlite3` binary yet, forcing a source build. | | ||||||
| | **Visual Studio Build Tools** | Install the **"Desktop development with C++"** workload. | | ||||||
| | **Python 3** | Required by `node-gyp` for the native rebuild. | | ||||||
|
|
||||||
| ```powershell | ||||||
| # Build tools (then tick "Desktop development with C++" in the installer) | ||||||
| winget install Microsoft.VisualStudio.2022.BuildTools | ||||||
|
|
||||||
| # Node 22 LTS | ||||||
| winget install --id OpenJS.NodeJS.22 -e | ||||||
| ``` | ||||||
|
|
||||||
| > If you already have Node 24, remove it first (or use a version manager) so | ||||||
| > `node -v` reports 20.x or 22.x. | ||||||
|
|
||||||
| ### PowerShell notes | ||||||
|
|
||||||
| - Windows PowerShell 5.1 does **not** support `&&`. Either install PowerShell 7 | ||||||
| (`winget install Microsoft.PowerShell`, run as `pwsh`) or chain with | ||||||
| `cmd1; if ($?) { cmd2 }`. | ||||||
| - If `npm` in PowerShell reports *"running scripts is disabled"*, allow user | ||||||
| scripts once: `Set-ExecutionPolicy -Scope CurrentUser RemoteSigned`. | ||||||
|
|
||||||
| --- | ||||||
|
|
||||||
| ## 2. Build & run | ||||||
|
|
||||||
| ```powershell | ||||||
| npm install | ||||||
| npm run rebuild # compile better-sqlite3 for Electron's ABI | ||||||
| npm run dev # launch the app | ||||||
| npm run build # production compile (no installer) | ||||||
| ``` | ||||||
|
|
||||||
| --- | ||||||
|
|
||||||
| ## 3. Packaging (Windows installer) | ||||||
|
|
||||||
| Installers are produced by [electron-builder](https://www.electron.build) | ||||||
| (config: `electron-builder.yml`; the win target builds an NSIS installer and a | ||||||
| portable exe). Native deps are rebuilt for the target Electron automatically | ||||||
| during packaging. Releases are also produced by the GitHub Actions workflow | ||||||
| (`.github/workflows/release.yml`) on tags. | ||||||
|
|
||||||
| ```powershell | ||||||
| npm run build # compile main/preload/renderer | ||||||
| npx electron-builder --win # NSIS + portable -> dist\ | ||||||
| ``` | ||||||
|
|
||||||
| **First-run note:** electron-builder downloads `winCodeSign`, which contains | ||||||
| macOS symlinks. Extracting symlinks on Windows needs a privilege standard users | ||||||
| lack. With electron-builder 26 this generally works unattended; if you hit | ||||||
| *"Cannot create symbolic link"*, either enable Windows **Developer Mode** | ||||||
| (Settings → For developers) or run the packaging command once from an elevated | ||||||
| terminal to populate the cache — subsequent builds work without elevation. | ||||||
|
|
||||||
| Output (installer + `win-unpacked/`) lands in `dist/`. | ||||||
|
|
||||||
| --- | ||||||
|
|
||||||
| ## 4. WSL integration | ||||||
|
|
||||||
| Pentest tooling often runs in WSL. To let a WSL shell log into RedLog running on | ||||||
| Windows, two things must line up. | ||||||
|
|
||||||
| ### 4.1 Token/port location | ||||||
|
|
||||||
| RedLog writes `api-token` and `api-port` to the **Windows** user profile | ||||||
| (`%USERPROFILE%\.redlog\`), not WSL's Linux `$HOME`. The hook scripts resolve | ||||||
| this automatically via `%USERPROFILE%` + `wslpath` — note the profile folder | ||||||
| name can differ from `%USERNAME%`, so `%USERPROFILE%` is the reliable anchor. | ||||||
|
|
||||||
| ### 4.2 Networking — mirrored mode is required | ||||||
|
|
||||||
| The API binds `127.0.0.1` on Windows. Under the default WSL2 **NAT** networking, | ||||||
| WSL's `127.0.0.1` is a separate loopback and **cannot reach it**. Enable | ||||||
| **mirrored networking** so localhost is shared: | ||||||
|
|
||||||
| 1. Create `%USERPROFILE%\.wslconfig`: | ||||||
| ```ini | ||||||
| [wsl2] | ||||||
| networkingMode=mirrored | ||||||
| ``` | ||||||
| 2. `wsl --shutdown` (from Windows PowerShell), then reopen WSL. | ||||||
| 3. Verify: `wslinfo --networking-mode` → `mirrored`. | ||||||
|
|
||||||
| To revert, remove that line and `wsl --shutdown` again. | ||||||
|
|
||||||
| ### 4.3 Logging from WSL | ||||||
|
|
||||||
| Two helper scripts live in `hooks/`: | ||||||
|
|
||||||
| ```bash | ||||||
| # Diagnose the WSL -> RedLog link (env, token path, reachability, round-trip) | ||||||
| bash /mnt/c/Users/<you>/Desktop/REDLOG/hooks/wsl-redlog-test.sh | ||||||
|
|
||||||
| # Send an event from any script/hook (fire-and-forget; no-ops if unreachable) | ||||||
| hooks/redlog-send.sh "nmap -sV $TARGET" command_start | ||||||
| nmap -sV "$TARGET" | ||||||
| hooks/redlog-send.sh "nmap -sV $TARGET" command_end "{\"exit_code\":$?}" | ||||||
|
Comment on lines
+111
to
+114
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Make the hook path independent of the working directory. The example says this can be called from any script/hook, but 🤖 Prompt for AI Agents |
||||||
| ``` | ||||||
|
|
||||||
| `redlog-send.sh` resolves the token path (native or WSL), probes a reachable host | ||||||
| (shared loopback under mirrored networking; the WSL2 gateway otherwise), caches | ||||||
| it, and silently no-ops when RedLog is not running or reachable. | ||||||
|
|
||||||
| --- | ||||||
|
|
||||||
| ## 5. Operational privacy & isolating private activity | ||||||
|
|
||||||
| RedLog is a passive recorder for an engagement. An operator also does **private** | ||||||
| things on the same machine (personal browsing, personal shells, credentials). | ||||||
| The goal: keep private activity out of the tamper-evident engagement DB. | ||||||
|
|
||||||
| ### 5.1 Instrument only the engagement workspace (primary control) | ||||||
|
|
||||||
| Isolation is most reliable at the **source** — control *where* producers run, | ||||||
| not just what the UI shows. | ||||||
|
|
||||||
| - **Dedicated engagement shell/distro.** Source the shell hook (or call | ||||||
| `redlog-send.sh`) **only** in the shell, WSL distro, VM, or OS user you use for | ||||||
| the engagement. Commands you run in your personal shell are never hooked. | ||||||
| - **Hooks fail safe.** Every hook no-ops when RedLog isn't running or the API | ||||||
| isn't reachable, so activity outside an active engagement session isn't logged. | ||||||
| - **Screenshots are deliberate.** Captures are manual / API-triggered, not a | ||||||
| passive desktop grabber — you choose when a screenshot (which may include | ||||||
| private windows) is taken. | ||||||
|
|
||||||
| A clean pattern on Windows: do all engagement work inside a dedicated **WSL | ||||||
| distro** with the hook sourced in that distro's `~/.bashrc`, and keep personal | ||||||
| work on the Windows host (unhooked). | ||||||
|
|
||||||
| ### 5.2 Pausing — understand the current limitation | ||||||
|
|
||||||
| The status-bar recording toggle sets a paused flag. **Today this only hides | ||||||
| events from the live timeline — it does not stop database writes.** Any producer | ||||||
| that POSTs to `/api/events` while "paused" is still persisted. Treat the toggle | ||||||
| as *hide*, not *stop*. | ||||||
|
|
||||||
| For genuine isolation right now, **stop the producer** (unsource/disable the | ||||||
| hook, or close the engagement workspace) rather than relying on pause. | ||||||
|
|
||||||
| > Planned hardening: gate persistence on the paused flag so the toggle truly | ||||||
| > stops capture, while still recording a pause/resume boundary marker for audit | ||||||
| > integrity; plus per-producer enable/disable in project config. Until then, use | ||||||
| > workspace isolation (§5.1) as the real control. | ||||||
|
|
||||||
| ### 5.3 Per-engagement isolation (built in) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Use the hyphenated form -### 5.3 Per-engagement isolation (built in)
+### 5.3 Per-engagement isolation (built-in)📝 Committable suggestion
Suggested change
🧰 Tools🪛 LanguageTool[grammar] ~160-~160: Use a hyphen to join words. (QB_NEW_EN_HYPHEN) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||
|
|
||||||
| Each project is a separate directory and SQLite DB | ||||||
| (`~/.redlog/projects/<id>/`), so engagements never cross-contaminate. Close / | ||||||
| switch the project when you stop working an engagement. | ||||||
|
|
||||||
| ### 5.4 Scope | ||||||
|
|
||||||
| Configure `scope.targets` / `excludeTargets` so out-of-scope hosts are flagged. | ||||||
| Combined with workspace isolation, this keeps the record focused on the | ||||||
| engagement. | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| #!/usr/bin/env bash | ||
| # RedLog event sender — WSL-aware | ||
| # -------------------------------- | ||
| # Send a single event to the RedLog timeline from any script or hook. Works on | ||
| # native Linux/macOS and inside WSL (reaching the RedLog API on the Windows | ||
| # host). Fire-and-forget: it silently no-ops (exit 0) if RedLog isn't running | ||
| # or isn't reachable, so it never breaks the calling script. | ||
| # | ||
| # Usage: | ||
| # redlog-send.sh "<command>" # subtype defaults to command_start | ||
| # redlog-send.sh "<command>" command_end # different subtype | ||
| # redlog-send.sh "<command>" command_end '{"exit_code":0}' # extra JSON merged into data{} | ||
| # AGENT_TYPE=agent redlog-send.sh "<command>" # override agent_type (default: shell) | ||
| # | ||
| # Example — wrap a tool in a script hook: | ||
| # redlog-send.sh "nmap -sV $TARGET" command_start | ||
| # nmap -sV "$TARGET" | ||
| # redlog-send.sh "nmap -sV $TARGET" command_end "{\"exit_code\":$?}" | ||
|
|
||
| set -uo pipefail | ||
|
|
||
| CMD="${1:-}" | ||
| SUBTYPE="${2:-command_start}" | ||
| EXTRA="${3:-}" | ||
| AGENT_TYPE="${AGENT_TYPE:-shell}" | ||
| [[ -n "${CMD}" ]] || exit 0 | ||
|
|
||
| # --- locate api-port / api-token ------------------------------------------- | ||
| # Native: $HOME/.redlog. WSL: the Windows app writes to the Windows user | ||
| # profile, so resolve %USERPROFILE% via wslpath. | ||
| _dir="" | ||
| if [[ -f "${HOME}/.redlog/api-port" ]]; then | ||
| _dir="${HOME}/.redlog" | ||
| elif grep -qi microsoft /proc/version 2>/dev/null && command -v wslpath >/dev/null 2>&1; then | ||
| _wp="$(cmd.exe /c 'echo %USERPROFILE%' 2>/dev/null | tr -d '\r')" | ||
| _wp="$(wslpath "${_wp}" 2>/dev/null || true)" | ||
| [[ -n "${_wp}" && -f "${_wp}/.redlog/api-port" ]] && _dir="${_wp}/.redlog" | ||
| fi | ||
| [[ -n "${_dir}" ]] || exit 0 | ||
|
|
||
| PORT="$(tr -d '\r\n' < "${_dir}/api-port" 2>/dev/null)" | ||
| TOKEN="$(tr -d '\r\n' < "${_dir}/api-token" 2>/dev/null)" | ||
| [[ -n "${PORT}" && -n "${TOKEN}" ]] || exit 0 | ||
|
|
||
| # --- resolve a reachable host (cached to avoid re-probing every call) ------- | ||
| # Under WSL2 mirrored networking / WSL1, 127.0.0.1 is shared. Under NAT, try | ||
| # the default gateway (Windows host) — reachable only if the API isn't bound to | ||
| # loopback-only; otherwise this sender simply no-ops. | ||
| _cache="${TMPDIR:-/tmp}/.redlog-host-${PORT}" | ||
| HOST="" | ||
| if [[ -f "${_cache}" ]]; then | ||
| HOST="$(cat "${_cache}" 2>/dev/null)" | ||
| curl -sf --connect-timeout 1 --max-time 2 "http://${HOST}:${PORT}/api/health" >/dev/null 2>&1 || HOST="" | ||
|
Comment on lines
+49
to
+53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win Store and validate the cached host securely. Line 49 uses a predictable shared Proposed direction- _cache="${TMPDIR:-/tmp}/.redlog-host-${PORT}"
+ _cache_dir="${XDG_CACHE_HOME:-${HOME}/.cache}/redlog"
+ (umask 077 && mkdir -p "${_cache_dir}") || exit 0
+ _cache="${_cache_dir}/host-${PORT}"Also resolve 🤖 Prompt for AI Agents |
||
| fi | ||
| if [[ -z "${HOST}" ]]; then | ||
| _gw="$(ip route show default 2>/dev/null | awk '{print $3; exit}')" | ||
| for _c in 127.0.0.1 "${_gw}"; do | ||
| [[ -z "${_c}" ]] && continue | ||
| if curl -sf --connect-timeout 1 --max-time 2 "http://${_c}:${PORT}/api/health" >/dev/null 2>&1; then | ||
| HOST="${_c}" | ||
| echo "${_c}" > "${_cache}" 2>/dev/null || true | ||
| break | ||
| fi | ||
| done | ||
| fi | ||
| [[ -n "${HOST}" ]] || exit 0 | ||
|
|
||
| # --- build payload ---------------------------------------------------------- | ||
| if command -v python3 >/dev/null 2>&1; then | ||
| PAYLOAD="$(CMD="${CMD}" SUBTYPE="${SUBTYPE}" EXTRA="${EXTRA}" AGENT_TYPE="${AGENT_TYPE}" python3 -c ' | ||
| import json, os | ||
| src = "native" | ||
| try: | ||
| if "microsoft" in open("/proc/version").read().lower(): | ||
| src = "wsl" | ||
| except Exception: | ||
| pass | ||
| d = {"agent_type": os.environ["AGENT_TYPE"], | ||
| "data": {"subtype": os.environ["SUBTYPE"], | ||
| "command": os.environ["CMD"], | ||
| "shell": os.path.basename(os.environ.get("SHELL", "")), | ||
| "source": src}} | ||
| ex = os.environ.get("EXTRA", "") | ||
| if ex: | ||
| try: | ||
| d["data"].update(json.loads(ex)) | ||
| except Exception: | ||
| pass | ||
| print(json.dumps(d))')" || exit 0 | ||
| else | ||
| # Minimal fallback without python3 (no EXTRA merge; basic escaping). | ||
| _esc() { printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'; } | ||
| PAYLOAD="{\"agent_type\":\"${AGENT_TYPE}\",\"data\":{\"subtype\":\"${SUBTYPE}\",\"command\":\"$(_esc "${CMD}")\",\"source\":\"native\"}}" | ||
| fi | ||
|
Comment on lines
+90
to
+94
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Do not hand-roll JSON escaping in the fallback. The fallback only escapes 🤖 Prompt for AI Agents |
||
|
|
||
| # --- fire-and-forget send --------------------------------------------------- | ||
| curl -sf -X POST "http://${HOST}:${PORT}/api/events" \ | ||
| -H "Authorization: Bearer ${TOKEN}" \ | ||
| -H "Content-Type: application/json" \ | ||
| -d "${PAYLOAD}" \ | ||
| --connect-timeout 1 --max-time 2 >/dev/null 2>&1 || true | ||
| exit 0 | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: guan4tou2/REDLOG
Length of output: 303
🌐 Web query:
Node.js current LTS version release date 24 status July 2026💡 Result:
As of today, July 28, 2026, Node.js 24 (codenamed "Krypton") is in the Active LTS (Long Term Support) phase [1][2][3]. The most recent release for this version line is v24.19.0, which was prepared on July 22, 2026 [4]. Node.js 24 entered the Active LTS phase on October 28, 2025, and is scheduled to remain in this status until it transitions to Maintenance mode on October 20, 2026, with an eventual End-of-Life date of April 30, 2028 [1][2][3]. Additionally, the Node.js project announced security releases for the 24.x release line scheduled for, or shortly after, July 27, 2026, to address identified vulnerabilities [5].
Citations:
🌐 Web query:
better-sqlite3 Node.js 24 prebuilt bindings npm package💡 Result:
As of July 28, 2026, better-sqlite3 supports Node.js 24 [1][2]. Prebuilt binaries for Node.js 24 were introduced in version 12.1.0 of the package [3][2]. If you are encountering installation issues or runtime errors indicating a version mismatch (such as being compiled against an older NODE_MODULE_VERSION), ensure your project is using better-sqlite3 version 12.1.0 or higher [2]. You can update your dependency in package.json to at least 12.1.0 to resolve this [2]: "better-sqlite3": "^12.1.0" If you are on an older version of the library (e.g., 11.x), it will not have the necessary prebuilt binaries for Node.js 24, which can lead to installation failures or attempts to compile from source [2]. Additionally, recent updates to better-sqlite3 have refactored how binaries are handled, moving away from prebuild-install and towards including prebuilt binaries directly within the package, with automatic selection at runtime [4]. If you still encounter issues: 1. Ensure you have updated to the latest version of better-sqlite3 [2]. 2. If compilation from source is required, ensure your environment has the necessary build tools (like python, make, and a C++ compiler) installed, as prebuilt binaries might not be available for every niche platform or architecture [4]. 3. For specific errors, check if you have cached older dependencies; running npm cache clean or deleting node_modules and package-lock.json before reinstalling is recommended [5].
Citations:
🌐 Web query:
node-pty Electron Node 24 build native module💡 Result:
To use node-pty in an Electron application with Node 24, you must recompile the native module against the specific version of Electron (and its bundled Node.js ABI) rather than your system's Node.js version [1][2][3]. Failing to do so causes ABI mismatch errors, such as posix_spawnp failed or ModuleNotFoundError [1][4][5]. The recommended approach is to use the
@electron/rebuildpackage [6][2][3]. Standard Workflow for Rebuilding 1. Install@electron/rebuildas a development dependency: npm install --save-dev@electron/rebuild2. After installing your dependencies (which may install prebuilt binaries for your host system), trigger a rebuild specifically for your Electron version: npx electron-rebuild -f -w node-pty This command forces (-f) a rebuild of the specified module (-w) against the Electron version detected in your project [1][6]. Important Considerations - Automation: Ensure this step is part of your build process. If you use Electron Forge, it typically handles this automatically [2][3]. If using Electron Builder or other bundlers, you may need to add it to your postinstall script or as a specific build hook to ensure it runs during packaging [1][4][7]. - ABI Mismatches: If you encounter errors about missing files (e.g.,../build/Release/pty.node), the module was likely compiled for the wrong architecture or Node ABI [5][8]. Always verify that your rebuild step targets the correct Electron version [6]. - System Requirements: Building native modules requires a C++ compiler and python (typically required by node-gyp) installed on your system [6][2]. If you see errors related to missing build tools (e.g., distutils), ensure your development environment is configured for native compilation [1]. - Hoisted Dependencies: If you are using npm workspaces, ensure that@electron/rebuildcan locate node-pty, especially if it is hoisted to the root of your repository [7]. You may need to specify the correct path to the module [7][9].Citations:
🏁 Script executed:
Repository: guan4tou2/REDLOG
Length of output: 50373
Align the Node.js support policy across both setup documents.
Docs currently direct users from EOL Node.js 20 toward Node 20–22 and exclude Node 24+, while Node 24 is LTS and
better-sqlite312.1.0+ supports Node 24. Update both files to state what versions Electron's native rebuild is tested for and remove the blanket “no prebuild” claim for 24+ unless the repo toolchain requires source rebuilds.docs/windows-wsl-setup.md#L13-L17README.md#L40-L43📍 Affects 2 files
docs/windows-wsl-setup.md#L13-L17(this comment)README.md#L40-L43🤖 Prompt for AI Agents
Source: MCP tools