pak::pkg_install() fails on corporate Windows where AppLocker blocks cmdunzip.exe
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 35/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Stale
- Tech stack
- r
- Domain
- operating-systems, tooling
Research direction
Start with pkgdepends:::make_install_process(), tracing its make_unzip_process() and zip::unzip_process() calls on Windows. Compare the proposed internal zip::unzip() path with the existing process-based path, and verify that package installation works when cmdunzip.exe is blocked by AppLocker without breaking non-zip archives.
Written by the indexing model from the issue text.
Description
Problem
pak::pkg_install() downloads packages successfully but fails during extraction on corporate Windows machines with AppLocker or Software Restriction Policies:
pak::pkg_install("dplyr")
#> Downloaded 27 packages (53.27 MB) in 40.9s
#> Error:
#> ! error in pak subprocess
#> Caused by error in `process_initialize(...)`:
#> ! Native call to `processx_exec` failed
#> Caused by error:
#> ! create process 'C:/Users/.../pak/library/zip/bin/x64/cmdunzip.exe'
#> (system error 1260, This program is blocked by group policy.)
The root cause is that pkgdepends:::make_install_process() calls make_unzip_process() → zip::unzip_process(), which spawns cmdunzip.exe as an external process. Corporate group policy blocks this .exe.
Standard R configuration (R_UNZIPCMD, options(unzip=), TAR) has no effect (I had TAR available on my corporate PC) because pak's internal code path ignores all of these.
Impact
This completely blocks pak on corporate Windows. The alternative is install.packages(), which loses pak's parallel downloads and dependency resolution and takes 6-10x longer (over an hour vs ~10 minutes in my case).
Proposed solution
Short term: Add a pak configuration option (e.g., PKG_ZIP_METHOD = "internal") that tells pkgdepends to use zip::unzip() (in-process C code, no external .exe) instead of zip::unzip_process() for .zip extraction.
Long term: The upstream fix belongs in the zip package — see r-lib/zip#135. If zip::unzip_process() could fall back to zip::unzip() when process creation fails, pak would inherit the fix automatically.
Working workaround
We developed a patch that replaces make_install_process in pak's worker subprocess. It extracts .zip files synchronously using zip::unzip(), then returns a real processx::process object (a finished cmd /c exit 0) so pak's async polling loop continues normally. Non-zip archives use the original code path.
library(pak)
pak:::remote(function() {
ns <- asNamespace("pkgdepends")
original <- get("make_install_process", envir = ns)
replacement <- function(filename, lib = .libPaths()[[1L]], metadata = NULL) {
type <- ns$detect_package_archive_type(filename)
if (type != "zip") return(original(filename, lib = lib, metadata = metadata))
now <- Sys.time()
lib_cache <- ns$library_cache(lib)
ns$mkdirp(pkg_cache <- tempfile(tmpdir = lib_cache))
zip::unzip(filename, exdir = pkg_cache, overwrite = TRUE)
ns$install_extracted_binary(filename, lib_cache, pkg_cache, lib, metadata, now)
p <- processx::process$new("cmd.exe", c("/c", "exit", "0"),
stdout = "|", stderr = "2>&1")
p$wait()
reg.finalizer(p, function(...) unlink(pkg_cache, recursive = TRUE), onexit = TRUE)
p
}
unlockBinding("make_install_process", ns)
assign("make_install_process", replacement, envir = ns)
lockBinding("make_install_process", ns)
invisible(TRUE)
})
pak::pkg_install("dplyr") # works
Tested successfully with 100+ packages on Windows 11 Enterprise with AppLocker.
Only issue with this is I have to source("patch_pak.R") after each library(pak) load or jam it into my .Rprofile, which would be fine if it was just me, but there's a few hundred R users where I am.
Environment
- Windows 11 Enterprise with AppLocker/SRP enabled
- R 4.4.x
- pak 0.8.0+
- Dominant language
- C
- Stars
- 821
- Forks
- 88
- Avg merge
- 17m
- Merged PRs (30d)
- 1
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from r-lib/pak
-
documentation upkeep
Difficulty 1/5 Under an hour Newbie friendliness 68/100
-
Difficulty 3/5 1-2 days Newbie friendliness 72/100
-
Difficulty 4/5 3-5 days Newbie friendliness 38/100
-
Difficulty 3/5 1-2 days Newbie friendliness 68/100
-
Difficulty 4/5 3-5 days Newbie friendliness 30/100
Similar issues
-
[adam] AdamNet network read doesn't cap to MAX_ADAM_PACKET_LEN, overflows client receive buffers Open
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
FujiNetWIFI/fujinet-firmware#1649 · 2 comments ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
HarbourMasters/Shipwright#7229 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
riscv-software-src/riscv-isa-sim#2435 · 1 comment ·
-
bug Self Built Image SNAPSHOT Supported Device target/ramips
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100