diff --git a/packages/openclaw-image/default.nix b/packages/openclaw-image/default.nix index 872a56b..4a11413 100644 --- a/packages/openclaw-image/default.nix +++ b/packages/openclaw-image/default.nix @@ -159,9 +159,6 @@ pkgs.dockerTools.buildLayeredImage { # Node user home directory nodeHome - # The openclaw application extracted from the upstream image - openclawApp - # Docker entrypoint script (in /usr/local/bin) entrypointPkg @@ -184,6 +181,10 @@ pkgs.dockerTools.buildLayeredImage { # Gitea CLI (PR workflow) pkgs.tea ]; + # NOTE: openclawApp is NOT in contents. It would create /app as a symlink + # to /nix/store/..., which breaks OpenClaw's symlink escape security check + # (resolved paths "escape" /app/dist/extensions). Instead, extraCommands + # copies the real files into /app as a proper directory. extraCommands = '' # Create /tmp with correct permissions (needed by Node.js and nix) @@ -195,6 +196,14 @@ pkgs.dockerTools.buildLayeredImage { # Create /var/empty (referenced by NSS passwd home dirs) mkdir -p var/empty + + # Copy OpenClaw app as a REAL directory (not a Nix store symlink). + # The app has a symlink escape check: resolved paths must stay within + # /app/dist/extensions/. If /app is a symlink to /nix/store/HASH/app/, + # realpath resolves to /nix/store/... which "escapes" the boundary. + rm -rf app + mkdir -p app + cp -a ${openclawApp}/app/. app/ ''; config = {