mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
* feat: Add proxy_install_only config to restrict proxy to download commands Introduces proxy_install_only (default: false) which, when enabled, skips the proxy for package manager commands that do not download packages (e.g. npm ls, pip list), avoiding unnecessary MITM overhead. - Add ProxyInstallOnly to Config and config template - Add IsKnownDownloadCommand / MayDownloadPackages to ParsedCommand - Add DownloadCommands to npm and pypi PM configs covering update, ci, audit, dlx, exec, x, download, run and equivalents per PM - Extract shared runner.Execute used by both proxy flow and guard - Proxy flow short-circuits to runner.Execute for non-download commands when proxy_install_only=true * refactor: Inject CommandExecutor into guard to fix dependency direction guard depended on internal/runner, which inverted the intended layer hierarchy. Now guard defines a CommandExecutor function type and accepts it as a constructor argument. internal/flows (the composition root) creates the executor closure wrapping runner.Execute and injects it, keeping guard free of internal/ dependencies. * refactor: Invert proxy_install_only logic to use known non-download commands Replace the DownloadCommands allowlist (opt-in, fail-open) with a NonDownloadCommands denylist (opt-out, fail-safe). The proxy now runs for all commands except those explicitly known to not download packages. Unknown or future package manager subcommands default to running with the proxy. Includes script runners (run, start, test, stop, restart) that can spin up local servers — setting proxy env vars on these breaks them without providing any security benefit. Also covers removal commands and local operations that never contact the registry. * fix: Support PMG_* env vars regardless of config file state AutomaticEnv only resolves env vars for keys Viper already knows about via AllKeys(). When a key is absent from the config file (commented out, new key added after last setup, or no config file at all), Viper had no knowledge of it and silently skipped the env var. Fix by registering all Config struct fields as Viper defaults via reflection (using mapstructure tags) before reading the config file. This ensures PMG_* env vars work in all cases. Precedence: cobra flags > env vars > config file > defaults. SetDefault is used (not Set) so env vars and config file can still override the Go defaults freely. Tests added covering all precedence levels including the key-absent- from-config-file case that was the original bug report. * fix: Only check first non-flag arg against NonDownloadCommands Scanning all args caused false proxy bypasses when package names or script arguments matched a NonDownloadCommands entry. For example: - npm exec test → "test" matched, proxy incorrectly skipped - npm update config → "config" matched, proxy skipped - npm publish --tag version → "version" matched, proxy skipped Fix by checking only the first non-flag argument (the subcommand). If it is not in NonDownloadCommands we break immediately, so trailing args never influence the classification. Applied to all four parsers: npm, pip/pip3, uv, and poetry. Regression tests added for the false positive cases. * refactor: Replace reflection-based Viper defaults with embedded template Load the embedded config template as the Viper base so all keys are registered upfront, enabling PMG_* env vars to work regardless of whether a key exists in the user's config file. * fix: Restore trusted_packages template entry and revert DefaultConfig change * docs: Document environment variable overrides for config keys * update npm test cmd * refactor: extract shared non-download command detection helper Replaces duplicated first-non-flag-arg detection loops in npm.go and pypi.go (pip + poetry parsers) with a shared isFirstNonFlagArgInList helper in packagemanager.go. https://claude.ai/code/session_01AHaKF3vc2Haj9tK3jgUBAs --------- Co-authored-by: Claude <noreply@anthropic.com>
161 lines
6.3 KiB
YAML
161 lines
6.3 KiB
YAML
# PMG configuration template. Customize this file as needed.
|
|
# https://github.com/safedep/pmg
|
|
|
|
# Enable transitive dependency resolution. Default is true.
|
|
transitive: true
|
|
|
|
# Maximum depth of transitive dependencies to resolve. Default is 5.
|
|
transitive_depth: 5
|
|
|
|
# Include dev dependencies in the dependency graph. Default is false.
|
|
include_dev_dependencies: false
|
|
|
|
# UI verbosity level. Valid values: silent, normal, verbose. Default is normal.
|
|
# silent: PMG is hidden from the user except for errors and malicious package detection
|
|
# normal: Show minimal status updates
|
|
# verbose: Show verbose status updates and detailed information
|
|
verbosity: normal
|
|
|
|
# Enable paranoid mode. In paranoid mode, PMG will treat suspicious packages
|
|
# as malicious packages
|
|
paranoid: false
|
|
|
|
# Skip event logging. Default is false.
|
|
# When skip_event_logging is false, all events will be logged to file. These events are useful for audit
|
|
# trail and incident response on systems using PMG. Set this config to true to disable event logging.
|
|
skip_event_logging: false
|
|
|
|
# Event log retention days. Default is 7.
|
|
# This is the number of days to retain event logs.
|
|
event_log_retention_days: 7
|
|
|
|
# Proxy mode. Default is true.
|
|
# When enabled, PMG uses a proxy-based interception approach instead of the
|
|
# default guard-based analysis. The proxy intercepts package manager requests in real-time
|
|
# and analyzes packages as they are downloaded. Proxy mode may not work in all environments,
|
|
# and can be disabled to fall back to the guard-based analysis.
|
|
proxy_mode: true
|
|
|
|
# Restrict proxy to install commands only. Default is false.
|
|
# When false, the proxy intercepts all package manager commands (e.g., npm install, npm ls).
|
|
# When true, non-install commands bypass the proxy and execute directly, which can improve
|
|
# performance for commands that don't download packages (e.g., npm ls, pip list, npm outdated).
|
|
proxy_install_only: false
|
|
|
|
# Trusted packages are packages that are trusted by the user and will be ignored by the security guardrails.
|
|
# This is useful for packages that are known to be safe and are used in the application.
|
|
# Example:
|
|
# - purl: pkg:npm/@safedep/pmg
|
|
# reason: "PMG is a trusted package for PMG"
|
|
#
|
|
# When a package is specified without an explicit version, all versions of the package will be trusted.
|
|
# This feature should be used with caution and should be used for minimal set of packages.
|
|
#
|
|
# When a package is specified with an explicit version, only that version will be trusted.
|
|
#
|
|
# The purl is the package identifier and the reason is the reason for trusting the package.
|
|
# PURL specification: https://github.com/package-url/purl-spec
|
|
trusted_packages:
|
|
- purl: pkg:npm/@safedep/pmg
|
|
reason: "PMG is a trusted package for PMG"
|
|
|
|
# Sandbox configuration (EXPERIMENTAL)
|
|
# When enabled, package managers run in sandbox environments with restricted
|
|
# filesystem, network, and process execution access. This provides defense-in-depth
|
|
# protection against malicious install scripts and supply chain attacks.
|
|
#
|
|
# When sandboxing is enabled for a package manager, policy violations will block execution
|
|
# (no "warn-only" mode). Sandboxing itself can be disabled globally or per package manager.
|
|
#
|
|
# Currently supported platforms:
|
|
# - macOS (using Seatbelt sandbox-exec)
|
|
# - Linux (using Bubblewrap with namespace isolation)
|
|
# - Windows (planned)
|
|
#
|
|
# Platform-specific limitations:
|
|
# - Linux: Filesystem permissions use coarse-grained bind mounts. Glob patterns (e.g., *.txt)
|
|
# are expanded at policy translation time, but entire directories may be mounted rather than
|
|
# individual matching files. This is less precise than macOS regex-based filtering.
|
|
# - macOS: Network filtering is limited (all-or-nothing for most policies).
|
|
sandbox:
|
|
# Enable sandbox mode (opt-in, default: false for backward compatibility)
|
|
enabled: false
|
|
|
|
# Controls scope of sandbox enforcement:
|
|
# - true: sandbox applies to all package manager commands
|
|
# - false (default): sandbox only applies to install commands, others run unrestricted
|
|
# Requires 'enabled: true' and per-PM policies to be active. May break workflows expecting unrestricted commands.
|
|
enforce_always: false
|
|
|
|
# Policy templates define policy profiles by name and path.
|
|
# They can be used to override a built-in profile or create a custom profile.
|
|
# Note: Custom profiles loaded via policy_templates can inherit from built-in
|
|
# profiles using the 'inherits' field in the YAML (e.g., inherits: npm-restrictive).
|
|
# Inheritance allows you to extend a base profile with additional permissions.
|
|
policy_templates:
|
|
# Name for the template. Can be used to override a built-in profile or create a custom profile.
|
|
# Path is the path to the template file.
|
|
# Relative path can be used to reference a template file in the config directory (example: ./npm-restrictive.yml)
|
|
npm-restrictive-override:
|
|
path: ./profiles/npm-restrictive.yml
|
|
|
|
# Per-package-manager sandbox policies
|
|
# Each package manager can have its own policy to account for unique security characteristics
|
|
policies:
|
|
# npm ecosystem. npm-restrictive is a built-in profile.
|
|
npm:
|
|
enabled: true
|
|
profile: npm-restrictive # Built-in profile, template name, or path to custom YAML
|
|
|
|
pnpm:
|
|
enabled: true
|
|
profile: pnpm-restrictive
|
|
|
|
npx:
|
|
enabled: true
|
|
profile: npx
|
|
|
|
pnpx:
|
|
enabled: true
|
|
profile: npx
|
|
|
|
yarn:
|
|
enabled: true
|
|
profile: npm-restrictive
|
|
|
|
bun:
|
|
enabled: true
|
|
profile: npm-restrictive
|
|
|
|
# PyPI ecosystem. pypi-restrictive is a built-in profile.
|
|
pip:
|
|
enabled: true
|
|
profile: pypi-restrictive
|
|
|
|
pip3:
|
|
enabled: true
|
|
profile: pypi-restrictive
|
|
|
|
poetry:
|
|
enabled: true
|
|
profile: pypi-restrictive
|
|
|
|
uv:
|
|
enabled: true
|
|
profile: pypi-restrictive
|
|
|
|
# Dependency cooldown blocks installation of package versions published within
|
|
# a configurable time window.
|
|
dependency_cooldown:
|
|
enabled: true
|
|
days: 5
|
|
|
|
# Cloud sync configuration.
|
|
# When enabled, PMG audit events are synced to SafeDep Cloud for centralized visibility.
|
|
# Requires SAFEDEP_API_KEY and SAFEDEP_TENANT_ID environment variables for authentication.
|
|
cloud:
|
|
enabled: false
|
|
# Endpoint ID is not required. By default, it falls back to the machine's hostname.
|
|
# Set it only if you want to explicitly override the identifier for this endpoint.
|
|
# endpoint_id: "my-machine"
|