fix(nixpak): pass the session TZ through to sandboxes

ICU takes the zone name from the /etc/localtime symlink target path. A bind
mount turns it into a plain file, which keeps the TZif data but loses the
path, so the only identifier left is the ambiguous "CST" abbreviation that
ICU reads from the file and maps to America/Chicago.

Export TZ from time.timeZone and pass TZ/TZDIR through the nixpak env
allowlist.

Assisted-by: DeepSeek Harness (deepseek-flash)
This commit is contained in:
Ryan Yin committed 2026-11-04 21:38:18 +08:00
1 parent 13d95daa36
commit c4a00e507c
5 files changed
+19 -1

No files matched your search

+1
View File
@@ -17,6 +17,7 @@ workflow.
- Cleared environment; filtered session D-Bus; private `/dev/shm`; per-app `/tmp`. Chromium-family
browsers share an app-specific `/tmp` so external URLs reuse one browser instance.
- Read-only `/nix/store`; GPU and display; fonts and themes; LAN and Internet.
- Host timezone: `TZ` and `TZDIR` are passed through from the session environment.
- Portals for file chooser, URI opening, notifications, input methods and document exports.
- No whole host home, system D-Bus, SSH agent, raw USB/serial or raw camera. The only device
passthrough is a security key's FIDO interface for Firefox/Chromium/Chrome; see [Limits](#limits).
@@ -151,6 +151,11 @@
"NO_AT_BRIDGE"
"QT_QPA_PLATFORMTHEME"
"QT_WAYLAND_DISABLE_WINDOWDECORATION"
# ICU takes the zone name from the /etc/localtime symlink target path, but
# the sandbox binds it as a plain file, leaving only the ambiguous "CST"
# abbreviation; pass the name from the session.
"TZ"
"TZDIR"
] (name: sloth.envOr name "");
};
}
+6
View File
@@ -144,6 +144,12 @@ let
"${name}/personalFiles" =
(app.browserPermissions.personalFiles or false) == (spec.personalFiles or false);
"${name}/secretPortal" = secretPortalCheck app (spec.secretPortal or false);
# nixpak resolves "env" entries from the launcher environment.
"${name}/timeZonePassthrough" =
app.bubblewrap.env ? TZ
&& app.bubblewrap.env.TZ.type == "env"
&& app.bubblewrap.env ? TZDIR
&& app.bubblewrap.env.TZDIR.type == "env";
};
extraChecks = lib.mapAttrs' (checkName: value: {
name = "${name}/${checkName}";
+4 -1
View File
@@ -1,8 +1,11 @@
{ lib, ... }:
{ config, lib, ... }:
{
# Set your time zone. A default: the computer-use VMs match their proxy region.
time.timeZone = lib.mkDefault "Asia/Shanghai";
# Passed through to nixpak sandboxes; see hardening/nixpaks/modules/desktop-base.nix.
environment.sessionVariables.TZ = config.time.timeZone;
# English is the default. Chinese overrides only the categories where the
# en_US default is factually wrong for China (metric, A4, CNY); everything
# else, including date/time names, stays English.
@@ -6,7 +6,10 @@
}:
let
pkgs = outputs.nixosConfigurations.ai-niri.pkgs;
hostConfig = outputs.nixosConfigurations.ai-niri.config;
in
# The sandboxes pass TZ through from the session environment.
assert hostConfig.environment.sessionVariables.TZ == hostConfig.time.timeZone;
import ../../../../hardening/tests/policy.nix {
inherit pkgs mylib;
mkNixPak = inputs.nixpak.lib.nixpak {