# 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 # Disable anonymous telemetry. Default is false. disable_telemetry: 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 # Optional message appended to every block output, regardless of which control # blocked the installation (malware analysis, dependency cooldown, etc.). # Useful for org deployments to point developers at internal policy docs or a # security contact. Example: # advisory_message: "Blocked by ACME security policy. Questions? #security-help" advisory_message: "" # Proxy configuration. # 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: enabled: true # When true, only install commands are proxied. Other commands # (e.g., npm ls, pip list) bypass the proxy and execute directly. install_only: false # Per-package-manager commands to skip proxying (only applies when install_only is true). # Example: # skip_commands: # pip: ["list", "show"] skip_commands: npm: [] # Persistent proxy server (`pmg proxy start`) settings. server: # Host the persistent proxy binds to. Defaults to 127.0.0.1 (loopback), # which keeps the MITM proxy private to the host (the right choice for CI # and local use). Set to 0.0.0.0 or a specific interface ONLY for a # deliberately hosted deployment: a non-loopback bind exposes the proxy, # and every client must trust the PMG CA. The --host flag overrides this. listen_host: 127.0.0.1 # Port the persistent proxy binds to. 0 means a random free port. The # --port flag overrides this. listen_port: 0 # 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 the shared base profile; each package # manager maps to a leaf profile that re-allows only its own environment # variables. npm: enabled: true profile: npm # Built-in profile, template name, or path to custom YAML pnpm: enabled: true profile: pnpm npx: enabled: true profile: npx pnpx: enabled: true profile: npx yarn: enabled: true profile: yarn bun: enabled: true profile: bun # PyPI ecosystem. pypi-restrictive is the shared base profile; each # package manager maps to a leaf profile that re-allows only its own # environment variables. pip: enabled: true profile: pip pip3: enabled: true profile: pip pipx: enabled: true profile: pipx poetry: enabled: true profile: poetry uv: enabled: true profile: uv uvx: enabled: true profile: uvx # Go ecosystem (experimental). The go command is opt-in: it runs only when # invoked explicitly as `pmg go ...`. go: enabled: true profile: go # Dependency cooldown blocks installation of package versions published within # a configurable time window. dependency_cooldown: enabled: true days: 5 # Per-control skip list of packages exempt from the cooldown window. # Packages here are STILL malware-scanned — only the cooldown wait is waived. # Use it for first-party / internal packages that must be installed immediately # on release (e.g. to sanity-test a freshly published version). # # To bypass every PMG control (malware analysis, cooldown, and any future # controls) for a package, add it to the top-level trusted_packages list # above instead. Trusted packages are automatically cooldown-exempt; you do # not need to repeat them here. # # A PURL without a version skips cooldown for ALL versions of the package; a # PURL with a version skips cooldown for that version only. Example: # skip: # - purl: pkg:npm/my-internal-sdk # all versions # reason: "First-party SDK; sanity-tested immediately on release" # - purl: pkg:npm/another-internal-pkg@1.2.3 # only 1.2.3 # reason: "Pin a specific just-published build" skip: [] # Persistent analysis cache (opt-in). Caching is analyzer-specific, so config is # nested per analyzer; today only the Malysis (malware) analyzer has a cache. # # By default PMG re-screens the whole resolved graph against the analysis # backend on every install. When enabled, clean (ALLOW) verdicts are cached on # disk and reused across runs, so repeat installs of an unchanged graph are # fast. Only ALLOW verdicts are cached — suspicious, malicious, and # tenant-excluded verdicts are always re-evaluated. # # Trade-off: a version that was clean when first screened but is later flagged # malicious is served from cache until its entry expires; `ttl` bounds that # window. Keep `ttl` short if you prefer freshness over speed. analysis_cache: # Malysis is SafeDep's threat intelligence feed. # Set cache TTL to be lower than dependency cooldown period to have a compensating # control in place for newly published packages whose verdict is cached. malysis: enabled: false ttl: 24h # 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: "" # Auto sync drains the local cloud-sync WAL to SafeDep Cloud opportunistically # at the end of each PMG invocation, gated by a per-host cooldown so it does # not fire on every command. The drain runs as a short-lived detached child # so the user-facing CLI returns immediately. # # Disable this in ephemeral environments (CI runners, throwaway VMs) where # the detached child may be torn down before it finishes draining; in those # environments, prefer an explicit `pmg cloud sync` at job-end. auto_sync: enabled: true # Minimum gap between sync attempts. The lastrun timestamp is updated on # every attempt (success or failure), so a failing cloud endpoint will not # cause every PMG invocation to retry. Reduce this if you want a more # aggressive retry cadence. min_interval: 15m # Hard timeout applied to a single background sync attempt. timeout: 5m