fix-security-vulnerability
Analyze and propose fixes for Dependabot security alerts
npx skills add https://github.com/getsentry/sentry-changelog --skill fix-security-vulnerabilityFix Security Vulnerability Skill
Analyze Dependabot security alerts and propose fixes for the sentry-changelog Next.js app. Does NOT auto-commit - always presents analysis first and waits for user approval.
Input
- Dependabot URL:
https://github.com/getsentry/sentry-changelog/security/dependabot/12 - Or just the alert number:
12
Workflow
Step 1: Fetch Vulnerability Details
gh api repos/getsentry/sentry-changelog/dependabot/alerts/<alert-number>
Extract: package name, vulnerable/patched versions, CVE ID, severity, description.
Step 2: Analyze Dependency Tree
pnpm why <package-name>
Determine if it's a direct or transitive dependency, and whether it's production or dev.
Step 3: Determine Fix Strategy
Check for pinned dependencies
Some dependencies are intentionally pinned due to compatibility constraints. Check package.json comments (the "//" field) for pin reasons before bumping.
Known pins:
google-auth-library- Pinned to v9.x to match@google-cloud/storage's bundled version (v10.x breaks Vercel OIDC auth)
For other dependencies
| Type | Action |
|---|---|
| Patch bump available | Preferred - lowest risk |
| Minor bump needed | Usually safe |
| Major bump needed | Analyze breaking changes first |
| Transitive dependency | Bump the parent package (see below) |
Step 3a: Transitive Dependencies
If the vulnerable package is pulled in by another package:
1. Identify and check the parent:
pnpm why <vulnerable-package>
npm view <parent-package>@latest dependencies.<vulnerable-package>
2. Fix approach:
| Scenario | Action |
|---|---|
| Parent has newer version with fix | Bump the parent |
| Parent hasn't released fix | Wait, or open an issue upstream |
AVOID pnpm.overrides. Forcing a transitive dependency version can break the parent package silently. Only consider overrides if:
- No upstream fix exists AND it's a production-critical vulnerability
- The forced version is a patch/minor bump (not major)
- You've manually verified compatibility
Step 4: Present Analysis
Present findings and wait for user approval before making changes:
## Security Vulnerability Analysis
**Package:** <name> | **Severity:** <severity> | **CVE:** <id>
**Vulnerable:** <range> | **Patched:** <version>
### Dependency Chain
<pnpm why output>
### Recommendation
<One of: Safe to bump / Intentionally pinned - do not bump / Bump parent package>
### Proposed Fix
1. Update package.json: "<package>": "<new-version>"
2. pnpm install
3. Verify with: pnpm why <package>
Proceed?
Step 5: Apply Fix (After Approval)
# 1. Edit package.json
# 2. Update lockfile
pnpm install
# 3. Verify
pnpm why <package>
# 4. Run tests
pnpm test:run
# 5. Show changes
git diff
Do NOT commit - let the user review first.
Step 5 (Alternative): Dismiss Alert
For alerts that should not be fixed, offer to dismiss instead.
Always get user approval first. Present the dismissal option:
This alert should be dismissed rather than fixed because:
- <reason: intentionally pinned / dev-only acceptable risk / etc.>
Dismiss with reason: <suggested reason>
Comment: "<suggested comment>"
Proceed with dismissal?
After user approval, dismiss via GitHub API:
gh api --method PATCH repos/getsentry/sentry-changelog/dependabot/alerts/<number> \
-f state=dismissed \
-f dismissed_reason=<reason> \
-f dismissed_comment="<comment>"
Dismissal reasons:
| Reason | When to use |
|---|---|
tolerable_risk | Dev-only dependency, risk accepted |
no_bandwidth | Will fix later, not urgent |
inaccurate | False positive, not actually vulnerable |
not_used | Vulnerable code path is not used in our code |
Commands Reference
| Command | Purpose |
|---|---|
pnpm why <pkg> | Show dependency tree |
gh api repos/getsentry/sentry-changelog/dependabot/alerts/<n> | Fetch alert |
gh api --method PATCH .../dependabot/alerts/<n> -f state=dismissed -f dismissed_reason=<reason> | Dismiss alert |
npm view <pkg>@latest dependencies.<dep> | Check transitive dep version |
pnpm test:run | Run tests |
Examples
Direct dependency - safe to bump
Package: contentful
Severity: moderate
Type: Production dependency (direct)
Recommendation: Safe to bump 10.15.0 → 10.16.0
- Patch version, low risk
- No breaking changes expected
Pinned dependency - dismiss instead
Package: google-auth-library
Severity: high
Recommendation: DISMISS (do not bump to v10.x)
This package is intentionally pinned to v9.x for compatibility
with @google-cloud/storage's bundled ExternalAccountClient.
Bumping to v10.x breaks Vercel OIDC authentication.
Proposed dismissal:
Reason: tolerable_risk
Comment: "Pinned to v9.x for @google-cloud/storage compat - see package.json comments"
Proceed with dismissal?
Transitive dependency - bump parent
Package: vulnerable-lib@1.9.0 (needs >=2.0.1)
Chain: @sentry/nextjs → @sentry/node → vulnerable-lib
Check: npm view @sentry/nextjs@latest dependencies
Result: Uses patched version ✓
Recommendation: Bump @sentry/nextjs 10.32.1 → 10.33.0
This pulls in the patched vulnerable-lib automatically.
Transitive dependency - no fix available
Package: deep-lib@2.9.0 (needs >=3.0.0)
Chain: next → some-pkg → deep-lib
No upstream fix available yet. Options:
1. Wait for upstream fix (preferred)
2. Accept risk if dev-only
3. Consider pnpm.overrides as last resort for production-critical issues
AVOID using overrides unless absolutely necessary.
Important Notes
- Never auto-commit - Always wait for user review
- Check pin reasons - Some deps are pinned for compatibility (see
"//"in package.json) - Dev vs Prod matters - Dev-only vulnerabilities are lower priority
- Bump parents, not transitive deps - If A depends on vulnerable B, bump A
- Avoid
pnpm.overrides- They bypass the parent's dependency constraints and can cause subtle breakage - Always verify - Run
pnpm why <pkg>after fixing to confirm the patched version is installed - Run tests - Run
pnpm test:runafter fixing to make sure nothing broke