From ccffddc864571fff672b5632baf47bf8a646ff09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?ryan4yin=20=7C=20=E4=BA=8C=E8=8A=B1?= Date: Sun, 1 Nov 2026 00:09:27 +0800 Subject: [PATCH] feat(wechat): native nixpkgs package with app-scoped data (#492) Switch to the native deb package from nixpkgs-patched (#560225), remove the AppImage/FHS bwrap layer, and enable native Wayland while keeping the X11 fallback. Keep only WeChat state under one app-scoped HOME and bind the host Documents and Downloads directories like the other desktop apps. User-selected files also go through the XDG FileChooser portal. Remove the launcher, activation script, and compatibility symlinks. Assisted-by: DeepSeek Harness (deepseek-flash) --- WORKAROUNDS.md | 26 +++--- flake.lock | 6 +- flake.nix | 6 +- hardening/README.md | 13 +-- hardening/bwraps/default.nix | 11 --- hardening/bwraps/wechat.nix | 81 ------------------- hardening/nixpaks/default.nix | 3 +- .../nixpaks/modules/desktop-integration.nix | 7 +- hardening/nixpaks/modules/wechat-policy.nix | 18 ++--- hardening/nixpaks/wechat.nix | 30 ++----- hardening/tests/wechat-runtime.md | 58 ------------- .../nixos/desktop/networking/mihomo/README.md | 8 +- .../aarch64-linux/src/12kingdoms-shoukei.nix | 1 - outputs/x86_64-linux/src/idols-ai.nix | 1 - 14 files changed, 49 insertions(+), 220 deletions(-) delete mode 100644 hardening/bwraps/default.nix delete mode 100644 hardening/bwraps/wechat.nix delete mode 100644 hardening/tests/wechat-runtime.md diff --git a/WORKAROUNDS.md b/WORKAROUNDS.md index 90608dae..46354240 100644 --- a/WORKAROUNDS.md +++ b/WORKAROUNDS.md @@ -16,17 +16,17 @@ obsolete workarounds get rolled back instead of lingering. A version or revision pinned for a reason that can go away. -| ID | What & where | Why | Removal condition | Added | Revisit | Status | -| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ---------- | -------------------------- | ------ | -| WA-001 | smartctl_exporter pinned to upstream `6274decc`, which carries PR [#329](https://github.com/prometheus-community/smartctl_exporter/pull/329) — `overlays/smartctl-exporter/` | `/metrics` returns HTTP 500 once a device becomes readable after startup ([#305](https://github.com/prometheus-community/smartctl_exporter/issues/305), [#326](https://github.com/prometheus-community/smartctl_exporter/issues/326)) | Drop once nixpkgs provides a version containing the #329 fix | 2026-10-03 | next nixpkgs bump | active | -| WA-004 | `catppuccin` on `main` — `flake.nix` | `main` carries the nodejs→nodejs-slim deprecation fix, which is not in a release | Switch to a release tag once it includes the fix | 2026-09-25 | on catppuccin release | active | -| WA-005 | `tuios` input — `flake.nix`; `home/base/tui/tuios/` | nixpkgs lags behind upstream | Use nixpkgs' `tuios` once it is recent enough | 2026-10-03 | on nixpkgs bump | active | -| WA-006 | `nixpkgs-blender` — `flake.nix` | Blender 5.2 LTS + CUDA/OptiX pin; keeps `just up` from triggering a full source rebuild | Bump deliberately when needed; drop the pin if the current nixpkgs build is acceptable | 2026-07-24 | deliberate | active | -| WA-007 | WeChat from `nixpkgs-master` — `hardening/bwraps/default.nix` | newest builds; the pinned channel lags | Fall back to the stable channel once it has a good build | 2026-10-03 | on nixpkgs bump | active | -| WA-020 | `fcitx5-vinput` pinned to release tag `v2.4.2` — `flake.nix`; consumer `home/linux/gui/base/vinput/default.nix` | Tracks a release tag instead of a branch, so `just up` stays on that release | Bump to a newer release tag when its changes are wanted | 2026-10-04 | on vinput release | active | -| WA-021 | `nix-x86-on-aarch64` input — our fork of rowanG077's patched FEX + muvm runtime — `flake.nix`; `hosts/12kingdoms-shoukei/game/` | FEX does not support 16K pages, so x86/x86_64 apps and games on shoukei need this pinned flake's 4K-page microVM runtime; our fork lets upstream changes be reviewed before use | Drop once FEX supports 16K pages directly, or nixpkgs/nixos-apple-silicon ships an equivalent runtime | 2026-10-07 | on FEX/nixpkgs/muvm update | active | -| WA-023 | `nix.package = pkgs.nixVersions.latest` — `modules/nixos/base/nix.nix` | NixOS is opted into Nix 2.35 (2.35.2), which nixpkgs ships as `nixVersions.latest`, while `nixVersions.stable` is still 2.34 | Drop the override and fall back to the default `pkgs.nix` once `nixVersions.stable` is 2.35 or newer | 2026-10-07 | next nixpkgs bump | active | -| WA-037 | `nixpkgs-npu` input pinned to `2ddccb854d89` — the `openvino-npu-compiler` branch of `ryan4yin/nixpkgs`, carrying [NixOS/nixpkgs#570230](https://github.com/NixOS/nixpkgs/pull/570230) — `flake.nix`; consumer `pkgs-npu` in `outputs/default.nix`, `hosts/idols-aquamarine/asr.nix` | The Intel NPU compiler, and the driver change that loads it, are unmerged, so the NPU driver the Whisper service needs comes from that branch | Drop the input and load `intel-npu-driver` from `nixos-unstable` once #570230 merges | 2026-10-17 | when #570230 merges | active | +| ID | What & where | Why | Removal condition | Added | Revisit | Status | +| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ---------- | ------------------------------------- | ------ | +| WA-001 | smartctl_exporter pinned to upstream `6274decc`, which carries PR [#329](https://github.com/prometheus-community/smartctl_exporter/pull/329) — `overlays/smartctl-exporter/` | `/metrics` returns HTTP 500 once a device becomes readable after startup ([#305](https://github.com/prometheus-community/smartctl_exporter/issues/305), [#326](https://github.com/prometheus-community/smartctl_exporter/issues/326)) | Drop once nixpkgs provides a version containing the #329 fix | 2026-10-03 | next nixpkgs bump | active | +| WA-004 | `catppuccin` on `main` — `flake.nix` | `main` carries the nodejs→nodejs-slim deprecation fix, which is not in a release | Switch to a release tag once it includes the fix | 2026-09-25 | on catppuccin release | active | +| WA-005 | `tuios` input — `flake.nix`; `home/base/tui/tuios/` | nixpkgs lags behind upstream | Use nixpkgs' `tuios` once it is recent enough | 2026-10-03 | on nixpkgs bump | active | +| WA-006 | `nixpkgs-blender` — `flake.nix` | Blender 5.2 LTS + CUDA/OptiX pin; keeps `just up` from triggering a full source rebuild | Bump deliberately when needed; drop the pin if the current nixpkgs build is acceptable | 2026-07-24 | deliberate | active | +| WA-047 | WeChat from `nixpkgs-patched` carrying [NixOS/nixpkgs#560225](https://github.com/NixOS/nixpkgs/pull/560225) — `flake.nix`, `hardening/nixpaks/default.nix` | the PR switches WeChat from the AppImage/FHS wrapper to a native deb package and adds native Wayland support | Drop once #560225 merges (and use the normal nixpkgs package) | 2026-10-31 | on nixpkgs-patched or upstream merges | active | +| WA-020 | `fcitx5-vinput` pinned to release tag `v2.4.2` — `flake.nix`; consumer `home/linux/gui/base/vinput/default.nix` | Tracks a release tag instead of a branch, so `just up` stays on that release | Bump to a newer release tag when its changes are wanted | 2026-10-04 | on vinput release | active | +| WA-021 | `nix-x86-on-aarch64` input — our fork of rowanG077's patched FEX + muvm runtime — `flake.nix`; `hosts/12kingdoms-shoukei/game/` | FEX does not support 16K pages, so x86/x86_64 apps and games on shoukei need this pinned flake's 4K-page microVM runtime; our fork lets upstream changes be reviewed before use | Drop once FEX supports 16K pages directly, or nixpkgs/nixos-apple-silicon ships an equivalent runtime | 2026-10-07 | on FEX/nixpkgs/muvm update | active | +| WA-023 | `nix.package = pkgs.nixVersions.latest` — `modules/nixos/base/nix.nix` | NixOS is opted into Nix 2.35 (2.35.2), which nixpkgs ships as `nixVersions.latest`, while `nixVersions.stable` is still 2.34 | Drop the override and fall back to the default `pkgs.nix` once `nixVersions.stable` is 2.35 or newer | 2026-10-07 | next nixpkgs bump | active | +| WA-037 | `nixpkgs-npu` input pinned to `2ddccb854d89` — the `openvino-npu-compiler` branch of `ryan4yin/nixpkgs`, carrying [NixOS/nixpkgs#570230](https://github.com/NixOS/nixpkgs/pull/570230) — `flake.nix`; consumer `pkgs-npu` in `outputs/default.nix`, `hosts/idols-aquamarine/asr.nix` | The Intel NPU compiler, and the driver change that loads it, are unmerged, so the NPU driver the Whisper service needs comes from that branch | Drop the input and load `intel-npu-driver` from `nixos-unstable` once #570230 merges | 2026-10-17 | when #570230 merges | active | ## Workarounds @@ -94,7 +94,7 @@ An unfinished feature or gap. - Security architecture, threat model and audit status: [SECURITY.md](./SECURITY.md). - Unmerged **nixpkgs** PRs are carried via the `nixpkgs-patched` input and the - [`.agents/skills/nixpkgs-patched`](./.agents/skills/nixpkgs-patched/SKILL.md) workflow (that input - currently carries nothing; package-level carries are recorded under `Pins`). + [`.agents/skills/nixpkgs-patched`](./.agents/skills/nixpkgs-patched/SKILL.md) workflow (currently + WA-047). - Routine version pins (colmena, agenix, disko, lanzaboote, haumea, home-manager, `nixpkgs-stable`, `nixpkgs-darwin`, …) are the versions in use, not workarounds, so they are not listed here. diff --git a/flake.lock b/flake.lock index 0324e31d..03e2a540 100644 --- a/flake.lock +++ b/flake.lock @@ -939,11 +939,11 @@ }, "nixpkgs-patched": { "locked": { - "lastModified": 1791048980, - "narHash": "sha256-KgItSKML8Xvte0B7/uGnBDsYzSnnKHcOaiUbgWBXLXw=", + "lastModified": 1793459509, + "narHash": "sha256-S1TWTifxgaWpjRxLGOvHslwFuul3z2SYycgzUmuKSks=", "owner": "ryan4yin", "repo": "nixpkgs", - "rev": "a7868a727837f3c09cee2ce0ca671c76b1589fed", + "rev": "30ed98991ef49fd51239d9edbd0602ddddd1936d", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index b904b352..3fe94609 100644 --- a/flake.nix +++ b/flake.nix @@ -28,9 +28,9 @@ }; nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-26.05"; - # ryan4yin/nixpkgs fork for the `.agents/skills/nixpkgs-patched` workflow. It - # currently carries no patches (see WORKAROUNDS.md), but `pkgs-patched` is - # wired in outputs/default.nix so a temporary carry needs no flake edit. + # ryan4yin/nixpkgs fork for the `.agents/skills/nixpkgs-patched` workflow. + # Carries NixOS/nixpkgs#560225 (WeChat native deb + Wayland support) until + # the PR merges; see WORKAROUNDS.md. nixpkgs-patched.url = "github:ryan4yin/nixpkgs/nixos-unstable-patched"; # get some latest packages from the master branch nixpkgs-master.url = "github:nixos/nixpkgs/master"; diff --git a/hardening/README.md b/hardening/README.md index 6c5d6cba..8f17edac 100644 --- a/hardening/README.md +++ b/hardening/README.md @@ -27,7 +27,7 @@ explicitly; other files use the document portal. Every app also has private writ | QQ | Isolated | Personal files, private app state | Media, notifications, tray, MPRIS, idle, accessibility | | Telegram | Isolated | Personal files, private app state | Media, notifications, tray, MPRIS, idle, accessibility, Ayatana indicators | | Zoom | Isolated | `~/.zoom`, `zoomus.conf`, `zoom.conf`, Downloads, `Documents/Zoom`, private app state | Media, X11/XWayland, FHS, SNI tray, idle, `/dev/video0-1`, read-only `/sys/class/drm` | -| WeChat | Isolated | `Documents/WeChat_Data`, its HOME mapping and `xwechat_files` link, private app state | Media, X11/xcb, FHS, SNI tray | +| WeChat | Isolated | Documents, Downloads, app-scoped `wechat` data, private app state | Media, Wayland, X11 fallback, SNI tray, file chooser portal | All browsers get read-only NSS certificates, printing, native notifications and accessibility. @@ -55,15 +55,16 @@ All browsers get read-only NSS certificates, printing, native notifications and ## Validation - Passed: `just fmt`, `just test`, `ai-niri` build and `shoukei-niri` eval. -- Deployed on `ai`; interactive startup and tray checks passed for Chrome, Firefox, QQ, Telegram, - Zoom and WeChat. +- Deployed on `ai`; interactive startup and tray checks passed for Chrome, Firefox, QQ, Telegram and + Zoom. +- WeChat uses the native deb package from nixpkgs-patched, with nixpak as the only bwrap layer. The + build passes; interactive Wayland validation is pending. - Chromium/Chrome: renderer sandbox, mounts, rendering and disposable-profile persistence passed. Chromium reaches host loopback; Chrome cannot. - Firefox: disposable headless screenshot passed. - Brave/Edge: renderer and permission checks passed; headless page export timed out. - Evidence: [browsers](tests/browser-runtime.md), - [Firefox/QQ/Telegram](tests/unified-app-runtime.md), [Zoom](tests/zoom-runtime.md), - [WeChat](tests/wechat-runtime.md). + [Firefox/QQ/Telegram](tests/unified-app-runtime.md), [Zoom](tests/zoom-runtime.md). ## Code map @@ -74,6 +75,6 @@ All browsers get read-only NSS certificates, printing, native notifications and grants. - [browser-permissions.nix](nixpaks/modules/browser-permissions.nix), [chromium-browser.nix](nixpaks/modules/chromium-browser.nix): browser scopes and launcher. -- [bwraps/wechat.nix](bwraps/wechat.nix): WeChat FHS and data setup. +- [nixpaks/wechat.nix](nixpaks/wechat.nix): WeChat package and data setup. - [kernel-hardening.nix](kernel-hardening.nix), [apparmor/](apparmor/): kernel sysctl and AppArmor profiles. diff --git a/hardening/bwraps/default.nix b/hardening/bwraps/default.nix deleted file mode 100644 index 011d1406..00000000 --- a/hardening/bwraps/default.nix +++ /dev/null @@ -1,11 +0,0 @@ -{ pkgs-master, ... }: -{ - nixpkgs.overlays = [ - (_: super: { - bwraps = { - # Track WeChat from nixpkgs-master, which carries the newest builds. - wechat = super.callPackage ./wechat.nix { wechat = pkgs-master.wechat; }; - }; - }) - ]; -} diff --git a/hardening/bwraps/wechat.nix b/hardening/bwraps/wechat.nix deleted file mode 100644 index 7b0105a4..00000000 --- a/hardening/bwraps/wechat.nix +++ /dev/null @@ -1,81 +0,0 @@ -# - wechat's flatpak manifest: https://github.com/flathub/com.tencent.WeChat/blob/master/com.tencent.WeChat.yaml -# Refer: -# - Flatpak manifest's docs: -# - https://docs.flatpak.org/en/latest/manifests.html -# - https://docs.flatpak.org/en/latest/sandbox-permissions.html -# -# We repack WeChat ourselves because nixpkgs' `wechat` package hardcodes its -# AppImage wrapper args and does not expose them for `.override`, so there is no -# way to add our bubblewrap sandbox (bind mounts, tmpfs /home, IME env) through -# it. We reuse its already-extracted, libtiff-patched AppImage (`wechat.src`), -# so the version and source hash stay maintained by nixpkgs. -# Upstream override support: https://github.com/NixOS/nixpkgs/pull/358977 -{ - appimageTools, - wechat, -}: -let - pname = "wechat"; - # nixpkgs' wechat package already extracted the AppImage and applied the - # libtiff.so.5 fix; reuse it so version/hash stay maintained upstream. - # https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/we/wechat/linux.nix - appimageContents = wechat.src; -in -appimageTools.wrapAppImage { - inherit pname; - inherit (wechat) version; - - src = appimageContents; - - extraInstallCommands = '' - mkdir -p $out/share/applications - cp ${appimageContents}/wechat.desktop $out/share/applications/ - mkdir -p $out/share/pixmaps - cp ${appimageContents}/wechat.png $out/share/pixmaps/ - - substituteInPlace $out/share/applications/wechat.desktop --replace-fail AppRun wechat - ''; - - # Prepare the WeChat data dirs before the sandbox starts. The isolation itself - # is the `--tmpfs /home` / `--tmpfs /root` in `extraBwrapArgs` below. - # Adapted from https://aur.archlinux.org/cgit/aur.git/tree/wechat-universal.sh?h=wechat-universal-bwrap - extraPreBwrapCmds = '' - XDG_DOCUMENTS_DIR="''${XDG_DOCUMENTS_DIR:-$(xdg-user-dir DOCUMENTS)}" - if [[ -z "''${XDG_DOCUMENTS_DIR}" ]]; then - echo 'Error: Failed to get XDG_DOCUMENTS_DIR, refuse to continue' - exit 1 - fi - - WECHAT_DATA_DIR="''${XDG_DOCUMENTS_DIR}/WeChat_Data" - - # Using ''${WECHAT_DATA_DIR} as Wechat Data folder - WECHAT_HOME_DIR="''${WECHAT_DATA_DIR}/home" - WECHAT_FILES_DIR="''${WECHAT_DATA_DIR}/xwechat_files" - - mkdir -p "''${WECHAT_FILES_DIR}" - mkdir -p "''${WECHAT_HOME_DIR}" - ln -snf "''${WECHAT_FILES_DIR}" "''${WECHAT_HOME_DIR}/xwechat_files" - ''; - extraBwrapArgs = [ - "--tmpfs /home" - "--tmpfs /root" - # format: --bind - "--bind \${WECHAT_HOME_DIR} \${HOME}" - "--bind \${WECHAT_FILES_DIR} \${WECHAT_FILES_DIR}" - "--chdir \${HOME}" - # wechat-universal only supports xcb - "--setenv QT_QPA_PLATFORM xcb" - "--setenv QT_AUTO_SCREEN_SCALE_FACTOR 1" - # use fcitx as IME - "--setenv QT_IM_MODULE fcitx" - "--setenv GTK_IM_MODULE fcitx" - ]; - chdirToPwd = false; - # WeChat needs outbound network; everything else is unshared - unshareNet = false; - unshareIpc = true; - unsharePid = true; - unshareUts = true; - unshareCgroup = true; - privateTmp = true; -} diff --git a/hardening/nixpaks/default.nix b/hardening/nixpaks/default.nix index ffa57a0c..c9c99bca 100644 --- a/hardening/nixpaks/default.nix +++ b/hardening/nixpaks/default.nix @@ -1,6 +1,7 @@ { pkgs, pkgs-master, + pkgs-patched, nixpak, ... }: @@ -26,7 +27,7 @@ in brave-origin = wrapper super ./brave-origin.nix; microsoft-edge = wrapper super ./microsoft-edge.nix; zoom = wrapper super ./zoom.nix; - wechat = wrapper super ./wechat.nix; + wechat = wrapper pkgs-patched ./wechat.nix; }; }) ]; diff --git a/hardening/nixpaks/modules/desktop-integration.nix b/hardening/nixpaks/modules/desktop-integration.nix index 1694fc1f..372a2a85 100644 --- a/hardening/nixpaks/modules/desktop-integration.nix +++ b/hardening/nixpaks/modules/desktop-integration.nix @@ -27,14 +27,15 @@ in "org.freedesktop.DBus" = "talk"; "org.kde.StatusNotifierWatcher" = "talk"; } - # SNI name is -; WeChat 4.1.13 uses -2. + # SNI name is -. The PID is from the nixpak + # namespace and varies with the inner AppImage/FHS startup chain. // builtins.listToAttrs ( lib.concatMap ( id: map ( instance: lib.nameValuePair "org.kde.StatusNotifierItem-${toString id}-${toString instance}" "own" - ) (lib.range 1 5) - ) (lib.range 2 5) + ) (lib.range 1 10) + ) (lib.range 2 30) ); }) (lib.mkIf cfg.mpris { diff --git a/hardening/nixpaks/modules/wechat-policy.nix b/hardening/nixpaks/modules/wechat-policy.nix index 49973e2f..f0f3b01f 100644 --- a/hardening/nixpaks/modules/wechat-policy.nix +++ b/hardening/nixpaks/modules/wechat-policy.nix @@ -1,4 +1,4 @@ -# The existing FHS layer owns WeChat's HOME remapping and xwechat_files link. +# WeChat data and its sandbox boundary are owned by nixpak. { config, lib, @@ -34,20 +34,18 @@ "/etc/machine-id" ] ]; - # The inner FHS /home reset replaces base XDG mounts with this backing tree. - bind.rw = lib.mkForce [ - (sloth.mkdir (sloth.concat' sloth.xdgDocumentsDir "/WeChat_Data")) - (sloth.concat' sloth.runtimeDir "/doc") - [ - (sloth.mkdir (sloth.concat' sloth.runtimeDir "/nixpak-${config.flatpak.appId}-tmp")) - "/tmp" - ] + bind.rw = [ + sloth.xdgDocumentsDir + sloth.xdgDownloadDir ]; env = { + # WeChat keeps .xwechat and xwechat_files under HOME. User-selected + # files also go through the XDG file chooser portal where available. + HOME = lib.mkForce (sloth.concat' sloth.xdgDataHome "/wechat"); DISPLAY = sloth.envOr "DISPLAY" ""; XAUTHORITY = sloth.envOr "XAUTHORITY" (sloth.concat' sloth.homeDir "/.Xauthority"); XDG_DOCUMENTS_DIR = sloth.xdgDocumentsDir; - # The existing pre-FHS script uses mkdir/ln before /usr/bin exists. + XDG_DOWNLOAD_DIR = sloth.xdgDownloadDir; PATH = lib.makeBinPath [ pkgs.coreutils ]; }; }; diff --git a/hardening/nixpaks/wechat.nix b/hardening/nixpaks/wechat.nix index 654c32b0..9e2587ee 100644 --- a/hardening/nixpaks/wechat.nix +++ b/hardening/nixpaks/wechat.nix @@ -1,6 +1,6 @@ { lib, - bwraps, + wechat, mkNixPak, buildEnv, makeDesktopItem, @@ -9,32 +9,12 @@ }: let appId = "com.tencent.WeChat"; - # As with Zoom, preserve the outer metadata file across the inner FHS layer. - # Keep the existing AppImage runtime and WeChat_Data layout unchanged. - package = bwraps.wechat.overrideAttrs (old: { - # Refuse unexpected layouts before the existing ln -snf can modify them. - extraPreBwrapCmds = '' - wechat_link="''${XDG_DOCUMENTS_DIR}/WeChat_Data/home/xwechat_files" - wechat_files="''${XDG_DOCUMENTS_DIR}/WeChat_Data/xwechat_files" - if [[ -e "$wechat_link" || -L "$wechat_link" ]]; then - if [[ ! -L "$wechat_link" || "$(readlink "$wechat_link")" != "$wechat_files" ]]; then - echo 'WeChat: unexpected xwechat_files layout; refusing to change existing data.' >&2 - exit 1 - fi - fi - '' - + (old.extraPreBwrapCmds or ""); - extraBwrapArgs = (old.extraBwrapArgs or [ ]) ++ [ - "--ro-bind /.flatpak-info /.flatpak-info" - # The inner /home reset must not hide an Xauthority file stored there. - ''--ro-bind-try "''${XAUTHORITY}" "''${XAUTHORITY}"'' - ]; - }); + wrapped = mkNixPak { config = { imports = [ ./modules/wechat-policy.nix ]; app = { - inherit package; + package = wechat; binPath = "bin/wechat"; }; flatpak = { inherit appId; }; @@ -43,7 +23,7 @@ let exe = lib.getExe wrapped.config.script; assets = runCommandLocal "wechat-desktop-assets" { } '' mkdir -p $out/share - ln -s ${package}/share/pixmaps $out/share/pixmaps + ln -s ${wechat}/share/icons $out/share/icons ''; in buildEnv { @@ -58,7 +38,7 @@ buildEnv { name = "wechat"; desktopName = "WeChat"; exec = "${exe} %U"; - icon = "wechat"; + icon = "${wechat}/share/icons/hicolor/256x256/apps/wechat.png"; terminal = false; startupWMClass = "wechat"; categories = [ diff --git a/hardening/tests/wechat-runtime.md b/hardening/tests/wechat-runtime.md deleted file mode 100644 index 498f3766..00000000 --- a/hardening/tests/wechat-runtime.md +++ /dev/null @@ -1,58 +0,0 @@ -# WeChat nested runtime verification - -WeChat 4.1.13.26 built and opened a `Weixin` X11 window with a disposable profile. The final -candidate was `/nix/store/6wr94i7da0674k9hzs23fk2nr1ih4i3f-nixpak-wechat-4.1.13.26`. The existing -AppImage extraction, FHS runtime, X11 and fcitx settings remain in `hardening/bwraps/wechat.nix`; -the new nixpak wrapper adds an outer boundary. - -The live extracted WeChat binary had three PID namespace identifiers, `NoNewPrivs: 1`, `Seccomp: 0`, -a network namespace different from the host, and `/.flatpak-info` identifying `com.tencent.WeChat`. -Its device view contained standard synthetic devices, `dri`, and the four explicit NVIDIA nodes; no -raw camera, USB or block devices. This smoke test does not establish an internal renderer sandbox -guarantee. - -A sentinel in the disposable `Documents/WeChat_Data/home` was readable at WeChat's remapped HOME. -Its `xwechat_files` link retained the absolute target `Documents/WeChat_Data/xwechat_files`, which -remains bound inside both layers. The final launcher also rejected a separate disposable layout -containing a real `home/xwechat_files` directory, exited 1, and preserved its sentinel and contents. -It will not silently migrate an unexpected existing layout. - -## Compatibility changes - -As with Zoom, the wrapper preserves the outer `/.flatpak-info` file explicitly: the FHS automatic -root mount loop only propagates directories. The inner `--dev-bind /dev /dev` inherits the outer -filtered devices. The original inner network setting inherits pasta's isolated outer namespace, -including its private loopback. - -The original inner `/home` reset hides the shared desktop base's XDG mounts. WeChat therefore -exposes its existing backing tree to the outer sandbox and keeps the original FHS HOME mapping. It -supplies `XDG_DOCUMENTS_DIR` and a coreutils-only PATH for the pre-FHS mkdir/link commands. -Xauthority is rebound after the inner HOME reset when present. - -The first run aborted in libdbus because no machine ID was available. The WeChat policy supplies a -synthetic app-specific ID rather than the host ID. Login/device identity continuity with an existing -account remains untested. No credentials or real profile were used for this test. - -## Historical constraint - -Commit `0c7e43a2` removed `nixpaks/wechat-uos.nix`. Its previous TODO said the FHS runtime was -problematic inside another sandbox, but supplied no failure log. That old module also disabled X11 -and set `QT_QPA_PLATFORM=kcb`, despite its xcb-only comment. Commit `28dee277` subsequently changed -the AppImage wrapper from Wayland to xcb and added fcitx environment settings. These records do not -prove the original failure's cause. Current runtime testing establishes that retaining FHS inside -nixpak is feasible with the explicit compatibility changes above. - -## Repeat safely - -Use the same disposable-home command as [Zoom](zoom-runtime.md), with WeChat's output and -executable, and additionally set `XDG_DOCUMENTS_DIR="$wechat_probe_dir/Documents"`. Prepare -`Documents/WeChat_Data/home` and `Documents/WeChat_Data/xwechat_files` beneath that disposable home -before launching. The smoke test stops before QR login and uses no account. Inspect the exact test -PID through `/proc` while the timeout is active; verify that its window and processes disappear -after timeout. - -Pending manual checks: existing account persistence, QR/login, fcitx input, notifications/tray, -portal file chooser and selected-file access, downloads, voice/video calls, camera/screencast portal -support and clipboard workflows. Camera and ScreenCast methods are explicit grants; raw capture -devices and the host PipeWire socket are not exposed. X11 retains its display trust limitations, so -portal permission does not imply all capture requires portal consent. diff --git a/modules/nixos/desktop/networking/mihomo/README.md b/modules/nixos/desktop/networking/mihomo/README.md index 2823453e..d3038188 100644 --- a/modules/nixos/desktop/networking/mihomo/README.md +++ b/modules/nixos/desktop/networking/mihomo/README.md @@ -64,8 +64,8 @@ still reaches the core. The gateway (`suzi`, not a host in this flake) runs the same config with a fixed set of deltas -- `gateway-config.nu` renders it from the same `sources.yaml` and `policy.yaml`. The gateway uses nftables TProxy, disables the desktop TUN auto-route, and uses `fake-ip` DNS with `dns.ipv6: false`: -LAN clients receive fake A mappings so mihomo retains the domain for routing and sniffing while their -traffic uses the working IPv4 TProxy path. The gateway withholds AAAA records because LAN IPv6 +LAN clients receive fake A mappings so mihomo retains the domain for routing and sniffing while +their traffic uses the working IPv4 TProxy path. The gateway withholds AAAA records because LAN IPv6 transparent handling is unreliable on this gateway. Its output carries the subscriptions and the private domains, so never commit it; the secret is filled in on the box, not here. Its binary is a static release build under `/usr/local/bin`, not a package: update it by hand, validate the live @@ -118,8 +118,8 @@ targets instead of writing a config the core rejects. - WeChat resolves for itself, but its queries still cross the TUN, so `dns-hijack: any:53` catches them and the fake-ip table hands the name back to the rules: `mmbiz.qpic.cn` measured DIRECT. `multimedia.nt.qq.com.cn` stays in `fake-ip-filter` for the same reason. The exclude-process fix - that won clash-verge-rev#1762 is not available here: `hardening/bwraps/wechat.nix` sets - `unsharePid = true` and the sandbox reports uid 0, so no process name resolves. + that won clash-verge-rev#1762 is not available here: nixpak unshares the PID namespace and the + sandbox reports uid 0, so no process name resolves. - `find-process-mode: off` unless `PROCESS-*` rules or `tun_exclude_process` need it. - `tun_exclude_address`: a destination that can never be a proxy target should not pay a fake-ip round trip -- RFC1918, RFC 6598's `100.64.0.0/10` (where Tailscale addresses come from), diff --git a/outputs/aarch64-linux/src/12kingdoms-shoukei.nix b/outputs/aarch64-linux/src/12kingdoms-shoukei.nix index 37b863a9..b44416dc 100644 --- a/outputs/aarch64-linux/src/12kingdoms-shoukei.nix +++ b/outputs/aarch64-linux/src/12kingdoms-shoukei.nix @@ -23,7 +23,6 @@ let "hosts/12kingdoms-${name}" # nixos hardening "hardening/nixpaks" - "hardening/bwraps" ]) ++ [ { diff --git a/outputs/x86_64-linux/src/idols-ai.nix b/outputs/x86_64-linux/src/idols-ai.nix index 8764d595..5a70e363 100644 --- a/outputs/x86_64-linux/src/idols-ai.nix +++ b/outputs/x86_64-linux/src/idols-ai.nix @@ -24,7 +24,6 @@ let "hosts/idols-${name}" # nixos hardening "hardening/nixpaks" - "hardening/bwraps" ]) ++ [ {