fix: Sandbox policy tuning for tmp write access #282
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: PMG E2E Tests | |
| on: | |
| pull_request: | |
| branches: | |
| - main | |
| push: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| e2e-test: | |
| name: PMG E2E Tests - All Package Managers | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 20 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest] | |
| defaults: | |
| run: | |
| shell: bash | |
| steps: | |
| - name: Checkout Source | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 | |
| - name: Setup Go | |
| uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5 | |
| with: | |
| go-version-file: go.mod | |
| - name: Setup Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: 20 | |
| check-latest: true | |
| - name: Setup PNPM | |
| uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4 | |
| with: | |
| version: 10 | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2 | |
| with: | |
| bun-version: latest | |
| - name: Setup Python | |
| uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Setup uv | |
| uses: astral-sh/setup-uv@caf0cab7a618c569241d31dcd442f54681755d39 | |
| - name: Install Poetry | |
| uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a | |
| - name: Build PMG | |
| run: make | |
| - name: Add pmg to PATH | |
| run: echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH | |
| - name: Setup PMG | |
| run: pmg setup install | |
| - name: Test PMG - Config File is Created | |
| run: | | |
| test -f $HOME/.config/safedep/pmg/config.yml | |
| - name: Test pmg.rc File is Created | |
| run: | | |
| test -f $HOME/.pmg.rc | |
| - name: Test NPM - Single Package & Manifest | |
| run: | | |
| echo "Testing NPM single package installation..." | |
| mkdir npm-test && cd npm-test | |
| pmg npm init -y | |
| pmg npm install express@5.2.1 | |
| pmg npm install lodash@4.17.21 | |
| # Verification: npm added packages present and manifest updated | |
| test -d node_modules/express | |
| test -d node_modules/lodash | |
| grep -q '"express"' package.json | |
| grep -q '"lodash"' package.json | |
| echo "Testing NPM manifest installation..." | |
| rm -rf node_modules package-lock.json | |
| pmg npm install | |
| # Verification: npm lockfile and installed modules exist after manifest install | |
| test -f package-lock.json | |
| test -d node_modules/express | |
| test -d node_modules/lodash | |
| cd .. && rm -rf npm-test | |
| - name: Test NPM - Experimental Proxy Mode | |
| run: | | |
| echo "Testing NPM with experimental proxy-based interception..." | |
| mkdir npm-proxy-test && cd npm-proxy-test | |
| pmg npm init -y | |
| echo "Testing proxy mode single package installation..." | |
| pmg --experimental-proxy-mode npm install express@5.2.1 | |
| pmg --experimental-proxy-mode npm install lodash@4.17.21 | |
| # Verification: packages installed via proxy mode | |
| test -d node_modules/express | |
| test -d node_modules/lodash | |
| grep -q '"express"' package.json | |
| grep -q '"lodash"' package.json | |
| echo "Testing proxy mode manifest installation..." | |
| rm -rf node_modules package-lock.json | |
| pmg --experimental-proxy-mode npm install | |
| # Verification: manifest install via proxy mode works | |
| test -f package-lock.json | |
| test -d node_modules/express | |
| test -d node_modules/lodash | |
| echo "Testing proxy mode with scoped package..." | |
| pmg --experimental-proxy-mode npm install @types/node@18.0.0 | |
| # Verification: scoped package installed via proxy | |
| test -d node_modules/@types | |
| test -d node_modules/@types/node | |
| grep -q '"@types/node"' package.json | |
| echo "Testing proxy mode dry-run (should not create files)..." | |
| rm -rf node_modules package-lock.json | |
| pmg --experimental-proxy-mode --dry-run npm install | |
| # Verification: dry-run doesn't create files even in proxy mode | |
| test ! -d node_modules | |
| test ! -f package-lock.json | |
| cd .. && rm -rf npm-proxy-test | |
| - name: Test PNPM - Single Package & Manifest | |
| run: | | |
| echo "Testing PNPM single package installation..." | |
| mkdir pnpm-test && cd pnpm-test | |
| pmg pnpm init | |
| pmg pnpm add express@5.2.1 | |
| pmg pnpm add lodash@4.17.21 | |
| # Verification: pnpm packages installed and lockfile created | |
| test -d node_modules/express | |
| test -d node_modules/lodash | |
| test -f pnpm-lock.yaml | |
| echo "Testing PNPM manifest installation..." | |
| rm -rf node_modules pnpm-lock.yaml | |
| pmg pnpm install | |
| # Verification: pnpm lockfile and modules exist after manifest install | |
| test -f pnpm-lock.yaml | |
| test -d node_modules/express | |
| test -d node_modules/lodash | |
| cd .. && rm -rf pnpm-test | |
| - name: Test Bun - Single Package & Manifest | |
| run: | | |
| echo "Testing Bun single package installation..." | |
| mkdir bun-test && cd bun-test | |
| pmg bun init -y | |
| pmg bun add express@5.2.1 | |
| pmg bun add lodash@4.17.21 | |
| # Verification: bun packages installed and lockfile created | |
| test -d node_modules/express | |
| test -d node_modules/lodash | |
| test -f bun.lock | |
| echo "Testing Bun manifest installation..." | |
| rm -rf node_modules bun.lock | |
| pmg bun install | |
| # Verification: bun lockfile and modules exist after manifest install | |
| test -f bun.lock | |
| test -d node_modules/express | |
| test -d node_modules/lodash | |
| cd .. && rm -rf bun-test | |
| - name: Test Yarn - Single Package & Manifest | |
| run: | | |
| echo "Testing Yarn single package installation..." | |
| export YARN_ENABLE_HARDENED_MODE=0 | |
| npm install -g yarn@1.22.22 | |
| yarn --version | |
| mkdir yarn-test && cd yarn-test | |
| pmg yarn init -y | |
| pmg yarn add express@5.2.1 | |
| pmg yarn add lodash@4.17.21 | |
| # Verification: yarn packages installed and lockfile created | |
| test -d node_modules/express | |
| test -d node_modules/lodash | |
| test -f yarn.lock | |
| echo "Testing Yarn manifest installation..." | |
| rm -rf node_modules yarn.lock | |
| pmg yarn install | |
| # Verification: yarn lockfile and modules exist after manifest install | |
| test -f yarn.lock | |
| test -d node_modules/express | |
| test -d node_modules/lodash | |
| cd .. && rm -rf yarn-test | |
| - name: Test NPX - Package Execution | |
| run: | | |
| echo "Testing NPX package execution..." | |
| mkdir npx-test && cd npx-test | |
| echo "Testing npx with a simple package..." | |
| pmg npx cowsay@1.6.0 "Hello from pmg npx" | tee npx-output.txt | |
| # Verification: cowsay output contains our message | |
| grep -q "Hello from pmg npx" npx-output.txt | |
| echo "Testing npx with --package flag..." | |
| pmg npx --package cowsay@1.6.0 -- cowsay "Hello with package flag" | tee npx-pkg-output.txt | |
| # Verification: package flag execution produces expected output | |
| grep -q "Hello with package flag" npx-pkg-output.txt | |
| echo "Testing npx dry-run mode..." | |
| pmg --dry-run npx cowsay@1.6.0 "This should not execute" | tee npx-dry-output.txt | |
| # Verification: dry-run should NOT produce cowsay ASCII art (cow face ^__^ should not appear) | |
| ! grep -q '\^__\^' npx-dry-output.txt | |
| cd .. && rm -rf npx-test | |
| - name: Test PNPX - Package Execution | |
| run: | | |
| echo "Testing PNPX package execution..." | |
| mkdir pnpx-test && cd pnpx-test | |
| echo "Testing pnpx with a simple package..." | |
| pmg pnpx cowsay@1.6.0 "Hello from pmg pnpx" | tee pnpx-output.txt | |
| # Verification: cowsay output contains our message | |
| grep -q "Hello from pmg pnpx" pnpx-output.txt | |
| echo "Testing pnpx with --package flag..." | |
| pmg pnpx --package cowsay@1.6.0 -- cowsay "Hello with package flag" | tee pnpx-pkg-output.txt | |
| # Verification: package flag execution produces expected output | |
| grep -q "Hello with package flag" pnpx-pkg-output.txt | |
| echo "Testing pnpx dry-run mode..." | |
| pmg --dry-run pnpx cowsay@1.6.0 "This should not execute" | tee pnpx-dry-output.txt | |
| # Verification: dry-run should NOT produce cowsay ASCII art (cow face ^__^ should not appear) | |
| ! grep -q '\^__\^' pnpx-dry-output.txt | |
| cd .. && rm -rf pnpx-test | |
| - name: Test Pip - Single Package & Manifest | |
| run: | | |
| echo "Testing Pip single package installation..." | |
| mkdir pip-test && cd pip-test | |
| python -m venv venv && source venv/bin/activate | |
| pmg pip install requests==2.32.4 | |
| pmg pip install numpy==2.3.5 | |
| pmg pip freeze > requirements.txt | |
| # Verification: requirements.txt contains expected packages | |
| test -s requirements.txt | |
| grep -E '^requests==' requirements.txt | |
| grep -E '^numpy==' requirements.txt | |
| echo "Testing Pip manifest installation..." | |
| pmg pip uninstall -y requests numpy | |
| pmg pip install -r requirements.txt | |
| # Verification: imported packages are available in the environment | |
| python -c "import requests, numpy; print(requests.__version__); print(numpy.__version__)" | |
| deactivate | |
| cd .. && rm -rf pip-test | |
| - name: Test Pip3 - Single Package & Manifest | |
| run: | | |
| echo "Testing Pip3 single package installation..." | |
| mkdir pip3-test && cd pip3-test | |
| python -m venv venv && source venv/bin/activate | |
| pmg pip3 install requests==2.32.4 | |
| pmg pip3 install numpy==2.3.5 | |
| pmg pip3 freeze > requirements.txt | |
| # Verification: requirements.txt contains expected packages | |
| test -s requirements.txt | |
| grep -E '^requests==' requirements.txt | |
| grep -E '^numpy==' requirements.txt | |
| echo "Testing Pip3 manifest installation..." | |
| pmg pip3 uninstall -y requests numpy | |
| pmg pip3 install -r requirements.txt | |
| # Verification: imported packages are available in the environment | |
| python -c "import requests, numpy; print(requests.__version__); print(numpy.__version__)" | |
| deactivate | |
| cd .. && rm -rf pip3-test | |
| - name: Test UV - Single Package & Manifest | |
| run: | | |
| echo "Testing UV single package installation..." | |
| mkdir uv-test && cd uv-test | |
| pmg uv init --no-readme | |
| pmg uv add requests==2.32.4 | |
| pmg uv add numpy==2.3.5 | |
| # Verification: pyproject.toml lists expected dependencies | |
| test -f pyproject.toml | |
| grep -q 'requests' pyproject.toml | |
| grep -q 'numpy' pyproject.toml | |
| echo "Testing UV manifest installation..." | |
| rm -rf .venv uv.lock | |
| pmg uv sync | |
| # Verification: uv lockfile and virtualenv created; packages present | |
| test -d .venv | |
| test -f uv.lock | |
| pmg uv pip show requests >/dev/null | |
| pmg uv pip show numpy >/dev/null | |
| echo "Testing UV pip commands..." | |
| pmg uv pip freeze > requirements.txt | |
| pmg uv pip install -r requirements.txt | |
| pmg uv pip sync requirements.txt | |
| # Verification: uv pip can show installed packages after requirements sync | |
| pmg uv pip show requests >/dev/null | |
| pmg uv pip show numpy >/dev/null | |
| cd .. && rm -rf uv-test | |
| - name: Test Poetry - Single Package & Manifest | |
| run: | | |
| echo "Testing Poetry single package installation..." | |
| mkdir poetry-test && cd poetry-test | |
| pmg poetry init --name poetry-test --no-interaction --quiet | |
| pmg poetry add requests==2.32.4 | |
| pmg poetry add numpy==2.3.5 | |
| # Verification: pyproject.toml dependencies updated | |
| test -f pyproject.toml | |
| grep -q 'requests' pyproject.toml | |
| grep -q 'numpy' pyproject.toml | |
| echo "Testing Poetry manifest installation..." | |
| rm -rf .venv poetry.lock | |
| pmg poetry install --no-root | |
| cd .. && rm -rf poetry-test | |
| - name: Test Malicious Package Detection | |
| run: | | |
| echo "Testing malicious package detection..." | |
| mkdir malicious-test && cd malicious-test | |
| pmg npm init -y | |
| ! pmg npm install nyc-config@10.0.0 || echo "Malicious package correctly blocked" | |
| cd .. && rm -rf malicious-test | |
| - name: Test safedep-test-pkg is Blocked using Proxy mode | |
| run: | | |
| echo "Testing that safedep-test-pkg is blocked..." | |
| mkdir safedep-test-pkg-test && cd safedep-test-pkg-test | |
| pmg npm init -y | |
| # Attempt to install safedep-test-pkg - should fail | |
| if pmg --experimental-proxy-mode npm --no-cache --prefer-online i safedep-test-pkg@0.1.3; then | |
| echo "ERROR: safedep-test-pkg was not blocked!" | |
| exit 1 | |
| else | |
| echo "SUCCESS: safedep-test-pkg correctly blocked" | |
| fi | |
| # Verify package is not installed locally | |
| if [ -d "node_modules/safedep-test-pkg" ]; then | |
| echo "ERROR: safedep-test-pkg found in node_modules!" | |
| exit 1 | |
| else | |
| echo "SUCCESS: safedep-test-pkg not present in node_modules" | |
| fi | |
| cd .. && rm -rf safedep-test-pkg-test | |
| - name: Test PMG Modes | |
| run: | | |
| echo "Testing different PMG modes..." | |
| mkdir pmg-modes-test && cd pmg-modes-test | |
| pmg npm init -y | |
| # Mode: --dry-run should not create node_modules or lockfiles | |
| pmg --dry-run npm install express | |
| # Verification: no files created during dry-run | |
| test ! -d node_modules | |
| test ! -f package-lock.json | |
| # Mode: --silent should install without noisy output | |
| pmg --silent npm install express | |
| # Verification: package installed | |
| test -d node_modules/express | |
| # Clean and test --verbose installation | |
| rm -rf node_modules package-lock.json | |
| pmg --verbose npm install express | |
| # Verification: package installed | |
| test -d node_modules/express | |
| # Clean and test --debug with log output | |
| rm -rf node_modules package-lock.json | |
| pmg --debug --log debug.json npm install express | |
| # Verification: debug log written | |
| test -f debug.json | |
| # Mode: --paranoid may require cloud credentials; run non-blocking with dry-run | |
| pmg --paranoid --dry-run npm install express || true | |
| cd .. && rm -rf pmg-modes-test | |
| sandbox-e2e-macos: | |
| name: Sandbox E2E - macOS | |
| runs-on: macos-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout Source | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 | |
| - name: Setup Go | |
| uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5 | |
| with: | |
| go-version-file: go.mod | |
| - name: Setup Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: 20 | |
| check-latest: true | |
| - name: Setup PNPM | |
| uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4 | |
| with: | |
| version: 10 | |
| - name: Build PMG | |
| run: make | |
| - name: Add pmg to PATH | |
| run: echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH | |
| - name: Setup PMG | |
| run: pmg setup install | |
| - name: Create Test Directories for Sandbox Permissions Tests | |
| run: mkdir -p ~/.aws ~/.gcloud ~/.kube ~/.ssh | |
| - name: Create Test Files for Sandbox Permissions Tests | |
| run: | | |
| touch ~/.aws/credentials | |
| touch ~/.gcloud/credentials.json | |
| touch ~/.kube/config | |
| touch ~/.ssh/id_rsa | |
| - name: Run Sandbox E2E Test | |
| run: pmg --sandbox --sandbox-enforce npm exec -- node test/sandbox-e2e.js | |
| - name: Run Package Manager E2E Test | |
| run: pmg --sandbox --sandbox-enforce npm exec -- node test/pm-e2e.js | |
| sandbox-e2e-linux: | |
| name: Sandbox E2E - Linux (Bubblewrap) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| defaults: | |
| run: | |
| shell: bash | |
| steps: | |
| - name: Checkout Source | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 | |
| - name: Setup Go | |
| uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5 | |
| with: | |
| go-version-file: go.mod | |
| - name: Setup Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: 20 | |
| check-latest: true | |
| - name: Setup PNPM | |
| uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4 | |
| with: | |
| version: 10 | |
| - name: Install Bubblewrap | |
| run: sudo apt-get update && sudo apt-get install -y bubblewrap | |
| - name: Verify Bubblewrap Installation | |
| run: bwrap --version | |
| - name: Build PMG | |
| run: make | |
| - name: Add pmg to PATH | |
| run: echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH | |
| - name: Setup PMG | |
| run: pmg setup install | |
| - name: Create Test Directories for Sandbox Permissions Tests | |
| run: mkdir -p ~/.aws ~/.gcloud ~/.kube ~/.ssh ~/.gnupg ~/.docker | |
| - name: Create Test Files for Sandbox Permissions Tests | |
| run: | | |
| touch ~/.aws/credentials | |
| touch ~/.gcloud/credentials.json | |
| touch ~/.kube/config | |
| touch ~/.ssh/id_rsa | |
| touch ~/.gnupg/pubring.kbx | |
| touch ~/.docker/config.json | |
| - name: Disable AppArmor for Bubblewrap | |
| run: | | |
| sudo systemctl stop apparmor | |
| sudo systemctl disable apparmor | |
| sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 | |
| - name: Run Sandbox E2E Test | |
| run: pmg --sandbox --sandbox-enforce --sandbox-profile npm-restrictive npm exec -- node test/sandbox-e2e.js | |
| - name: Run Package Manager E2E Test | |
| run: pmg --sandbox --sandbox-enforce --sandbox-profile npm-restrictive npm exec -- node test/pm-e2e.js |