Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/R-CMD-check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,9 @@ jobs:
with:
upload-snapshots: true
build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")'

- name: Run full test suite
run: |
Rscript -e 'devtools::test()'
env:
NOT_CRAN: true
4 changes: 2 additions & 2 deletions .github/workflows/test-coverage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

on:
push:
branches: [main, master]
pull_request:
tags:
- 'v*.*.*'

name: test-coverage

Expand Down
19 changes: 8 additions & 11 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,18 +171,14 @@ Main R Process (Controller) ←──nanonext REQ/REP──→ Worker R Process
- Configurable via options: `replr.worker.type = "macos-sandbox"`, `replr.worker.macos.sandbox.profile`
- **Default Security Profile** (auto-generated using Sandbox Profile Language):
- **Filesystem access**:
- Read: System files (`/System`, `/Library`, `/usr/lib`), R installation, user R libraries
- Write: Only `/tmp` and `/private/tmp` directories
- Blocked: Home directory writes and other user locations
- Read: All files (allows R to read system files, libraries, data)
- Write: Only `/tmp`, `/private/tmp`, `/var/tmp` and `.Rtmp*` directories
- Blocked: Home directory writes (except temp directories)
- **Network access**:
- Allowed: Localhost/loopback only (`127.0.0.1`, `::1`)
- Blocked: All outbound internet access, network binding to external interfaces
- **Process operations**:
- Allowed: Process execution, forking, signaling
- Allowed: IPC (POSIX shared memory, semaphores, Mach lookups)
- **System access**:
- Allowed: Reading system info via `sysctl`
- Blocked: System socket creation, system modifications
- Allowed: Localhost only (for IPC with host process)
- Blocked: All outbound external network access
- **Other operations**: Allows process execution, IPC, and system calls needed for R to function
- **Implementation**: Uses `(allow default)` with specific denials for network-outbound and home directory writes
- **Custom Profiles**: Support for custom `.sb` profile files using Sandbox Profile Language (SBPL)
- **Profile Management**: Default profiles auto-generated at runtime, temporary profiles cleaned up via finalizer
- **Process Management**: Worker executed as `sandbox-exec -f <profile> Rscript worker.R <port>`
Expand Down Expand Up @@ -318,3 +314,4 @@ Global options control package behavior:

**macOS Sandbox Configuration:**
- `replr.worker.macos.sandbox.profile` (string): Path to custom sandbox profile (.sb) file (default: NULL)
- to memorize : when testing scripts and examples, always use devtools::load_all() and source from within an R session instead of using Rscript
26 changes: 17 additions & 9 deletions R/worker-wrappers.R
Original file line number Diff line number Diff line change
Expand Up @@ -533,23 +533,31 @@ MacOSSandboxWorkerWrapper <- R6::R6Class(
private$.temp_profile <- profile_file

# Default macOS sandbox profile using Sandbox Profile Language (SBPL)
# Note: macOS sandbox-exec has complex, undocumented restrictions
# We use a permissive profile that blocks external network only
profile_content <- paste(
# Provides network isolation and filesystem write restrictions
profile_content <- c(
"; macOS Sandbox Profile for replr worker",
"; Allows most operations but blocks external network access",
"; Provides network isolation and home directory write protection",
"(version 1)",
"",
"; Start with default allow for most operations",
"; Allow most operations by default (R needs many system calls)",
"(allow default)",
"",
"; Block network access except to localhost",
"; This provides network isolation while keeping R functional",
"; === Network Restrictions ===",
"; Block external network access (but allow localhost for IPC)",
"(deny network-outbound (remote ip))",
"(allow network* (remote tcp \"localhost:*\"))",
"(allow network* (remote ip \"localhost:*\"))",
"(allow network* (local ip \"localhost:*\"))",
sep = "\n"
"",
"; === Filesystem Write Restrictions ===",
"; Deny writes to home directory (users' files)",
sprintf("(deny file-write* (subpath \"%s\"))", path.expand("~")),
"; But allow writes to temp directories even if in home",
"(allow file-write* (subpath \"/tmp\"))",
"(allow file-write* (subpath \"/private/tmp\"))",
"(allow file-write* (subpath \"/var/tmp\"))",
sprintf("(allow file-write* (regex #\"^%s/\\\\.Rtmp.*\"))", path.expand("~"))
)
profile_content <- paste(profile_content, collapse = "\n")

writeLines(profile_content, profile_file)
debug_log("Created temporary macOS sandbox profile: ", profile_file)
Expand Down
43 changes: 0 additions & 43 deletions inst/examples/docker-integration-demo.R

This file was deleted.

184 changes: 0 additions & 184 deletions inst/examples/firejail-demo.R

This file was deleted.

Loading