* feat: Add dependency cooldown for npm packages
Strip recently-published package versions from npm registry metadata
responses so npm's resolver naturally falls back to older versions.
Overrides the Accept header to force full packument responses (which
include the "time" field needed for publish-date checks).
Reports cooldown blocks only when all versions are stripped (remaining == 0),
matching npm's --min-release-age behavior for silent fallback.
* fix: Report oldest version in cooldown block (shortest wait)
When all versions are blocked by cooldown, report the oldest version
since it exits the cooldown window first — giving the user the
shortest wait time instead of the longest.
* fix: Handle resp.Body.Close error return for errcheck linter
* test: Add dependency cooldown assertions to template config tests
* fix: config template for dependency cooldown
* fix: Prevent npm from caching cooldown-stripped metadata responses
* fix: Restore body on ReadAll failure and log Close errors in response modifier
* fix: Close response body before replacing to prevent connection leak
* fix: Correct daysLeft ceiling math and update ContentLength on error recovery
* fix: Clear Status on status code change and update ContentLength in modifier error path
* refactor: address review comments on dependency cooldown PR
- Make NpmCooldownHandler and constructor package-private
- Pass cooldown days as parameter instead of reading config internally
- Convert standalone functions to methods on npmCooldownHandler
- Set Accept-Encoding: identity to prevent gzip responses breaking JSON parsing
- Return 503 with descriptive message when upstream body read fails
* fix: log errors in stripCooldownVersions instead of swallowing them
* fix: Config preserve fallback defaults
* fix: Code review fixes
* fix: correct cooldown tip to show wait time instead of incorrect trusted_packages advice
* fix: prevent integer overflow in cooldown duration calculation with large days values
* refactor: deduplicate CooldownBlock into internal/models, fix misleading variable names
- Move CooldownBlock struct to internal/models to eliminate duplication
between proxy/interceptors and internal/ui packages
- Simplify proxy_flow.go by using direct assignment instead of field copy
- Rename latestStripped/latestDate to oldestVer/oldestDate for clarity
* fix: Dependency Cooldown Check Encapsulation (#207)
* fix: Encapsulate cooldown check
* feat: Add --skip-dependency-cooldown override
* fix: Code review fixes
---------
Co-authored-by: Abhisek Datta <abhisek.datta@gmail.com>
When users have HTTP_PROXY/HTTPS_PROXY set in their shell (e.g. corporate
proxy), PMG's upstream transport routes all traffic through that external
proxy — including requests to localhost/127.0.0.1. The external proxy
cannot reach the user's loopback, causing EFAULT/ConnectionRefused errors.
This adds loopback bypass in two places:
- Proxy upstream transport skips external proxy for localhost/127.0.0.1/::1
- Child process env gets NO_PROXY so proxy-aware libs (axios) skip PMG's
proxy for loopback addresses
Fixes#193
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* update README.md
* ci: Remove paths-ignore filters from all workflows
Removes docs/ and *.md path exclusions so required checks always run,
preventing PRs from being blocked when only documentation files change.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* docs: Add config merging design spec for #114
Defines the merge-during-setup-install approach for keeping user
configs up to date with new template keys while preserving all
existing values, comments, and formatting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: Add implementation plan for config merging
TDD-based plan with 6 tasks: dependency setup, failing tests,
core merge implementation, integration test, WriteTemplateConfig
integration, and full verification.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: Merge template config into existing user config during setup install
Instead of skipping when a config file exists, WriteTemplateConfig() now
merges missing keys from the embedded template into the user's config
using YAML AST manipulation. Preserves all user values, comments, and
formatting. Only adds keys present in the template but absent in the
user's config.
Closes#114
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: Graceful error handling for config loading and setup commands
Replace panics in loadViperConfig with error returns so the app falls
back to defaults instead of crashing on malformed config files. Add
SilenceUsage to setup install/remove commands so runtime errors don't
dump the full usage text.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* add test cmd in readme
* update copy text
* refactor: Address review feedback on config merging
- Rename existing/template to dest/source for generic util naming
- Remove unnecessary code comments (Rule N references, obvious comments)
- Add AGENTS.md with dev guide and code style rules, symlink CLAUDE.md
- Add BenchmarkMergeYAML (~46μs/op on M4 Pro)
- Remove stale design spec
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* update `MergeYAML` to use from dry/utils
* update AGENTS.md
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The npm postinstall script used `unzip` to extract .zip archives, but
`unzip` is not available by default on Windows, causing installation to
fail with a `spawn UNKNOWN` error. Use PowerShell's `Expand-Archive`
on Windows instead, which is available since PowerShell 5.0 (Windows 10+).
Fixes#187
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The spinner goroutine was writing carriage-return + status text to
os.Stdout every 100ms. In the non-interactive TTY path, the child
process also writes directly to os.Stdout, causing both writers to
race on the same file descriptor. The \r emitted by the spinner
resets the cursor to column 0 mid-line, corrupting and truncating
the child process output.
Fix by writing all spinner/status output to os.Stderr, which is the
standard Unix convention for diagnostic and status messages. This is
also consistent with how progress.go and ShowWarning already behave.
https://claude.ai/code/session_012jMiRSS4Jx9Bs7a2F4S6KN
Co-authored-by: Claude <noreply@anthropic.com>
* add support to merge system CA with PMG CA
* Keep CA cert immutable; merge system bundle only when writing proxy CA file
* Update proxy/certmanager/generator.go
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Signed-off-by: Sahil Bansal <bansalsahil315@gmail.com>
* Update internal/flows/proxy_flow.go
Co-authored-by: Abhisek Datta <abhisek.datta@gmail.com>
Signed-off-by: Sahil Bansal <bansalsahil315@gmail.com>
* update config field name
* Use integer-only guard when sizing merged CA bundle
* Use int64-only guard when sizing merged CA bundle
* add tests for firstReadablePath
* Update proxy/certmanager/generator.go
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Signed-off-by: Sahil Bansal <bansalsahil315@gmail.com>
* fix linter
* refactor system CA merge API
* add max limit to 2MB for certificates
* update max limit to 2MB for certificate merging
* remove python specific env var for CAs
---------
Signed-off-by: Sahil Bansal <bansalsahil315@gmail.com>
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Abhisek Datta <abhisek.datta@gmail.com>
* provide package blocked feedback in proxy mode
* update test case & clear status on block
* refactor reporting
* clearStatus on `continueExecution`
* set spinnerChan to nil
* add sync for spinner
* fix proxy mode failing for GH private packages
* skip analysis for private packages for proxy mode
* introduce npmRegistryConfig and support for handling multiple parsers in future
* refactor name and unexport npm config functions
* rm unused function
* rename & unexport npmRegistryURLParser
* add e2e for malicious pkg blocked using proxy mode
* introduce enforce_always sandbox config & hooks for flows
* fix sandbox failing for unsupported commands
* add hooks for pypi package managers
* add tests for sandbox hook
* introduce enforce_always flag for ease use & CI
* make comments descriptive
* remove hooks & update config to add API to configure sandbox
* add comments
* rm unused function
* feat: Add support for bubblewrap sandbox
* fix: Glob pattern expansion limit for linux
* fix: Bug in glob pattern expansion for bwrap
* fix: README on trust
* fix: Multiple bubblewrap translator fix
* test: Add E2E for linux sandbox
* fix: Refactor bwrap sandbox to use common dangerous files
* fix: Path test case
* fix: Non-existent path handling bug
* refactor: Misc cleanup
* fix: Avoid bind mount for non-existentent deny protection
* fix: Off by one bug in path depth handling
* ci: Disable AppArmor on GHA runner
* fix: Disable apparmor userns restrictions