dependency-vulnerability-triage

安装量: 35
排名: #19710

安装

npx skills add https://github.com/patricio0312rev/skills --skill dependency-vulnerability-triage
Dependency Vulnerability Triage
Convert vulnerability reports into actionable patch plans.
Vulnerability Severity Matrix
// severity-matrix.ts
export
interface
Vulnerability
{
id
:
string
;
package
:
string
;
currentVersion
:
string
;
patchedVersion
:
string
;
severity
:
"critical"
|
"high"
|
"medium"
|
"low"
;
cvss
:
number
;
cwe
:
string
[
]
;
exploitability
:
"high"
|
"medium"
|
"low"
;
impact
:
string
;
path
:
string
[
]
;
}
export
interface
PatchPriority
{
vulnerability
:
Vulnerability
;
priority
:
1
|
2
|
3
|
4
;
reasoning
:
string
;
patchWindow
:
"24h"
|
"1week"
|
"1month"
|
"next-release"
;
breakingChange
:
boolean
;
testingRequired
:
"minimal"
|
"moderate"
|
"extensive"
;
}
export
function
calculatePriority
(
vuln
:
Vulnerability
)
:
PatchPriority
{
let
priority
:
1
|
2
|
3
|
4
=
4
;
let
patchWindow
:
"24h"
|
"1week"
|
"1month"
|
"next-release"
=
"next-release"
;
let
testingRequired
:
"minimal"
|
"moderate"
|
"extensive"
=
"minimal"
;
// P1: Critical + High Exploitability + Production
if
(
vuln
.
severity
===
"critical"
&&
vuln
.
exploitability
===
"high"
&&
isProductionDependency
(
vuln
.
package
)
)
{
priority
=
1
;
patchWindow
=
"24h"
;
testingRequired
=
"moderate"
;
}
// P2: High + Medium/High Exploitability
else
if
(
vuln
.
severity
===
"high"
&&
[
"high"
,
"medium"
]
.
includes
(
vuln
.
exploitability
)
)
{
priority
=
2
;
patchWindow
=
"1week"
;
testingRequired
=
"moderate"
;
}
// P3: Medium or Low Exploitability High
else
if
(
vuln
.
severity
===
"medium"
||
(
vuln
.
severity
===
"high"
&&
vuln
.
exploitability
===
"low"
)
)
{
priority
=
3
;
patchWindow
=
"1month"
;
testingRequired
=
"minimal"
;
}
return
{
vulnerability
:
vuln
,
priority
,
reasoning
:
`
${
vuln
.
severity
}
severity,
${
vuln
.
exploitability
}
exploitability
`
,
patchWindow
,
breakingChange
:
isBreakingChange
(
vuln
.
currentVersion
,
vuln
.
patchedVersion
)
,
testingRequired
,
}
;
}
Audit Report Parser
// scripts/parse-audit.ts
import
{
execSync
}
from
"child_process"
;
interface
NpmAuditResult
{
vulnerabilities
:
Record
<
string
,
any
>
;
metadata
:
{
vulnerabilities
:
{
critical
:
number
;
high
:
number
;
moderate
:
number
;
low
:
number
;
}
;
}
;
}
function
parseNpmAudit
(
)
:
Vulnerability
[
]
{
const
auditOutput
=
execSync
(
"npm audit --json"
,
{
encoding
:
"utf-8"
}
)
;
const
audit
:
NpmAuditResult
=
JSON
.
parse
(
auditOutput
)
;
const
vulnerabilities
:
Vulnerability
[
]
=
[
]
;
Object
.
entries
(
audit
.
vulnerabilities
)
.
forEach
(
(
[
pkg
,
data
]
)
=>
{
vulnerabilities
.
push
(
{
id
:
data
.
via
[
0
]
?.
url
||
`
vuln-
${
pkg
}
`
,
package
:
pkg
,
currentVersion
:
data
.
range
,
patchedVersion
:
data
.
fixAvailable
?.
version
||
"N/A"
,
severity
:
data
.
severity
,
cvss
:
data
.
via
[
0
]
?.
cvss
?.
score
||
0
,
cwe
:
data
.
via
[
0
]
?.
cwe
||
[
]
,
exploitability
:
determineExploitability
(
data
)
,
impact
:
data
.
via
[
0
]
?.
title
||
"Unknown"
,
path
:
data
.
via
.
map
(
(
v
:
any
)
=>
v
.
name
)
,
}
)
;
}
)
;
return
vulnerabilities
;
}
function
determineExploitability
(
data
:
any
)
:
"high"
|
"medium"
|
"low"
{
// Check if actively exploited
if
(
data
.
via
[
0
]
?.
findings
?.
some
(
(
f
:
any
)
=>
f
.
exploit
===
"proof-of-concept"
)
)
{
return
"high"
;
}
// Check CVSS exploitability subscore
const
exploitScore
=
data
.
via
[
0
]
?.
cvss
?.
exploitabilityScore
;
if
(
exploitScore
>
3.5
)
return
"high"
;
if
(
exploitScore
>
2.0
)
return
"medium"
;
return
"low"
;
}
Patch Plan Generator
// scripts/generate-patch-plan.ts
interface
PatchPlan
{
immediate
:
PatchPriority
[
]
;
// P1 - 24h
shortTerm
:
PatchPriority
[
]
;
// P2 - 1 week
mediumTerm
:
PatchPriority
[
]
;
// P3 - 1 month
longTerm
:
PatchPriority
[
]
;
// P4 - next release
breakingChanges
:
PatchPriority
[
]
;
safeUpgrades
:
PatchPriority
[
]
;
}
function
generatePatchPlan
(
vulnerabilities
:
Vulnerability
[
]
)
:
PatchPlan
{
const
prioritized
=
vulnerabilities
.
map
(
calculatePriority
)
;
return
{
immediate
:
prioritized
.
filter
(
(
p
)
=>
p
.
priority
===
1
)
,
shortTerm
:
prioritized
.
filter
(
(
p
)
=>
p
.
priority
===
2
)
,
mediumTerm
:
prioritized
.
filter
(
(
p
)
=>
p
.
priority
===
3
)
,
longTerm
:
prioritized
.
filter
(
(
p
)
=>
p
.
priority
===
4
)
,
breakingChanges
:
prioritized
.
filter
(
(
p
)
=>
p
.
breakingChange
)
,
safeUpgrades
:
prioritized
.
filter
(
(
p
)
=>
!
p
.
breakingChange
)
,
}
;
}
function
printPatchPlan
(
plan
:
PatchPlan
)
{
console
.
log
(
"# Security Patch Plan\n"
)
;
console
.
log
(
"## 🚨 Immediate (24 hours)\n"
)
;
plan
.
immediate
.
forEach
(
(
p
)
=>
{
console
.
log
(
`
- **
${
p
.
vulnerability
.
package
}
**
${
p
.
vulnerability
.
currentVersion
}
${
p
.
vulnerability
.
patchedVersion
}
`
)
;
console
.
log
(
`
${
p
.
vulnerability
.
impact
}
`
)
;
console
.
log
(
`
Breaking:
${
p
.
breakingChange
?
"YES ⚠️"
:
"No"
}
`
)
;
}
)
;
console
.
log
(
"\n## ⚡ Short-term (1 week)\n"
)
;
plan
.
shortTerm
.
forEach
(
(
p
)
=>
{
console
.
log
(
`
- **
${
p
.
vulnerability
.
package
}
**
${
p
.
vulnerability
.
currentVersion
}
${
p
.
vulnerability
.
patchedVersion
}
`
)
;
}
)
;
console
.
log
(
"\n## 📅 Medium-term (1 month)\n"
)
;
plan
.
mediumTerm
.
forEach
(
(
p
)
=>
{
console
.
log
(
`
-
${
p
.
vulnerability
.
package
}
${
p
.
vulnerability
.
currentVersion
}
${
p
.
vulnerability
.
patchedVersion
}
`
)
;
}
)
;
console
.
log
(
"\n## ⚠️ Breaking Changes\n"
)
;
plan
.
breakingChanges
.
forEach
(
(
p
)
=>
{
console
.
log
(
`
-
${
p
.
vulnerability
.
package
}
Review migration guide ` ) ; } ) ; } Safe Upgrade Order // Dependency graph-based upgrade order interface DependencyGraph { [ pkg : string ] : string [ ] ; } function determineSafeUpgradeOrder ( patches : PatchPriority [ ] ) : PatchPriority [ ] [ ] { const graph = buildDependencyGraph ( ) ; const ordered : PatchPriority [ ] [ ] = [ ] ; // Level 0: No dependencies on other patches const level0 = patches . filter ( ( p ) => ! hasUpgradeDependencies ( p . vulnerability . package , patches , graph ) ) ; ordered . push ( level0 ) ; // Level 1+: Depends on previous levels let remaining = patches . filter ( ( p ) => ! level0 . includes ( p ) ) ; let level = 1 ; while ( remaining . length

0 && level < 10 ) { const currentLevel = remaining . filter ( ( p ) => canUpgradeNow ( p . vulnerability . package , ordered . flat ( ) , graph ) ) ; if ( currentLevel . length === 0 ) break ; // Circular dependency ordered . push ( currentLevel ) ; remaining = remaining . filter ( ( p ) => ! currentLevel . includes ( p ) ) ; level ++ ; } return ordered ; } // Example output: // Level 0: [lodash, axios] - No dependencies // Level 1: [express] - Depends on lodash // Level 2: [next] - Depends on express Risk Assessment interface RiskAssessment { package : string ; riskFactors : string [ ] ; riskScore : number ; // 1-10 mitigations : string [ ] ; } function assessUpgradeRisk ( patch : PatchPriority ) : RiskAssessment { const risks : string [ ] = [ ] ; let score = 0 ; // Check for breaking changes if ( patch . breakingChange ) { risks . push ( "Breaking changes detected" ) ; score += 4 ; } // Check for major version bump if ( isMajorVersionBump ( patch . vulnerability . currentVersion , patch . vulnerability . patchedVersion ) ) { risks . push ( "Major version upgrade" ) ; score += 3 ; } // Check usage patterns const usage = analyzePackageUsage ( patch . vulnerability . package ) ; if ( usage . importCount

50 ) { risks . push ( "Heavily used in codebase" ) ; score += 2 ; } // Check test coverage if ( usage . testCoverage < 0.7 ) { risks . push ( "Low test coverage" ) ; score += 2 ; } return { package : patch . vulnerability . package , riskFactors : risks , riskScore : Math . min ( score , 10 ) , mitigations : generateMitigations ( risks ) , } ; } function generateMitigations ( risks : string [ ] ) : string [ ] { const mitigations : string [ ] = [ ] ; if ( risks . includes ( "Breaking changes detected" ) ) { mitigations . push ( "Read CHANGELOG and migration guide" ) ; mitigations . push ( "Test on feature branch first" ) ; mitigations . push ( "Deploy to staging before production" ) ; } if ( risks . includes ( "Heavily used in codebase" ) ) { mitigations . push ( "Run full test suite" ) ; mitigations . push ( "Perform manual smoke tests" ) ; mitigations . push ( "Monitor error rates after deploy" ) ; } if ( risks . includes ( "Low test coverage" ) ) { mitigations . push ( "Add tests for critical paths" ) ; mitigations . push ( "Extend monitoring" ) ; } return mitigations ; } Automated Patch Script

!/bin/bash

scripts/apply-patches.sh

set -e PRIORITY = $1

immediate, short-term, medium-term

if [ -z " $PRIORITY " ] ; then echo "Usage: ./apply-patches.sh [immediate|short-term|medium-term]" exit 1 fi echo "🔧 Applying $PRIORITY patches..."

Generate patch plan

npm audit --json

audit-report.json node scripts/generate-patch-plan.js --priority = $PRIORITY

patch-plan.json

Apply patches

while IFS = read -r package ; do echo "Updating $package ..."

Try to apply fix

npm audit fix --package-lock-only --package = $package

Run tests

if npm test ; then echo "✅ Tests passed for $package " git add package.json package-lock.json git commit -m "security: patch $package vulnerability" else echo "❌ Tests failed for $package - reverting" git checkout package.json package-lock.json fi done < < ( jq -r '.packages[]' patch-plan.json ) echo "✅ Patches applied" CI Vulnerability Gating

.github/workflows/security-audit.yml

name : Security Audit on : pull_request : schedule : - cron : "0 0 * * *"

Daily

jobs : audit : runs-on : ubuntu - latest steps : - uses : actions/checkout@v4 - uses : actions/setup - node@v4 with : node-version : "20" - name : Install dependencies run : npm ci - name : Run npm audit run : npm audit - - audit - level=moderate continue-on-error : true - name : Run Snyk test uses : snyk/actions/node@master env : SNYK_TOKEN : $ { { secrets.SNYK_TOKEN } } with : args : - - severity - threshold=high - name : Generate patch plan if : failure() run : npm run generate - patch - plan - name : Comment PR if : failure() && github.event_name == 'pull_request' uses : actions/github - script@v7 with : script : | const fs = require('fs'); const plan = fs.readFileSync('patch-plan.md', 'utf8'); github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, body: plan }); Patch Rollback Strategy

Vulnerability Patch Rollback Plan

Before Patching 1. ** Create rollback tag **

git tag -a pre-security-patch-$(date +%Y%m%d) -m "Pre-patch checkpoint"

Document current versions npm list --depth = 0

versions-before.txt Run baseline tests npm test

test-results-before.txt Rollback Steps If issues detected after patching: Immediate revert git revert HEAD git push origin main Redeploy previous version git checkout pre-security-patch- $( date +%Y%m%d ) npm ci npm run build npm run deploy Verify rollback npm test npm run smoke-tests Incident report Document what failed Update patch plan with new risk factors Schedule retry with additional testing

Best Practices

  1. Triage weekly: Review new vulnerabilities
  2. Prioritize by impact: Not just severity score
  3. Test before merging: Automated + manual testing
  4. Stage deployments: Dev → Staging → Production
  5. Monitor after patch: Watch error rates
  6. Document breaking changes: Migration guides
  7. Keep dependencies updated: Reduce vulnerability surface

Output Checklist

  • [ ] Severity matrix defined
  • [ ] Audit parser implemented
  • [ ] Patch plan generated
  • [ ] Safe upgrade order determined
  • [ ] Risk assessment completed
  • [ ] Breaking changes identified
  • [ ] Automated patch script
  • [ ] CI vulnerability gating
  • [ ] Rollback strategy documented
  • [ ] Team notified of critical patches
返回排行榜