Skip to content

Add macOS support for local package analysis#1128

Open
dsoni-affirm wants to merge 1 commit intoossf:mainfrom
dsoni-affirm:feat/macos-support
Open

Add macOS support for local package analysis#1128
dsoni-affirm wants to merge 1 commit intoossf:mainfrom
dsoni-affirm:feat/macos-support

Conversation

@dsoni-affirm
Copy link

@dsoni-affirm dsoni-affirm commented Mar 4, 2026

Add macOS Support for Local Package Analysis

Problem

Package Analysis currently only works on Linux for local analysis. Developers on macOS cannot run the analysis
pipeline locally because of several platform-specific incompatibilities:

  1. gVisor (runsc) is Linux-only — it cannot run inside Docker Desktop's LinuxKit VM, so the sandbox runtime fails
    entirely on macOS.
  2. crun has memfd re-execution errors in Docker Desktop, preventing nested container execution.
  3. Overlay storage driver doesn't work on macOS due to missing kernel whiteout support for nested containers.
  4. Shell utilities differ — macOS realpath doesn't support the -m flag, and findmnt is not available, causing the
    run_analysis.sh script to fail.
  5. rmdir --ignore-fail-on-non-empty is a GNU extension not available on macOS.

This means any contributor using macOS has to either spin up a Linux VM manually or push to CI for every change,
significantly slowing down the development feedback loop.

Solution

This PR adds macOS detection and compatibility shims so that run_analysis.sh and the Go analysis code gracefully
degrade on macOS while preserving full functionality on Linux.

Shell script changes (scripts/run_analysis.sh)

  • Platform-aware realpath: Falls back to dirname/basename resolution when realpath -m is unavailable.
  • findmnt guard: Checks for findmnt availability before calling it; assumes non-matching filesystem type on macOS.
  • macOS runtime configuration (activated when uname == Darwin):
    • Uses a Docker named volume instead of host bind mounts (avoids pivot_root failures).
    • Forces the vfs storage driver for Podman inside the container (avoids overlay incompatibility).
    • Disables seccomp for nested containers (required for runc in Docker Desktop).
    • Provides a runsc shim script that transparently redirects gVisor calls to runc, stripping unsupported flags.
    • Extracts a real runc binary from the analysis image on first run (cached at ~/.cache/pa-runc/runc) to replace
      the broken crun.
    • Uses a custom entrypoint wrapper to copy the runc binary into the container's writable filesystem at startup.
  • Cross-platform rmdir: Removed GNU-specific --ignore-fail-on-non-empty flag for portability.
  • Moved ANALYSIS_IMAGE variable assignment earlier so it can be referenced during macOS setup.

Go analysis changes (internal/dynamicanalysis/analysis.go)

  • Graceful degradation when strace is unavailable: Instead of returning a fatal error when the strace log cannot be
    opened or parsed (which always happens with runc since it doesn't produce strace logs like gVisor), the analysis now
    returns partial results containing DNS data and stdout/stderr.
  • New setDNSData method: Extracts and populates only the DNS portion of the analysis result, used as a fallback when
    full strace data is unavailable.

Trade-offs

  • No syscall tracing on macOS: Since gVisor can't run on macOS, strace-based analysis (file access, network
    connections, command execution) is unavailable. Only DNS queries, stdout, and stderr are captured.
  • No packet capture on macOS: Network packet capture depends on gVisor's networking stack and is not available with
    runc.
  • One-time setup cost: The first run on macOS extracts a runc binary from the analysis image, which takes a bit
    longer. Subsequent runs use the cached binary.

Testing

  • Verified on macOS (Apple Silicon) with Docker Desktop
  • Confirmed Linux behavior is unchanged (all macOS-specific code paths are gated behind uname == Darwin or runtime
    availability checks)

Docker Desktop's LinuxKit VM lacks several Linux-specific features needed
by the analysis pipeline (findmnt, overlay fs whiteouts, gVisor/runsc,
crun memfd). This adds automatic macOS detection that:

- Uses Docker named volumes instead of host bind mounts (pivot_root compat)
- Forces vfs storage driver for podman (overlay not supported)
- Replaces gVisor runsc with runc via a shim script
- Disables seccomp for nested containers (runc requirement in Docker Desktop)
- Makes strace log parsing non-fatal so dynamic analysis returns partial
  results (status, stdout/stderr, DNS) when gVisor logs are unavailable
- Fixes macOS-incompatible commands (findmnt, realpath -m, rmdir flags)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant