veraltete und unsichere Pakete automatisch erkennen
Ein Dependency Update Checker sammelt regelmäßig den Stand veralteter Pakete über mehrere Repositories hinweg und macht Sicherheitslücken sichtbar, bevor sie in einem Audit unangenehm auffallen. Dieser Artikel zeigt, wie ein solcher Dependency Update Checker composer outdated und npm outdated per jq auswertet, Versionssprünge klassifiziert und die Ergebnisse automatisch als Report verschickt.
Inhaltsverzeichnis
- 1. Warum ein Dependency Update Checker sich lohnt
- 2. composer outdated und npm outdated als Datenquelle
- 3. JSON-Ausgabe mit jq strukturiert auslesen
- 4. Versionssprünge klassifizieren
- 5. Bekannte Sicherheitslücken einbeziehen
- 6. Einen lesbaren Report generieren
- 7. Benachrichtigung per Slack Webhook
- 8. Automatisierung als Cronjob und CI-Job
- 9. Dependency Update Checker im Vergleich
- 10. Zusammenfassung
- 11. FAQ
1. Warum ein Dependency Update Checker sich lohnt
Abhängigkeiten veralten in fast jedem Projekt schneller, als Teams es aktiv nachverfolgen. Ohne einen festen Prozess bleibt die Erkenntnis, dass ein Paket monatelang keine Sicherheitsupdates erhalten hat, oft dem Zufall überlassen, etwa wenn ein externer Pentest die Lücke findet. Ein Dependency Update Checker schließt diese Lücke, indem er regelmäßig und automatisiert prüft, welche Pakete veraltet sind und wie groß der Rückstand tatsächlich ist.
Für Projekte, die sowohl PHP mit Composer als auch JavaScript mit npm einsetzen, wie es bei Magento- oder Hyvä-basierten Shops üblich ist, deckt ein einheitlicher Dependency Update Checker beide Ökosysteme gleichzeitig ab. Statt zwei getrennte Werkzeuge zu pflegen, kombiniert ein Bash-Skript die Ausgabe von composer outdated und npm outdated zu einem gemeinsamen, konsistenten Report.
Der eigentliche Wert eines Dependency Update Checkers entsteht erst durch Automatisierung: Ein wöchentlicher Lauf, der die Ergebnisse per Slack oder E-Mail verschickt, macht veraltete Abhängigkeiten sichtbar, ohne dass jemand aktiv daran denken muss, die Prüfung manuell anzustoßen.
2. composer outdated und npm outdated als Datenquelle
Sowohl Composer als auch npm bringen eingebaute Befehle mit, die veraltete Pakete auflisten: composer outdated --format=json und npm outdated --json. Ein Dependency Update Checker nutzt diese strukturierte JSON-Ausgabe statt die menschenlesbare Tabellenform zu parsen, was deutlich robuster gegenüber Formatänderungen zwischen Versionen ist.
Wichtig ist, beide Befehle mit dem Rückgabewert-Verhalten korrekt zu behandeln: npm outdated gibt absichtlich einen Nicht-Null-Exit-Code zurück, sobald veraltete Pakete gefunden werden, was unter set -e das Skript sofort beenden würde. Ein sauberer Dependency Update Checker fängt diesen speziellen Exit-Code deshalb explizit ab, statt sich von set -e überraschen zu lassen.
#!/usr/bin/env bash
# collect-outdated.sh — gather raw outdated package data from both ecosystems
set -euo pipefail
collect_composer_outdated() {
local project_dir="$1"
(cd "$project_dir" && composer outdated --direct --format=json 2>/dev/null) || true
}
collect_npm_outdated() {
local project_dir="$1"
# npm outdated exits 1 when packages are outdated — this is expected, not a failure
(cd "$project_dir" && npm outdated --json 2>/dev/null) || true
}
readonly PROJECT_DIR="${1:?Usage: collect-outdated.sh <project-dir>}"
collect_composer_outdated "$PROJECT_DIR" > /tmp/composer-outdated.json
collect_npm_outdated "$PROJECT_DIR" > /tmp/npm-outdated.json
echo "[OK] Raw outdated data collected for ${PROJECT_DIR}" >&2
3. JSON-Ausgabe mit jq strukturiert auslesen
Die rohe JSON-Ausgabe beider Werkzeuge hat unterschiedliche Strukturen: Composer liefert ein Objekt mit einem installed Array, npm liefert ein flaches Objekt mit dem Paketnamen als Schlüssel. Ein Dependency Update Checker normalisiert beide Formate mit jq auf eine gemeinsame, einheitliche Zeilenstruktur mit Paketname, aktueller Version und verfügbarer Version.
Diese Normalisierung ist der entscheidende Schritt, der später alle weiteren Auswertungen, von der Versionsklassifizierung bis zur Report-Generierung, unabhängig vom ursprünglichen Ökosystem macht. Der Dependency Update Checker muss ab diesem Punkt nicht mehr wissen, ob ein Paket aus Composer oder npm stammt.
#!/usr/bin/env bash
# normalize.sh — unify composer and npm outdated output into one line format
set -euo pipefail
normalize_composer() {
jq -r '.installed[]? | [.name, .version, .latest, "composer"] | @tsv' \
/tmp/composer-outdated.json
}
normalize_npm() {
jq -r 'to_entries[]? | [.key, .value.current, .value.latest, "npm"] | @tsv' \
/tmp/npm-outdated.json
}
{
normalize_composer
normalize_npm
} > /tmp/normalized-outdated.tsv
echo "[OK] Normalized $(wc -l < /tmp/normalized-outdated.tsv) outdated packages" >&2
4. Versionssprünge klassifizieren
Nicht jedes veraltete Paket ist gleich dringend. Ein Dependency Update Checker sollte den Versionssprung nach Semantic Versioning einordnen: Ein Patch-Update ist meist risikolos, ein Minor-Update sollte zeitnah geprüft werden, ein Major-Update erfordert oft manuelle Anpassungen und einen eigenen Testlauf. Diese Klassifizierung hilft Teams, sich zuerst auf die wirklich relevanten Änderungen zu konzentrieren, statt bei zwanzig Patch-Updates den Überblick zu verlieren.
Die Berechnung erfolgt, indem der Dependency Update Checker die erste Ziffer der aktuellen und der verfügbaren Version vergleicht. Weicht sie ab, handelt es sich um ein Major-Update. Bleibt die erste Ziffer gleich, aber die zweite weicht ab, ist es ein Minor-Update. Alles andere gilt als Patch-Update.
#!/usr/bin/env bash
# classify.sh — categorize version jumps as patch, minor, or major
set -euo pipefail
classify_bump() {
local current="$1" latest="$2"
local cur_major cur_minor lat_major lat_minor
IFS='.' read -r cur_major cur_minor _ <<< "${current#v}"
IFS='.' read -r lat_major lat_minor _ <<< "${latest#v}"
if [[ "$cur_major" != "$lat_major" ]]; then
echo "major"
elif [[ "$cur_minor" != "$lat_minor" ]]; then
echo "minor"
else
echo "patch"
fi
}
while IFS=$'\t' read -r name current latest source; do
bump="$(classify_bump "$current" "$latest")"
printf '%s\t%s\t%s\t%s\t%s\n' "$name" "$current" "$latest" "$source" "$bump"
done < /tmp/normalized-outdated.tsv > /tmp/classified-outdated.tsv
5. Bekannte Sicherheitslücken einbeziehen
Neben reinen Versionsständen liefert ein vollständiger Dependency Update Checker auch Informationen zu bekannten Sicherheitslücken. composer audit --format=json und npm audit --json liefern jeweils eine Liste betroffener Pakete mit Schweregrad. Diese Information sollte im Report deutlich hervorgehoben werden, unabhängig davon, ob das betroffene Paket sonst als geringfügig veraltet eingestuft wurde.
Ein wichtiger Unterschied zur reinen Versionsprüfung: Ein Paket kann sicherheitskritisch sein, obwohl der Versionssprung selbst nur ein Patch-Update ist. Ein guter Dependency Update Checker behandelt Sicherheitslücken deshalb als eigene, priorisierte Kategorie, die unabhängig von der Bump-Klassifizierung immer zuerst im Report erscheint.
#!/usr/bin/env bash
# audit.sh — pull known security advisories from both ecosystems
set -euo pipefail
audit_composer() {
local project_dir="$1"
(cd "$project_dir" && composer audit --format=json 2>/dev/null) || true
}
audit_npm() {
local project_dir="$1"
(cd "$project_dir" && npm audit --json 2>/dev/null) || true
}
readonly PROJECT_DIR="${1:?Usage: audit.sh <project-dir>}"
echo "=== Composer security advisories ==="
audit_composer "$PROJECT_DIR" | jq -r '.advisories // {} | to_entries[]? | .key'
echo "=== npm security advisories ==="
audit_npm "$PROJECT_DIR" | jq -r '.vulnerabilities // {} | to_entries[]? | "\(.key): \(.value.severity)"'
6. Einen lesbaren Report generieren
Rohe TSV-Zeilen sind für den Alltag ungeeignet. Ein Dependency Update Checker sollte die klassifizierten Daten in ein lesbares Markdown-Dokument überführen, gegliedert nach Sicherheitslücken zuerst, dann Major-, Minor- und zuletzt Patch-Updates. Diese Reihenfolge spiegelt die tatsächliche Dringlichkeit wider und erspart es Lesenden, die relevanten Zeilen selbst aus einer langen Liste herauszusuchen.
Die Markdown-Ausgabe eines Dependency Update Checkers lässt sich direkt als Kommentar in ein GitLab- oder GitHub-Issue posten, was den Report sofort in den bestehenden Team-Workflow einbindet, ohne ein zusätzliches Dashboard betreiben zu müssen.
#!/usr/bin/env bash
# generate-report.sh — turn classified data into a readable markdown report
set -euo pipefail
{
echo "# Dependency Update Report — $(date +%F)"
echo
for bump in major minor patch; do
echo "## ${bump^} updates"
echo
echo "| Package | Current | Latest | Source |"
echo "|---|---|---|---|"
awk -F'\t' -v b="$bump" '$5 == b { printf "| %s | %s | %s | %s |\n", $1, $2, $3, $4 }' \
/tmp/classified-outdated.tsv
echo
done
} > dependency-report.md
echo "[OK] Report written to dependency-report.md" >&2
7. Benachrichtigung per Slack Webhook
Ein Report, der nur als Datei auf der Festplatte liegt, wird selten aktiv angeschaut. Ein Dependency Update Checker gewinnt erst durch aktive Benachrichtigung an Wert, etwa über einen Slack Incoming Webhook, der eine Kurzzusammenfassung mit Anzahl der Sicherheitslücken und Major-Updates direkt in den Team-Channel postet.
Für die Nachricht selbst reicht ein einfacher curl Aufruf mit einem JSON-Payload. Wichtig ist, die Nachricht kompakt zu halten und nur auf den vollständigen Report zu verlinken, statt die gesamte Tabelle in den Chat zu quetschen, was die Übersicht eher verschlechtert als verbessert.
#!/usr/bin/env bash
# notify-slack.sh — post a compact summary to a Slack channel
set -euo pipefail
readonly WEBHOOK_URL="${SLACK_WEBHOOK_URL:?Set SLACK_WEBHOOK_URL}"
security_count="$(grep -c "CVE" dependency-report.md || true)"
major_count="$(awk -F'\t' '$5 == "major"' /tmp/classified-outdated.tsv | wc -l)"
payload=$(jq -n \
--arg sec "$security_count" \
--arg maj "$major_count" \
'{ text: ("Dependency check: \($sec) security advisories, \($maj) major updates pending. See dependency-report.md for details.") }')
curl -sf -X POST -H 'Content-Type: application/json' -d "$payload" "$WEBHOOK_URL" > /dev/null
echo "[OK] Slack notification sent"
8. Automatisierung als Cronjob und CI-Job
Damit der Dependency Update Checker tatsächlich regelmäßig läuft, gehört er entweder in einen Cronjob auf dem Deployment-Server oder als geplanten Job in die CI-Pipeline. Ein wöchentlicher Lauf, etwa jeden Montagmorgen, gibt dem Team genug Vorlauf, um vor dem nächsten Release-Fenster auf kritische Updates zu reagieren.
Wichtig für den Dependency Update Checker im CI-Kontext: Der Job sollte den Build niemals fehlschlagen lassen, nur weil veraltete Pakete gefunden wurden, es sei denn, es handelt sich um eine kritische Sicherheitslücke. Die Aufgabe ist informativ, nicht blockierend, sonst verliert das Team schnell die Geduld mit ständig roten Pipelines wegen unkritischer Patch-Updates.
9. Dependency Update Checker im Vergleich
Es gibt SaaS-Lösungen wie Dependabot oder Renovate, die ähnliche Aufgaben automatisiert und sogar mit automatischen Pull Requests lösen. Ein selbst gebauter Dependency Update Checker in Bash bietet dagegen volle Kontrolle über Format, Kanal und Kriterien, ohne Abhängigkeit von einem externen Dienst oder dessen Rate Limits.
| Ansatz | Automatische PRs | Kontrolle über Format | Geeignet für |
|---|---|---|---|
| Bash Dependency Update Checker | Nein, nur Reporting | Vollständig | Interne Reports, Slack-Integration |
| Dependabot | Ja, automatisch | Begrenzt konfigurierbar | GitHub-native Projekte |
| Renovate | Ja, automatisch | Umfangreich konfigurierbar | Große Monorepos, viele Ökosysteme |
| Manuelle Prüfung | Nein | Keine Struktur | Sehr kleine Projekte |
Für Teams, die selbst entscheiden möchten, wann und wie ein Update eingespielt wird, ist ein Dependency Update Checker ohne automatische PRs oft die bewusstere Wahl, gerade in sensiblen Produktionsumgebungen wie Magento-Shops mit vielen kundenspezifischen Erweiterungen.
Mironsoft
Shell-Automatisierung, Abhängigkeitsmanagement und Sicherheits-Tooling
Ein Dependency Update Checker für eure Projekte?
Wir bauen einen maßgeschneiderten Dependency Update Checker für Composer und npm, mit Sicherheits-Audit, Klassifizierung und automatischer Slack-Benachrichtigung.
Skript-Entwicklung
Individueller Dependency Update Checker für euren Stack
Sicherheits-Audit
Bekannte Sicherheitslücken in Composer- und npm-Paketen erkennen
Reporting
Wöchentliche Berichte mit Slack- oder E-Mail-Anbindung
10. Zusammenfassung
Ein Dependency Update Checker in Bash kombiniert die eingebauten Befehle composer outdated und npm outdated zu einer einheitlichen, priorisierten Übersicht über veraltete Pakete. Klassifizierung nach Semantic Versioning und die Einbeziehung von Sicherheits-Audits sorgen dafür, dass die wirklich dringenden Fälle nicht in einer langen Liste untergehen.
Der entscheidende Hebel liegt in der Automatisierung: Ein Dependency Update Checker, der wöchentlich läuft und Ergebnisse aktiv per Slack meldet, verhindert, dass veraltete Abhängigkeiten monatelang unbemerkt bleiben. Für Teams mit mehreren PHP- und JavaScript-Projekten reduziert das den manuellen Prüfaufwand erheblich, ohne die Kontrolle über den Update-Zeitpunkt an eine externe SaaS-Lösung abzugeben.
Dependency Update Checker in Bash — Das Wichtigste auf einen Blick
Datenquelle
composer outdated --format=json und npm outdated --json als strukturierte Basis.
Normalisierung
jq vereinheitlicht beide Formate zu einer gemeinsamen Zeilenstruktur, unabhängig vom Ökosystem.
Priorisierung
Sicherheitslücken zuerst, danach Major, Minor und Patch, jeweils klassifiziert nach Semantic Versioning.
Benachrichtigung
Kompakte Slack-Nachricht mit Link zum vollständigen Markdown-Report, wöchentlich per Cron oder CI.