Initial commit
This commit is contained in:
@@ -0,0 +1,510 @@
|
||||
# Vulnerability Remediation Patterns
|
||||
|
||||
Common patterns for remediating dependency vulnerabilities detected by Grype.
|
||||
|
||||
## Table of Contents
|
||||
- [General Remediation Strategies](#general-remediation-strategies)
|
||||
- [Package Update Patterns](#package-update-patterns)
|
||||
- [Base Image Updates](#base-image-updates)
|
||||
- [Dependency Pinning](#dependency-pinning)
|
||||
- [Compensating Controls](#compensating-controls)
|
||||
- [Language-Specific Patterns](#language-specific-patterns)
|
||||
|
||||
## General Remediation Strategies
|
||||
|
||||
### Strategy 1: Direct Dependency Update
|
||||
|
||||
**When to use**: Vulnerability in a directly declared dependency
|
||||
|
||||
**Pattern**:
|
||||
1. Identify fixed version from Grype output
|
||||
2. Update dependency version in manifest file
|
||||
3. Test application compatibility
|
||||
4. Re-scan to verify fix
|
||||
5. Deploy updated application
|
||||
|
||||
**Example**:
|
||||
```bash
|
||||
# Grype reports: lodash@4.17.15 has CVE-2020-8203, fixed in 4.17.19
|
||||
# Update package.json
|
||||
npm install lodash@4.17.19
|
||||
npm test
|
||||
grype dir:. --only-fixed
|
||||
```
|
||||
|
||||
### Strategy 2: Transitive Dependency Update
|
||||
|
||||
**When to use**: Vulnerability in an indirect dependency
|
||||
|
||||
**Pattern**:
|
||||
1. Identify which direct dependency includes the vulnerable package
|
||||
2. Check if direct dependency has an update that resolves the issue
|
||||
3. Update direct dependency or use dependency override mechanism
|
||||
4. Re-scan to verify fix
|
||||
|
||||
**Example (npm)**:
|
||||
```json
|
||||
// package.json - Override transitive dependency
|
||||
{
|
||||
"overrides": {
|
||||
"lodash": "^4.17.21"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Example (pip)**:
|
||||
```txt
|
||||
# constraints.txt
|
||||
lodash>=4.17.21
|
||||
```
|
||||
|
||||
### Strategy 3: Base Image Update
|
||||
|
||||
**When to use**: Vulnerability in OS packages from container base image
|
||||
|
||||
**Pattern**:
|
||||
1. Identify vulnerable OS package and fixed version
|
||||
2. Update to newer base image tag or rebuild with package updates
|
||||
3. Re-scan updated image
|
||||
4. Test application on new base image
|
||||
|
||||
**Example**:
|
||||
```dockerfile
|
||||
# Before: Alpine 3.14 with vulnerable openssl
|
||||
FROM alpine:3.14
|
||||
|
||||
# After: Alpine 3.19 with fixed openssl
|
||||
FROM alpine:3.19
|
||||
|
||||
# Or: Explicit package update
|
||||
FROM alpine:3.14
|
||||
RUN apk upgrade --no-cache openssl
|
||||
```
|
||||
|
||||
### Strategy 4: Patch or Backport
|
||||
|
||||
**When to use**: No fixed version available or update breaks compatibility
|
||||
|
||||
**Pattern**:
|
||||
1. Research if security patch exists separately from full version update
|
||||
2. Apply patch using package manager's patching mechanism
|
||||
3. Consider backporting fix if feasible
|
||||
4. Document patch and establish review schedule
|
||||
|
||||
**Example (npm postinstall)**:
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"postinstall": "patch-package"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Strategy 5: Compensating Controls
|
||||
|
||||
**When to use**: Fix not available and risk must be accepted
|
||||
|
||||
**Pattern**:
|
||||
1. Document vulnerability and risk acceptance
|
||||
2. Implement network, application, or operational controls
|
||||
3. Enhance monitoring and detection
|
||||
4. Schedule regular review (quarterly)
|
||||
5. Track for future remediation when fix becomes available
|
||||
|
||||
## Package Update Patterns
|
||||
|
||||
### Pattern: Semantic Versioning Updates
|
||||
|
||||
**Minor/Patch Updates** (Generally Safe):
|
||||
```bash
|
||||
# Python: Update to latest patch version
|
||||
pip install --upgrade 'package>=1.2.0,<1.3.0'
|
||||
|
||||
# Node.js: Update to latest minor version
|
||||
npm update package
|
||||
|
||||
# Go: Update to latest patch
|
||||
go get -u=patch github.com/org/package
|
||||
```
|
||||
|
||||
**Major Updates** (Breaking Changes):
|
||||
```bash
|
||||
# Review changelog before updating
|
||||
npm show package versions
|
||||
pip index versions package
|
||||
|
||||
# Update and test thoroughly
|
||||
npm install package@3.0.0
|
||||
npm test
|
||||
```
|
||||
|
||||
### Pattern: Lock File Management
|
||||
|
||||
**Update specific package**:
|
||||
```bash
|
||||
# npm
|
||||
npm install package@latest
|
||||
npm install # Update lock file
|
||||
|
||||
# pip
|
||||
pip install --upgrade package
|
||||
pip freeze > requirements.txt
|
||||
|
||||
# Go
|
||||
go get -u github.com/org/package
|
||||
go mod tidy
|
||||
```
|
||||
|
||||
**Update all dependencies**:
|
||||
```bash
|
||||
# npm (interactive)
|
||||
npm-check-updates --interactive
|
||||
|
||||
# pip
|
||||
pip list --outdated | cut -d ' ' -f1 | xargs -n1 pip install -U
|
||||
|
||||
# Go
|
||||
go get -u ./...
|
||||
go mod tidy
|
||||
```
|
||||
|
||||
## Base Image Updates
|
||||
|
||||
### Pattern: Minimal Base Images
|
||||
|
||||
**Reduce attack surface with minimal images**:
|
||||
|
||||
```dockerfile
|
||||
# ❌ Large attack surface
|
||||
FROM ubuntu:22.04
|
||||
|
||||
# ✅ Minimal attack surface
|
||||
FROM alpine:3.19
|
||||
# or
|
||||
FROM gcr.io/distroless/base-debian12
|
||||
|
||||
# ✅ Minimal for specific language
|
||||
FROM python:3.11-slim
|
||||
FROM node:20-alpine
|
||||
```
|
||||
|
||||
**Benefits**:
|
||||
- Fewer packages = fewer vulnerabilities
|
||||
- Smaller image size
|
||||
- Faster scans
|
||||
|
||||
### Pattern: Multi-Stage Builds
|
||||
|
||||
**Separate build dependencies from runtime**:
|
||||
|
||||
```dockerfile
|
||||
# Build stage with full toolchain
|
||||
FROM node:20 AS builder
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
# Production stage with minimal image
|
||||
FROM node:20-alpine AS production
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/dist ./dist
|
||||
COPY --from=builder /app/node_modules ./node_modules
|
||||
USER node
|
||||
CMD ["node", "dist/index.js"]
|
||||
```
|
||||
|
||||
**Benefits**:
|
||||
- Build tools not present in final image
|
||||
- Reduced vulnerability exposure
|
||||
- Smaller production image
|
||||
|
||||
### Pattern: Regular Base Image Updates
|
||||
|
||||
**Automate base image updates**:
|
||||
|
||||
```yaml
|
||||
# Dependabot config for Dockerfile
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
```
|
||||
|
||||
**Manual update process**:
|
||||
```bash
|
||||
# Check for newer base image versions
|
||||
docker pull alpine:3.19
|
||||
docker images alpine
|
||||
|
||||
# Update Dockerfile
|
||||
sed -i 's/FROM alpine:3.18/FROM alpine:3.19/' Dockerfile
|
||||
|
||||
# Rebuild and scan
|
||||
docker build -t myapp:latest .
|
||||
grype myapp:latest
|
||||
```
|
||||
|
||||
## Dependency Pinning
|
||||
|
||||
### Pattern: Pin to Secure Versions
|
||||
|
||||
**Lock to known-good versions**:
|
||||
|
||||
```dockerfile
|
||||
# ✅ Pin specific versions
|
||||
FROM alpine:3.19.0@sha256:abc123...
|
||||
|
||||
# Install specific package versions
|
||||
RUN apk add --no-cache \
|
||||
ca-certificates=20240226-r0 \
|
||||
openssl=3.1.4-r0
|
||||
```
|
||||
|
||||
```json
|
||||
// package.json - Exact versions
|
||||
{
|
||||
"dependencies": {
|
||||
"express": "4.18.2",
|
||||
"lodash": "4.17.21"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Benefits**:
|
||||
- Reproducible builds
|
||||
- Controlled updates
|
||||
- Prevent automatic vulnerability introduction
|
||||
|
||||
**Drawbacks**:
|
||||
- Manual update effort
|
||||
- May miss security patches
|
||||
- Requires active maintenance
|
||||
|
||||
### Pattern: Range-Based Pinning
|
||||
|
||||
**Allow patch updates, lock major/minor**:
|
||||
|
||||
```json
|
||||
// package.json - Allow patch updates
|
||||
{
|
||||
"dependencies": {
|
||||
"express": "~4.18.2", // Allow 4.18.x
|
||||
"lodash": "^4.17.21" // Allow 4.x.x
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```python
|
||||
# requirements.txt - Compatible releases
|
||||
express>=4.18.2,<5.0.0
|
||||
lodash>=4.17.21,<5.0.0
|
||||
```
|
||||
|
||||
## Compensating Controls
|
||||
|
||||
### Pattern: Network Segmentation
|
||||
|
||||
**Isolate vulnerable systems**:
|
||||
|
||||
```yaml
|
||||
# Docker Compose network isolation
|
||||
services:
|
||||
vulnerable-service:
|
||||
image: myapp:vulnerable
|
||||
networks:
|
||||
- internal
|
||||
# No external port exposure
|
||||
|
||||
gateway:
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
- "80:80"
|
||||
networks:
|
||||
- internal
|
||||
- external
|
||||
|
||||
networks:
|
||||
internal:
|
||||
internal: true
|
||||
external:
|
||||
```
|
||||
|
||||
**Benefits**:
|
||||
- Limits attack surface
|
||||
- Contains potential breaches
|
||||
- Buys time for proper remediation
|
||||
|
||||
### Pattern: Web Application Firewall (WAF)
|
||||
|
||||
**Block exploit attempts at perimeter**:
|
||||
|
||||
```nginx
|
||||
# ModSecurity/OWASP Core Rule Set
|
||||
location / {
|
||||
modsecurity on;
|
||||
modsecurity_rules_file /etc/nginx/modsec/main.conf;
|
||||
proxy_pass http://vulnerable-backend;
|
||||
}
|
||||
```
|
||||
|
||||
**Virtual Patching**:
|
||||
- Create WAF rules for specific CVEs
|
||||
- Block known exploit patterns
|
||||
- Monitor for exploitation attempts
|
||||
|
||||
### Pattern: Runtime Application Self-Protection (RASP)
|
||||
|
||||
**Detect and prevent exploitation at runtime**:
|
||||
|
||||
```python
|
||||
# Example: Add input validation
|
||||
def process_user_input(data):
|
||||
# Validate against known exploit patterns
|
||||
if contains_sql_injection(data):
|
||||
log_security_event("SQL injection attempt blocked")
|
||||
raise SecurityException("Invalid input")
|
||||
|
||||
return sanitize_input(data)
|
||||
```
|
||||
|
||||
## Language-Specific Patterns
|
||||
|
||||
### Python
|
||||
|
||||
**Update vulnerable package**:
|
||||
```bash
|
||||
# Check for vulnerabilities
|
||||
grype dir:/path/to/project -o json
|
||||
|
||||
# Update package
|
||||
pip install --upgrade vulnerable-package
|
||||
|
||||
# Freeze updated dependencies
|
||||
pip freeze > requirements.txt
|
||||
|
||||
# Verify fix
|
||||
grype dir:/path/to/project
|
||||
```
|
||||
|
||||
**Use constraints files**:
|
||||
```bash
|
||||
# constraints.txt
|
||||
vulnerable-package>=1.2.3 # CVE-2024-XXXX fixed
|
||||
|
||||
# Install with constraints
|
||||
pip install -r requirements.txt -c constraints.txt
|
||||
```
|
||||
|
||||
### Node.js
|
||||
|
||||
**Update vulnerable package**:
|
||||
```bash
|
||||
# Check for vulnerabilities
|
||||
npm audit
|
||||
grype dir:. -o json
|
||||
|
||||
# Fix automatically (if possible)
|
||||
npm audit fix
|
||||
|
||||
# Manual update
|
||||
npm install package@version
|
||||
|
||||
# Verify fix
|
||||
npm audit
|
||||
grype dir:.
|
||||
```
|
||||
|
||||
**Override transitive dependencies**:
|
||||
```json
|
||||
{
|
||||
"overrides": {
|
||||
"vulnerable-package": "^2.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Go
|
||||
|
||||
**Update vulnerable module**:
|
||||
```bash
|
||||
# Check for vulnerabilities
|
||||
go list -m all | grype
|
||||
|
||||
# Update specific module
|
||||
go get -u github.com/org/vulnerable-module
|
||||
|
||||
# Update all modules
|
||||
go get -u ./...
|
||||
|
||||
# Verify and tidy
|
||||
go mod tidy
|
||||
grype dir:.
|
||||
```
|
||||
|
||||
### Java/Maven
|
||||
|
||||
**Update vulnerable dependency**:
|
||||
```xml
|
||||
<!-- pom.xml - Update version -->
|
||||
<dependency>
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>vulnerable-lib</artifactId>
|
||||
<version>2.0.0</version> <!-- Updated from 1.0.0 -->
|
||||
</dependency>
|
||||
```
|
||||
|
||||
**Force dependency version**:
|
||||
```xml
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>vulnerable-lib</artifactId>
|
||||
<version>2.0.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
```
|
||||
|
||||
### Rust
|
||||
|
||||
**Update vulnerable crate**:
|
||||
```bash
|
||||
# Check for vulnerabilities
|
||||
cargo audit
|
||||
grype dir:. -o json
|
||||
|
||||
# Update specific crate
|
||||
cargo update -p vulnerable-crate
|
||||
|
||||
# Update all crates
|
||||
cargo update
|
||||
|
||||
# Verify fix
|
||||
cargo audit
|
||||
grype dir:.
|
||||
```
|
||||
|
||||
## Verification Workflow
|
||||
|
||||
After applying any remediation:
|
||||
|
||||
Progress:
|
||||
[ ] 1. **Re-scan**: Run Grype scan to verify vulnerability resolved
|
||||
[ ] 2. **Test**: Execute test suite to ensure no functionality broken
|
||||
[ ] 3. **Document**: Record CVE, fix applied, and verification results
|
||||
[ ] 4. **Deploy**: Roll out fix to affected environments
|
||||
[ ] 5. **Monitor**: Watch for related security issues or regressions
|
||||
|
||||
Work through each step systematically. Check off completed items.
|
||||
|
||||
## References
|
||||
|
||||
- [npm Security Best Practices](https://docs.npmjs.com/security-best-practices)
|
||||
- [Python Packaging Security](https://packaging.python.org/en/latest/guides/security/)
|
||||
- [Go Modules Security](https://go.dev/blog/vuln)
|
||||
- [OWASP Dependency Check](https://owasp.org/www-project-dependency-check/)
|
||||
Reference in New Issue
Block a user