Dies ist Teil 2 einer zweiteiligen Serie zum Schutz von Astro-Websites vor npm-Supply-Chain-Angriffen. Teil 1 behandelte das Verständnis der Bedrohung und unmittelbare Reaktionsmaßnahmen. Dieser Artikel konzentriert sich auf langfristige Sicherheitsmaßnahmen, Monitoring und Best Practices.
SponsoredHochwertige Starter-Kits mit integriertem Authentifizierungsfluss (Auth.js), Objekt-Uploads (AWS, Clouflare R2, Firebase Storage, Supabase Storage), integrierten Zahlungen (Stripe, LemonSqueezy), E-Mail-Verifizierungsablauf (Resend, Postmark, Sendgrid) und viel mehr . Kompatibel mit jeder Datenbank (Redis, Postgres, MongoDB, SQLite, Firestore).
Get all 3 kits Bundle ↗
Next.js Starter Kit SvelteKit Starter Kit Astro Starter KitOne-time license · Lifetime updates
In Teil 1 haben wir die unmittelbare Reaktion auf den Shai-Hulud-2.0-Angriff behandelt. Jetzt ist es an der Zeit, umfassende Sicherheitsmaßnahmen zu implementieren, die Ihr Astro-Projekt vor zukünftigen Supply-Chain-Angriffen schützen. Das sind keine temporären Fixes – es sind wesentliche Praktiken, die Teil Ihres Entwicklungs-Workflows werden sollten.
Voraussetzungen
Sie benötigen Folgendes:
- Abgeschlossenen Teil 1 dieser Serie
1. Package Lock und Verifizierung implementieren
Die erste Verteidigungslinie gegen Supply-Chain-Angriffe besteht darin, sicherzustellen, dass Sie stets genau die Versionen der Pakete installieren, die Sie getestet und verifiziert haben.
1.1 Exakte Versionsnummern verwenden
Verwenden Sie niemals Versionsbereiche in Ihrer package.json für Produktions-Dependencies:
// ❌ Schlecht: Erlaubt automatische Updates{ "dependencies": { "astro": "^4.16.1", // Kann 4.16.x oder 4.x.x installieren "sharp": "~0.33.1" // Kann 0.33.x installieren }}
// ✅ Gut: Nur exakte Versionen{ "dependencies": { "astro": "4.16.1", "sharp": "0.33.1" }}1.2 npm/pnpm für Sicherheit konfigurieren
Erstellen Sie eine .npmrc-Datei im Projektroot mit strengen Sicherheitseinstellungen:
# Always use exact versions when saving packagessave-exact=true
# Ensure package-lock.json is always created and usedpackage-lock=true
# Run audit on every installaudit=true
# Set minimum audit level (low, moderate, high, critical)audit-level=moderate
# Fail install if vulnerabilities are foundaudit-report=trueFür pnpm-Nutzer (empfohlen) konfigurieren Sie zusätzliche Sicherheitsfunktionen:
# File: .npmrc (for pnpm)
# Require exact versionssave-exact=true
# Strict peer dependenciesstrict-peer-dependencies=true
# Verify package integrity using checksumspackage-import-method=copy
# Run security audit on installaudit=true
# Only allow packages from verified registriesregistry=https://registry.npmjs.org/
# Verify SSL certificatesstrict-ssl=true1.3 Lock-Dateien immer committen
Ihre Lock-Datei (package-lock.json oder pnpm-lock.yaml) ist entscheidend für reproduzierbare Builds:
# Ensure lock file is tracked in gitgit add pnpm-lock.yamlgit commit -m "chore: commit lock file for security"Aktualisieren Sie Ihre .gitignore, damit Lock-Dateien niemals ignoriert werden:
# Make sure these are NOT in .gitignore:# pnpm-lock.yaml# package-lock.json# yarn.lock
# But DO ignorenode_modules/2. Dependency-Scanning-Tools verwenden
Automatisierte Scanning-Tools können Schwachstellen erkennen, bevor sie in die Produktion gelangen. Richten wir einen umfassenden Scanning-Workflow ein.
2.1 Snyk-Sicherheitsscan mit GitHub Actions
Snyk ist eine führende Developer-Security-Plattform, die sich auf das Scannen Ihrer Dependencies auf Schwachstellen spezialisiert.
Erstellen Sie einen GitHub-Actions-Workflow für Snyk-Scans:
name: Snyk Security Scan
on: push: branches: [main, develop] pull_request: branches: [main, develop] schedule: - cron: '0 2 * * *' workflow_dispatch:
jobs: snyk-scan: runs-on: ubuntu-latest
permissions: contents: read
steps: - name: Checkout code uses: actions/checkout@v4
- name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'pnpm'
- name: Install pnpm uses: pnpm/action-setup@v2 with: version: 8
- name: Install dependencies (safely) run: pnpm install --frozen-lockfile --ignore-scripts
- name: Run npm audit run: pnpm audit --audit-level=moderate continue-on-error: true id: npm-audit
- name: Run Snyk security scan uses: snyk/actions/node@master env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} with: args: --severity-threshold=high --all-projects continue-on-error: true id: snyk-scan
- name: Generate Security Report if: always() run: | echo "# Snyk Security Scan Report" > security-report.md echo "Generated: $(date)" >> security-report.md echo "" >> security-report.md echo "## Scan Results" >> security-report.md echo "- npm audit: ${{ steps.npm-audit.outcome }}" >> security-report.md echo "- Snyk scan: ${{ steps.snyk-scan.outcome }}" >> security-report.md
- name: Upload Security Report uses: actions/upload-artifact@v4 if: always() with: name: snyk-security-report-${{ github.run_number }} path: security-report.md retention-days: 90Snyk bietet kontinuierliches Monitoring Ihrer Dependencies und verfolgt neue Schwachstellen auch nach dem Merge Ihres Codes. Es liefert Fix-Vorschläge, die genau identifizieren, welche Updates bekannte Probleme beheben. Mit starker IDE- und CI/CD-Integration hilft Snyk Ihnen, Sicherheitsprobleme zu erkennen, bevor Ihre Dependencies die Produktion erreichen. Zudem bietet Snyk eine großzügige kostenlose Stufe für öffentliche und Open-Source-Repositories – damit ist es für die breitere Entwickler-Community zugänglich.
2.2 Trivy-Vulnerability-Scanner mit GitHub Actions
Trivy ist ein Open-Source-Vulnerability-Scanner, der breiteres Scanning bietet – einschließlich Infrastruktur- und Container-Sicherheit.
Richten Sie Trivy mit GitHub Actions ein:
name: Trivy Scan
on: push: branches: [main, develop] pull_request: branches: [main, develop] schedule: - cron: '0 4 * * *' workflow_dispatch:
jobs: trivy-scan: runs-on: ubuntu-latest
permissions: contents: read security-events: write
steps: - name: Checkout code uses: actions/checkout@v4
- name: Install pnpm uses: pnpm/action-setup@v2 with: version: 8
- name: Install dependencies (safely) run: pnpm install --frozen-lockfile --ignore-scripts
- name: Trivy vulnerability scan (code & dependencies) uses: aquasecurity/trivy-action@master with: scan-type: 'fs' scan-ref: '.' format: 'sarif' output: 'trivy-results.sarif' severity: 'HIGH,CRITICAL'
- name: Upload Trivy results to GitHub Security uses: github/codeql-action/upload-sarif@v3 if: always() with: sarif_file: 'trivy-results.sarif'Trivy ist ein Open-Source-Sicherheitsscanner mit breiter Abdeckung von Schwachstellen in Ihrem gesamten Projekt – nicht nur in node_modules, sondern auch in Containern, Betriebssystem-Paketen, Konfigurationsdateien und Infrastructure-as-Code. Die Ergebnisse können im SARIF-Format ausgegeben werden, was eine nahtlose Integration mit GitHub-Security-Features ermöglicht. Trivy ist kostenlos, einfach zu automatisieren und gut geeignet für lokale wie CI/CD-Workflows.
2.3 Lokales Security-Scanning einrichten
Warten Sie nicht, bis CI/CD Probleme findet. Scannen Sie lokal, bevor Sie pushen:
# Install Snyk CLI globallynpm install -g snyk
# Authenticate with Snyksnyk auth
# Scan your projectsnyk test
# Monitor your project (sends snapshot to Snyk for continuous monitoring)snyk monitorFügen Sie einen Pre-Push-Git-Hook hinzu:
# Install husky if you haven't alreadypnpm add -D husky
# Initialize huskynpx husky init
# Create pre-push hookcat > .husky/pre-push << 'EOF'#!/bin/sh. "$(dirname "$0")/_/husky.sh"
echo "🔍 Running security scan before push..."pnpm audit --audit-level=moderateEOF
chmod +x .husky/pre-push3. Ihre CI/CD-Pipeline absichern
Der Shai-Hulud-2.0-Angriff zielte gezielt auf CI/CD-Umgebungen ab, in denen Secrets leicht verfügbar sind. So härten Sie Ihre Pipeline ab.
3.1 Minimale Berechtigungen verwenden
Konfigurieren Sie Ihre GitHub Actions nach dem Prinzip der geringsten Privilegien:
name: Deploy to Production
on: push: branches: [main]
# Set minimal default permissionspermissions: contents: read
jobs: deploy: runs-on: ubuntu-latest
# Override only for specific needs permissions: contents: read deployments: write id-token: write # For OIDC authentication
steps: - uses: actions/checkout@v4
- name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'pnpm'
- name: Install pnpm uses: pnpm/action-setup@v2 with: version: 8
# Critical: Disable install scripts in CI - name: Install dependencies run: pnpm install --frozen-lockfile --ignore-scripts
- name: Build env: # Use environment-specific secrets DATABASE_URL: ${{ secrets.PROD_DATABASE_URL }} API_KEY: ${{ secrets.PROD_API_KEY }} run: pnpm run build
- name: Deploy run: pnpm run deploy3.2 Install-Skripte deaktivieren
Install-Skripte sind der primäre Angriffsvektor. Deaktivieren Sie sie in CI/CD immer:
# Always use --ignore-scripts in CI- name: Install dependencies run: pnpm install --frozen-lockfile --ignore-scriptsFür Pakete, die Install-Skripte legitimerweise benötigen (wie sharp oder esbuild), bauen Sie diese explizit neu:
import { execSync } from 'child_process'
console.log('🔒 Running secure installation...\n')
try { // Install without running any scripts console.log('📦 Installing packages without scripts...') execSync('pnpm install --frozen-lockfile --ignore-scripts', { stdio: 'inherit', })
console.log('\n✅ Dependencies installed safely')
// Explicitly rebuild trusted packages that need native bindings const TRUSTED_PACKAGES = [ 'sharp', // Image processing 'esbuild', // Bundler '@parcel/watcher', // File watcher // Add other trusted packages here ]
console.log('\n📦 Rebuilding trusted native packages...') for (const pkg of TRUSTED_PACKAGES) { try { console.log(` - Rebuilding ${pkg}...`) execSync(`pnpm rebuild ${pkg}`, { stdio: 'inherit' }) console.log(` ✅ ${pkg} rebuilt successfully`) } catch (error) { console.error(` ❌ Failed to rebuild ${pkg}`) // Don't fail the whole process - package might not be installed } }
console.log('\n✅ Secure installation complete!')} catch (error) { console.error('\n❌ Installation failed:', error.message) process.exit(1)}Aktualisieren Sie Ihre package.json:
{ "scripts": { "install:safe": "tsx scripts/secure-install.ts", "build": "astro build", "dev": "astro dev" }}3.3 Umgebungsisolation verwenden
Verwenden Sie unterschiedliche Secrets und Credentials für jede Umgebung (Dev, Staging, Produktion), um potenzielle Sicherheitsverletzungen einzudämmen und zu verhindern, dass Leaks sich über Umgebungen hinweg ausbreiten.
name: Deploy to Staging
on: push: branches: [develop]
jobs: deploy-staging: runs-on: ubuntu-latest environment: staging # GitHub environment
steps: - uses: actions/checkout@v4
- name: Build and Deploy env: # Staging-specific secrets DATABASE_URL: ${{ secrets.STAGING_DATABASE_URL }} API_KEY: ${{ secrets.STAGING_API_KEY }} run: | pnpm install --frozen-lockfile --ignore-scripts pnpm run build pnpm run deploy:stagingname: Deploy to Production
on: push: branches: [main]
jobs: deploy-production: runs-on: ubuntu-latest environment: production # Different environment
steps: - uses: actions/checkout@v4
- name: Build and Deploy env: # Production-specific secrets DATABASE_URL: ${{ secrets.PROD_DATABASE_URL }} API_KEY: ${{ secrets.PROD_API_KEY }} run: | pnpm install --frozen-lockfile --ignore-scripts pnpm run build pnpm run deploy:production3.4 OIDC statt langfristiger Tokens verwenden
Für Cloud-Deployments verwenden Sie OpenID Connect (OIDC) anstelle gespeicherter langfristiger Credentials:
name: Deploy to AWS
on: push: branches: [main]
permissions: id-token: write # Required for OIDC contents: read
jobs: deploy: runs-on: ubuntu-latest
steps: - uses: actions/checkout@v4
# Use OIDC to get temporary credentials - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole aws-region: us-east-1
# Now you have temporary AWS credentials - name: Deploy to S3 run: | pnpm run build aws s3 sync dist/ s3://my-bucket/Durch die Einführung von OIDC entfällt die Notwendigkeit, langfristige Cloud-Credentials in GitHub zu speichern – das reduziert das Risiko erheblich, falls Ihre CI-Umgebung kompromittiert wird. Stattdessen kann GitHub Actions für jeden Workflow-Lauf kurzlebige, automatisch ablaufende Credentials anfordern. Jedes Authentifizierungsereignis wird in AWS CloudTrail protokolliert und ist auditierbar – für vollständige Nachverfolgbarkeit und Sicherheitstransparenz.
4. npm-Audit-Automatisierung konfigurieren
Machen Sie Sicherheits-Audits zu einem regelmäßigen Bestandteil Ihres Entwicklungs-Workflows.
4.1 Pre-Commit-Hooks einrichten
Pre-Commit-Hooks fügen Ihrem Workflow einen automatisierten Kontrollpunkt hinzu, der verhindert, dass unsicherer Code committed wird. Jedes Mal, wenn Sie einen Commit versuchen, löst Husky das Sicherheits-Audit aus (mit pnpm audit --audit-level=moderate). Werden Schwachstellen oberhalb des Schwellenwerts erkannt, wird der Commit blockiert, bis die Probleme behoben oder bewusst umgangen werden. So stellen Sie sicher, dass nur sicherer Code ins Repository gelangt und die Integrität Ihres Projekts von Anfang an gewahrt bleibt.
#!/bin/sh. "$(dirname "$0")/_/husky.sh"
echo "🔍 Running pre-commit security checks...\n"
# Run auditecho "📦 Checking for vulnerabilities..."pnpm audit --audit-level=moderate
if [ $? -ne 0 ]; then echo "\n❌ Security vulnerabilities found!" echo "Run 'pnpm audit fix' to resolve issues." echo "Or use --no-verify to skip (not recommended)." exit 1fi
echo "✅ Security checks passed!\n"Aktualisieren Sie außerdem die Skripte in der package.json, um Audits über den jeweiligen Paketmanager auszuführen.
{ "scripts": { "audit": "pnpm audit --audit-level=moderate", "audit:fix": "pnpm audit fix", "audit:production": "pnpm audit --production --audit-level=high", "precommit": "pnpm run audit", "prepush": "pnpm run audit:production" }}4.2 Automatisierte Sicherheitsberichte erstellen
In diesem Abschnitt erfahren Sie, wie Sie automatisierte Sicherheitsberichte für Ihr Projekt erstellen.
import { execSync } from 'child_process'import { writeFileSync } from 'fs'
const generateSecurityReport = () => { console.log('📊 Generating security report...\n')
const report = { timestamp: new Date().toISOString(), auditResults: null as any, outdatedPackages: null as any, recommendations: [] as string[], }
try { // Run npm audit const auditOutput = execSync('pnpm audit --json', { encoding: 'utf-8', }) report.auditResults = JSON.parse(auditOutput) } catch (error: any) { // Audit exits with non-zero if vulnerabilities found if (error.stdout) { report.auditResults = JSON.parse(error.stdout) } }
// Generate recommendations const vulnerabilities = report.auditResults?.metadata?.vulnerabilities if (vulnerabilities) { const { critical, high, moderate } = vulnerabilities
if (critical > 0) { report.recommendations.push( `🚨 CRITICAL: ${critical} critical vulnerabilities require immediate attention` ) } if (high > 0) { report.recommendations.push( `⚠️ HIGH: ${high} high-severity vulnerabilities should be addressed soon` ) } if (moderate > 0) { report.recommendations.push( `ℹ️ MODERATE: ${moderate} moderate vulnerabilities should be reviewed` ) } }
// Write report const reportPath = `security-report-${Date.now()}.json` writeFileSync(reportPath, JSON.stringify(report, null, 2))
console.log(`✅ Security report generated: ${reportPath}\n`)
// Print summary console.log('📊 Summary:') report.recommendations.forEach(rec => console.log(rec))
return report}
generateSecurityReport()- Führen Sie einen
pnpm audit-Befehl aus, um Ihre Dependencies auf Schwachstellen zu scannen und die Ergebnisse als JSON zu erfassen. - Erfassen Sie den Zeitstempel der Erkennung, Audit-Ergebnisse und Empfehlungen zur Behebung.
- Fassen Sie Schwachstellen nach Schweregrad (critical, high, moderate) zusammen und geben Sie handlungsrelevante Empfehlungen, falls Probleme vorliegen.
- Schreiben Sie den resultierenden Sicherheitsbericht in eine Datei, die Sie prüfen oder mit Ihrem Team teilen können.
Durch die Integration dieses Skripts in Ihren Workflow stellen Sie klare und regelmäßige Transparenz über die Sicherheitslage Ihres Projekts sicher. Das erleichtert das effektive Verfolgen und Beheben von Schwachstellen und unterstützt eine Politik des kontinuierlichen Security-Monitorings.
Fazit
Die hier behandelten Schritte schaffen eine zuverlässige Verteidigung: Verwenden Sie stets exakte Versionen und Lock-Dateien, automatisieren Sie Sicherheitsprüfungen in Ihrer CI/CD-Pipeline, deaktivieren Sie Install-Skripte während Produktions-Builds, nutzen Sie OIDC statt statischer Credentials und machen Sie Sicherheitsreviews zu einem Standardbestandteil Ihres Git-Prozesses.
Bei Fragen oder Anmerkungen erreichen Sie mich gerne auf Twitter.