GLPI 11 plugin mlabvuln: matches the software inventoried by glpi-agent against
vuln.mlab.sh to show the CVEs affecting your fleet, prioritise them
(KEV > EPSS > CVSS) and automatically open tickets for actively exploited vulnerabilities.
- Per computer: "To update" with the target version, then the CVE details.
- Fleet-wide: every CVE in the fleet, sorted by priority, filterable, exportable.
- Tickets: one ticket per KEV CVE, affected computers linked, CISA due date as resolution date.
- Dashboard: "mlab vuln" cards.
Contents: Installation · First steps · Deploying agents · Usage · Operations · Troubleshooting · How it works · Development
Two options: A, a new server with the provided Docker stack (GLPI + MariaDB + HTTPS); B, add the plugin to an existing GLPI 11.
Requirements
- A Linux server with Docker Engine 24+ and the Compose plugin (
docker compose version). - A DNS name (e.g.
glpi.example.com) pointing to this server. - Ports 80 and 443 reachable from the Internet (or at least from Let's Encrypt and your endpoints): Caddy obtains and renews the HTTPS certificate on its own.
- 2 vCPU, 4 GB RAM, 20 GB disk for a fleet of a few thousand computers.
Step 1: get the project
git clone https://github.com/mlab-sh/mlab-glpi.git /opt/mlab-glpicd /opt/mlab-glpiStep 2: configure
cp .env.example .envEdit .env: set GLPI_DOMAIN, then two passwords generated with openssl rand -base64 32
for DB_PASSWORD and DB_ROOT_PASSWORD. Protect the file:
chmod 600 .envStep 3: start
docker compose up -d --buildThe first start installs the GLPI database (1 to 2 minutes). Follow progress with:
docker compose logs -f glpiIt is ready once supervisord started shows up. On every start, the container:
- installs or upgrades GLPI (
database:install/database:update); - sets the public URL (
url_base = https://GLPI_DOMAIN); - enables native inventory (so glpi-agent submissions are accepted);
- installs or upgrades the plugin and enables it;
- runs Apache and the GLPI cron (every 60 s, which triggers the
scantask).
What the stack does for security: only Caddy is exposed (80 redirects to 443, HSTS), MariaDB
is only reachable from the Docker network, session cookies are Secure / HttpOnly /
SameSite=Strict, and there are no hard-coded passwords (startup fails if .env is incomplete).
Go to section 2.
-
Download
mlabvuln-<version>.tar.gzfrom the releases. -
Extract it into GLPI's
plugins/directory, owned by the web server user:tar -xzf mlabvuln-*.tar.gz -C /var/www/glpi/pluginschown -R www-data:www-data /var/www/glpi/plugins/mlabvuln
-
Install and enable it, either from the UI (Setup > Plugins > mlab vuln > Install, then Enable) or from the command line:
sudo -u www-data php /var/www/glpi/bin/console plugin:install mlabvuln
sudo -u www-data php /var/www/glpi/bin/console plugin:activate mlabvuln
-
Make sure native inventory is enabled (Administration > Inventory > Enable inventory).
-
Make sure the GLPI cron runs in CLI mode (the
scantask is external).www-datacrontab:* * * * * /usr/bin/php /var/www/glpi/front/cron.php
The server needs outbound HTTPS access to https://vuln.mlab.sh (proxy: Setup >
General > System > Proxy, used by the plugin).
- Open
https://GLPI_DOMAINand log in withglpi/glpi. - Secure it right away: GLPI shows a banner listing the default accounts.
Change the
glpipassword (Administration > Users > glpi), and disable or deletetech,normalandpost-only. Ideally, create your own super-admin account and disableglpi. - Configure the plugin: Setup > Plugins > mlab vuln.
| Setting | Default | Purpose |
|---|---|---|
| API token | none | Personal token generated at https://vuln.mlab.sh/me/tokens. Without a token: anonymous quotas, enough for a small fleet. Stored encrypted with the GLPI key. |
| Rescan a version every | 24 h | How often an already scanned version is checked again. |
| CVE cache per CPE product | 7 days | CVE list of a Windows / macOS product (Chrome: about 7,000 CVEs). |
| Refresh EPSS / KEV | 3 days | Updates scores and the "actively exploited" status. |
| Automatic tickets | KEV only | Disabled, KEV only or KEV + EPSS ≥ threshold. |
| EPSS threshold | 0.5 | Used by the KEV + EPSS mode. |
Tickets are created in the entity of the affected computers: set up your business rules (Administration > Rules > Business rules for tickets) to assign them to the right group.
The plugin only reads the inventory: no agent, nothing to scan. Download the latest glpi-agent
from https://github.com/glpi-project/glpi-agent/releases. The server address is simply
https://GLPI_DOMAIN/.
Windows (silent, as a service, immediate inventory; deployable through GPO or any software distribution tool):
msiexec /i GLPI-Agent-x64.msi /quiet SERVER="https://glpi.example.com/" RUNNOW=1Debian / Ubuntu / Rocky / AlmaLinux / other Linux (official Perl installer):
sudo perl glpi-agent-linux-installer.pl --install --server="https://glpi.example.com/" --runnowmacOS: .pkg package from the releases, then set server = https://glpi.example.com/
in /Applications/GLPI-Agent/etc/agent.cfg.
Check: the computer shows up in Assets > Computers a few seconds after the inventory. The agent then sends its inventory again on its own (once a day by default).
The scan task runs every hour (Setup > Automatic actions > scan) and processes
2,000 software versions per run. To avoid waiting after deploying the agents:
Setup > Plugins > mlab vuln > Scan now, or from the command line (option A):
docker compose exec glpi php front/cron.php --force scanWhere to look:
- Assets > Computers > a computer > Vulnerabilities tab: "To update" (target version per software), then the CVE details.
- Assets > Software > a software > Vulnerabilities tab.
- Tools > Vulnerabilities: every CVE in the fleet, sorted by priority, filterable and exportable; CVE page with the exposed computers.
- Assistance > Tickets: one ticket per KEV CVE, affected computers linked, CISA due date as resolution date.
- Dashboard: edit mode, add a card from the "mlab vuln" group.
Adding a Windows / macOS application: Setup > Plugins > mlab vuln > Manage CPE rules.
A rule maps a software name (regex on the name and, optionally, the publisher) to a CPE
vendor:product as shown on the vuln.mlab.sh CVE page. 18 rules are provided:
Chrome, Firefox, Thunderbird, Edge, 7-Zip, Notepad++, VLC, Acrobat Reader, WinRAR, PuTTY, WinSCP,
FileZilla, KeePass, Wireshark, OpenVPN, TeamViewer, AnyDesk, LibreOffice.
Every command in this section applies to option A and runs from /opt/mlab-glpi.
Schedule it nightly (host cron), then copy the files off the server:
docker compose exec -T db sh -c 'mariadb-dump -uroot -p"$MARIADB_ROOT_PASSWORD" --single-transaction glpi' | gzip > glpi-db-$(date +%F).sql.gzdocker run --rm -v mlab-glpi_glpi:/data:ro -v "$PWD":/backup alpine tar -czf /backup/glpi-files-$(date +%F).tar.gz -C /data .The second archive contains config/glpicrypt.key: without this key, the passwords and the API
token stored in the database cannot be decrypted. Keep it with the SQL backup, somewhere safe.
gunzip -c glpi-db-YYYY-MM-DD.sql.gz | docker compose exec -T db sh -c 'mariadb -uroot -p"$MARIADB_ROOT_PASSWORD" glpi'docker run --rm -v mlab-glpi_glpi:/data -v "$PWD":/backup alpine tar -xzf /backup/glpi-files-YYYY-MM-DD.tar.gz -C /dataThen docker compose restart glpi.
Take a backup, then:
git pulldocker compose up -d --buildThe container upgrades the GLPI database and the plugin on startup. To change the GLPI version,
edit the FROM line of the Dockerfile (read the GLPI release notes first).
Option B: replace the plugins/mlabvuln directory with the new archive, then run
bin/console plugin:install --force mlabvuln.
docker compose logs --tail 200 glpiHistory of every run of the task (versions scanned, errors, tickets created): Setup > Automatic actions > scan > Logs.
Setup > Plugins > mlab vuln > Uninstall drops its tables and configuration. Tickets already created stay in GLPI.
| Symptom | Likely cause | Action |
|---|---|---|
docker compose up: "GLPI_DOMAIN missing" |
.env missing or incomplete |
Section 1, step 2. |
| No HTTPS certificate | DNS not propagated yet, or ports 80/443 closed | docker compose logs caddy. |
| No computers in the inventory | agent misconfigured, or inventory disabled | glpi-agent --force on an endpoint, read its output. |
| Empty Vulnerabilities tab | not scanned yet | Scan now (section 4). |
Scans failing with HTTP 401/403 |
API token invalid or expired | Generate a new one, or tick "remove". |
Scans failing with HTTP 429 |
anonymous quota reached | Set an API token. |
Scans failing with cURL error |
no outbound access to vuln.mlab.sh | Firewall or proxy (option B: GLPI proxy). |
| A Windows application is never found | no CPE rule matches its name | Add a rule (section 4). |
An API error (outage, exhausted quota) keeps the previous results for the affected version: an outage is never shown as "no vulnerabilities". The version is retried on the next run.
| Inventoried software | Method | Endpoint |
|---|---|---|
| Linux packages (Debian, Ubuntu, Alpine, Rocky, AlmaLinux) | Computer OS to OSV ecosystem, exact package + version lookup | POST /api/v2/query |
| Windows / macOS applications | CPE rule (name / publisher regex to vendor:product), product CVEs filtered locally on NVD version ranges |
GET /api/v1/cve?q= |
| CVSS / EPSS / KEV enrichment | per CVE, refreshed every N days | GET /api/v1/cve/{id} |
One scan per software version, not per computer: 1,000 endpoints running the same Chrome = 1 call.
API calls run in parallel (8 concurrent), 429 responses are honoured (Retry-After).
| Operation | Time |
|---|---|
| Vulnerabilities tab of a computer (4,196 CVEs) | 60 to 80 ms |
| Tab badge | 5 ms |
| CVE page with 2,503 exposed computers | 71 ms |
| Dashboard (4 cards) | < 50 ms |
| Cold scan of the 20 CPE products (incl. 6,600 Chrome CVEs) | 6 s |
| OSV scan | about 23 versions/s |
| Enrichment | about 50 CVEs/s |
| Tickets: 68,821 computer links, first run / next runs | 0.7 s / 0.35 s |
- Debian / Ubuntu: OSV indexes source packages, the agent reports binary packages
(
openssh-server,libssl3…): those whose name differs are not found. - Windows / macOS: coverage = CPE rules (18 provided, extensible from the UI). The Windows OS itself is not covered yet.
- The plugin UI is in French only.
Local test stack: the same stack, with GLPI_DOMAIN=localhost in .env
(Caddy then serves a certificate from its internal CA, to accept in the browser). After changing
the plugin: docker compose up -d --build.
python3 seed/seed.py https://localhostpushes 7 demo inventories (3 Windows endpoints, Debian 12, Ubuntu 22.04, Rocky 9 and Alpine 3.18 servers). Never against a production instance.
Tests (no GLPI needed):
docker run --rm -v "$PWD/plugin/mlabvuln":/p -w /p --entrypoint php glpi/glpi:11.0.9 tests/check.phpReleasing: bump PLUGIN_MLABVULN_VERSION in plugin/mlabvuln/setup.php and
CHANGELOG.md, then push a vX.Y.Z tag: CI checks, tests and publishes
mlabvuln-X.Y.Z.tar.gz to the GitHub releases.
MIT license.




