WordPress-installaties vormen een aantrekkelijk doelwit voor misbruik, zeker wanneer kwetsbare plugins of thema’s niet tijdig worden gesignaleerd. Tegelijkertijd wil je voorkomen dat dagelijkse security-scans leiden tot ruis, onnodige logging of overbodige alerts. In dit artikel beschrijven we hoe je met een self-hosted n8n-workflow en de WPScan-plugin een robuuste, schaalbare en efficiënte afhandeling van WordPress vulnerability alerts kunt inrichten.
Alleen bij daadwerkelijke onraad wordt de scan informatie opgeslagen in de database en gelogd; bij een schone scan is een korte informatieve melding in het logbestand voldoende.
Architectuur op hoofdlijnen
De oplossing bestaat uit vier logisch gescheiden componenten:
-
WPScan plugin (WordPress)
-
Draait periodiek (bijvoorbeeld dagelijks).
-
Stuurt scanresultaten via een webhook als JSON naar n8n.
-
Beperking: maximaal twee scans per etmaal (plugin-afhankelijk).
-
-
n8n Webhook
-
Ontvangt de scanresultaten.
-
Vormt het startpunt van de workflow.
-
-
Normalisatie en filtering (Code-node)
-
Extraheert vulnerabilities uit plugins, themes, WordPress core en security checks.
-
Zet deze om naar een uniform datamodel.
-
Voegt één expliciet log-item toe voor beslislogica.
-
-
Conditionele verwerking
-
Alleen daadwerkelijke vulnerabilities worden opgeslagen in PostgreSQL.
-
Logging (INFO of WAARSCHUWING) gebeurt op basis van één samenvattend log-item.
-
Normaliseren van vulnerability scans vóór beslissen
Een belangrijke ontwerpkeuze is het normaliseren van de webhook-payload voordat er beslissingen worden genomen. WPScan levert zijn resultaten namelijk genest aan, bijvoorbeeld:
-
plugins → vulnerabilities
-
themes → vulnerabilities
-
wordpress core → vulnerabilities
-
security-checks → vulnerabilities
In plaats van deze structuur downstream te blijven interpreteren, is in n8n gekozen voor één centrale Code-node die:
-
alle vulnerabilities verzamelt;
-
per vulnerability één database-record oplevert;
-
exact één extra item toevoegt met samenvattende informatie.
Dat log-item ziet er conceptueel als volgt uit:
Dit patroon heeft twee voordelen:
-
downstream nodes hoeven niets te weten van de oorspronkelijke WPScan-structuur;
-
de beslislogica is eenvoudig en makkelijker controleerbaar in de workflow.
Opslag in PostgreSQL: alleen wat ertoe doet
De PostgreSQL-tabel wp_scan_logs bevat uitsluitend relevante security-events, geen lege of “schone” scans. De tabelstructuur is bewust compact gehouden:
| kolom | betekenis |
|---|---|
| scan_date | tijdstip van detectie |
| vulnerability_type | type kwetsbaarheid |
| severity | ernst (indien beschikbaar) |
| plugin_theme | plugin, theme of core |
| version | betrokken versie |
| details | korte toelichting |
Hiermee ontstaat een historisch overzicht dat geschikt is voor analyse en dat eenvoudig te koppelen is aan dashboards of meldingen.
Logging: één regel per scan, niet per plugin
Een veelgemaakte valkuil bij security-scans is over-logging. In deze workflow is dat expliciet voorkomen.
De beslislogica in de IF-node kijkt uitsluitend naar het log-item:
-
Vulnerability gevonden
→[WAARSCHUWING] WP scan uitgevoerd. Eén of meerdere vulnerabilities gevonden. -
Geen vulnerabilities
→[INFO] WP scan uitgevoerd. Geen vulnerabilities gedetecteerd.
De true/false-branches van de IF-node zijn zodanig ingericht dat de true branch leidt tot een INFO melding en de false branch tot een WAARSCHUWING melding. De IF-node wordt bovendien slechts één keer geëvalueerd (op het log-item), en dus niet op elk vulnerability-record. Het resultaat is een logbestand met maximaal één regel per scan.
Leerpunten
Deze implementatie was er eentje van trial-and-error….
-
Normaliseer vroeg. Beslislogica werkt alleen betrouwbaar als de input eenduidig is.
-
Scheid data van beslissingen. Vulnerability-records en logica-items hebben verschillende doelen en moeten dat ook expliciet uitdrukken.
-
Ga uit van beperkingen van tooling. WPScan-rate-limits betekenen dat “lege” payloads valide zijn; de workflow moet daar expliciet tegen bestand zijn.
-
Minimaliseer ruis. Security-monitoring is alleen effectief als signalen schaars en betekenisvol zijn.
Resultaat
Met deze opzet ontstaat een workflow die dagelijks automatisch draait en alleen de relevante security-informatie opslaat. Deze is makkelijk te inspecteren omdat er geen uitgebreide logs zijn en bovendien wordt de database alleen geactualiseerd wanneer er vulnerability informatie is.
