Vulnerabilities¶
Mercator includes a vulnerability detection engine based on Vulnerability-Lookup and the NVD (National Vulnerability Database). Once the vendor and product fields are filled in for an asset, Mercator can identify known CVEs associated with that component and display them alongside their CVSS severity score.
This page covers the architecture of the feature, its configuration, initialization, and day-to-day usage.
Concepts¶
Three standards underpin the detection system:
| Term | Meaning | Example |
|---|---|---|
| CPE | Common Platform Enumeration — a standardized dictionary of known software, operating systems and hardware | cpe:2.3:a:apache:log4j:2.14.1:*:*:*:*:*:*:* |
| CVE | Common Vulnerabilities and Exposures — the public list of known security flaws | CVE-2021-44228 (Log4Shell) |
| NVD | National Vulnerability Database — the US database linking CPE ↔ CVE | The data source queried by Mercator |
The overall workflow is as follows:
Mercator inventory
└─> vendor + product + version filled in for an asset
└─> Mercator looks up the matching CPE in its local database
└─> Mercator queries the NVD for CVEs linked to that CPE
Architecture¶
Mercator stores CPE data in three dedicated tables:
| Table | Contents |
|---|---|
cpe_vendors |
Publishers and manufacturers (e.g. apache, microsoft, cisco) |
cpe_products |
Products by vendor (e.g. log4j, windows_10) |
cpe_versions |
Versions of each product |
These tables are populated by the mercator:cpe-sync command.
Assets supporting CPE fields¶
The vendor, product and version fields are available on the following asset types:
| View | Object | Available in UI |
|---|---|---|
| Applications | Application | ✅ |
| Applications | Application module | ✅ |
| Logical infrastructure | Security appliance (logical) | ✅ |
| Physical infrastructure | Peripheral | ✅ |
| Physical infrastructure | Physical server | ⚠️ stored in DB, not shown |
| Physical infrastructure | Workstation | ⚠️ stored in DB, not shown |
| Physical infrastructure | Physical switch | ⚠️ stored in DB, not shown |
| Physical infrastructure | Physical router | ⚠️ stored in DB, not shown |
| Physical infrastructure | Wi-Fi access point | ⚠️ stored in DB, not shown |
| Physical infrastructure | Phone | ⚠️ stored in DB, not shown |
| Physical infrastructure | Storage infrastructure | ⚠️ stored in DB, not shown |
For assets whose fields are not yet visible in the interface, they remain accessible via the REST API or through JSON import.
Filling in vendor / product / version¶
Vulnerability detection depends entirely on the quality of the data entered. Without the vendor, product and version fields correctly filled in, no CVE search can return results.
CPE naming conventions¶
Values must match exactly the identifiers used in the NVD: lowercase, with underscores replacing spaces.
| Software | vendor |
product |
version |
|---|---|---|---|
| Apache Log4j 2.14 | apache |
log4j |
2.14.1 |
| Microsoft Windows 11 | microsoft |
windows_11 |
21h2 |
| Cisco IOS 15.4 | cisco |
ios |
15.4 |
| SAP S/4HANA 2022 | sap |
s\/4hana |
2022 |
| Ubuntu 22.04 | canonical |
ubuntu_linux |
22.04 |
| Docker 24.0.5 | docker |
docker |
24.0.5 |
If you are unsure of the exact identifiers, use the Guess function (see next section).
Entering data in the interface¶
For an Application:
Applications → Applications → open or create the record → fill in Vendor, Product, Version.
For an Application module:
Applications → Application modules → same procedure.
Import via the API (JSON)¶
{
"name": "Apache Guacamole",
"technology": "apache",
"vendor": "apache",
"product": "guacamole",
"version": "1.5.4"
}
Search¶
The vulnerability search is powered by Vulnerability-Lookup, the open-source service developed by CIRCL (Computer Incident Response Center Luxembourg) and available on GitHub.
Unlike a search limited to the NVD/NIST database, Vulnerability-Lookup aggregates multiple sources: GitHub Advisory Database, PySec, and CSAF feeds from Red Hat, CISA, Cisco, Siemens and other CERTs, providing significantly broader coverage of known vulnerabilities.
Search performs an exact match: Mercator looks up the CPE in its local database that precisely corresponds to the vendor and product values entered, then queries Vulnerability-Lookup for the associated CVEs.
Prerequisite: both fields must be filled in and present in the local CPE database.
Usage:
- Open an application record or any asset record with
vendor,productandversionfields - Click
CVE Search - CVEs are displayed with their CVSS score and description
If no results appear, verify that the CPE database is loaded and that the
vendorandproductvalues match the NVD identifiers exactly.
CPE-Guesser¶
CPE-Guesser is an open-source tool developed by CIRCL (Computer Incident Response Center Luxembourg). It identifies the most probable CPEs from one or more keywords, using an inverted index built from the NVD dictionary and ranked by each CPE's frequency of appearance in known CVEs. Mercator queries CPE-Guesser to return a ranked list of candidates, without requiring the vendor / product / version fields to already be aligned with NVD identifiers.
When to use Guess:
- To identify the correct CPE to record on the asset afterwards
- The exact NVD identifiers are unknown
- CVE Search returns no results
Usage:
- Open the application record or navigate to the CVE menu
- Use the
Guessfunction - Select the matching CPE from the suggested list
- Copy the
vendor/product/versionvalues back to the asset record so that Search works in future
Comparison¶
| Search | Guess | |
|---|---|---|
| Prerequisite | CPE fields filled in and present in the database | None |
| Speed | Instant (local database) | Slower (approximate matching) |
| Accuracy | Very precise when fields are correct | May return false positives |
| Typical use | Well-documented assets | CPE discovery, poorly documented assets |
Reports¶
CVSS score¶
Each CVE is presented with its CVSS (Common Vulnerability Scoring System) score:
| Score | Severity | Priority |
|---|---|---|
| 0.0 | None | — |
| 0.1 – 3.9 | Low | Low |
| 4.0 – 6.9 | Medium | Normal |
| 7.0 – 8.9 | High | High |
| 9.0 – 10.0 | Critical | Immediate |
Detected CVEs appear in the security reports accessible via the Reports menu.
Backing up CVE / CPE data¶
CPE data is stored in the database only (tables cpe_vendors, cpe_products, cpe_versions). There are no separate CVE/CPE files on the filesystem to back up.
Three strategies are available depending on your context:
Option A — Skip CPE table backups
The tables can be regenerated from the NVD at any time. This is the lightest strategy, at the cost of a re-synchronization delay after a restore.
Option B — Full database backup (recommended)
mysqldump -u mercator_user -p mercator > mercator_backup_$(date +%Y%m%d).sql
# Under Docker
docker exec mercator-db mysqldump -u mercator_user -p mercator \
> mercator_backup_$(date +%Y%m%d).sql
Option C — Lightweight backup excluding CPE tables
mysqldump -u mercator_user -p mercator \
--ignore-table=mercator.cpe_vendors \
--ignore-table=mercator.cpe_products \
--ignore-table=mercator.cpe_versions \
> mercator_backup_no_cpe_$(date +%Y%m%d).sql
After a restore, run mercator:cpe-sync --now to repopulate the CPE tables.
Configuration¶
NVD API Key¶
The NVD enforces rate limits depending on whether an API key is used:
| Without key | With key |
|---|---|
| 5 requests / 30 s | 50 requests / 30 s |
| Initial load: 8–24 h | Initial load: 30 min – 2 h |
The key is free. To obtain one:
- Go to https://nvd.nist.gov/developers/request-an-api-key
- Enter an e-mail address
- Receive the key by e-mail (within a few minutes)
Environment variables¶
Add the following lines to your .env file:
# NVD API URL (do not change)
CPE_API_URL=https://services.nvd.nist.gov/rest/json/cpes/2.0
# NVD API key — strongly recommended
NVD_API_KEY=your-key-here
Docker deployment¶
In docker-compose.yml, add these variables to the environment section of the app service:
environment:
- CPE_API_URL=https://services.nvd.nist.gov/rest/json/cpes/2.0
- NVD_API_KEY=your-key-here
Then reload the configuration:
docker-compose up -d
docker exec -it mercator-app php artisan config:clear
docker exec -it mercator-app php artisan config:cache
Initialization¶
Initial CPE database load¶
The CPE database must be synchronized before any CVE searches can be performed. The NVD contains several hundred thousand entries; the duration depends directly on whether an API key is available (see previous section).
# Standard installation (VM)
php artisan mercator:cpe-sync --now
# Docker deployment
docker exec -it mercator-app php artisan mercator:cpe-sync --now
Handling interruptions¶
If the command is interrupted (network outage, timeout, container restart), there is no resume mechanism: the synchronization starts over from scratch.
To avoid this, run the command inside a screen or tmux session to protect it from SSH disconnections:
screen -S cpe-sync
docker exec -it mercator-app php artisan mercator:cpe-sync --now
# Press Ctrl+A then D to detach the session
It is also useful to monitor the Laravel logs in a separate terminal:
docker exec -it mercator-app tail -f storage/logs/laravel.log
Open issue: The ability to synchronize incrementally, or to limit the sync to applications already present in the CMDB, is under consideration. See the Open issues section.
Automatic updates¶
Laravel scheduler¶
Mercator uses the Laravel task scheduler to keep the CPE database up to date. The synchronization is scheduled daily at 03:30, provided the system cron is active.
Cron setup (standard VM)¶
sudo crontab -e
Add the following line:
* * * * * cd /var/www/mercator && php artisan schedule:run >> /dev/null 2>&1
This single entry is sufficient: Laravel internally manages the exact execution time for each scheduled task.
Verification under Docker¶
To list scheduled tasks and confirm that cpe-sync is registered:
docker exec -it mercator-app php artisan schedule:list
To trigger the scheduler manually:
docker exec -it mercator-app php artisan schedule:run
Verifying the CPE database¶
After initialization, or whenever the sync status is uncertain, two methods are available to check the database contents.
Via MySQL / MariaDB¶
-- Row counts per table
SELECT 'vendors' AS type, COUNT(*) AS count FROM cpe_vendors
UNION ALL
SELECT 'products', COUNT(*) FROM cpe_products
UNION ALL
SELECT 'versions', COUNT(*) FROM cpe_versions;
-- Date of last synchronization (approximation via updated_at)
SELECT MAX(updated_at) AS last_sync FROM cpe_versions;
Under Docker:
docker exec -it mercator-db mysql -u mercator_user -p mercator \
-e "SELECT 'vendors' AS type, COUNT(*) AS count FROM cpe_vendors
UNION ALL SELECT 'products', COUNT(*) FROM cpe_products
UNION ALL SELECT 'versions', COUNT(*) FROM cpe_versions
UNION ALL SELECT 'last_sync', MAX(updated_at) FROM cpe_versions;"
Via Laravel logs¶
# Standard installation
tail -n 100 /var/www/mercator/storage/logs/laravel.log | grep -i cpe
# Docker
docker exec -it mercator-app tail -n 100 storage/logs/laravel.log | grep -i cpe
Open issue: The date of the last CPE sync is not yet displayed in the interface or in reports. See the Open issues section.
Open issues¶
The following points were identified during use and are being tracked. This section will be updated as the project evolves.
Resume after cpe-sync interruption¶
Question: If cpe-sync --now is interrupted, is it possible to resume from where it stopped rather than starting over?
Status: ⏳ Pending. Approach under consideration: incremental synchronization, or limiting the sync to applications already present in the CMDB.
CPE sync date not shown in the interface¶
Observation: There is currently no way to see from the interface whether the CPE database is loaded or when it was last updated. The current workaround is a direct SQL query (see Verifying the CPE database).
Status: ⏳ Pending.
Proposal: Display the last CPE sync date on the CVE search screen and in security reports.
CPE fields not visible for certain assets¶
Observation: The vendor, product and version fields exist in the database for several asset types (physical servers, workstations, switches…) but are not accessible from the UI.
Status: ⏳ Clarification requested.
Proposal: Expose these fields in the UI for all CPE-capable assets, to avoid relying on the API or JSON imports for data entry.
"Version" column missing from the Applications list¶
Observation: The Applications list view does not display the version field, even though it is used by the CPE engine.
Status: ⏳ Suggestion submitted.
Proposal: Add a version column to this view to make asset documentation coverage more visible.
Search / Guess distinction not visible in the UI¶
Observation: The interface does not clearly indicate that Search requires the CPE fields to be filled in, nor does it explain the difference in behaviour compared to Guess.
Status: ⏳ Suggestion submitted.
Proposal: Add tooltips or inline explanatory text next to the Search and Guess functions.
Appendix A — Quick command reference¶
# Initial CPE database load
docker exec -it mercator-app php artisan mercator:cpe-sync --now
# List scheduled tasks
docker exec -it mercator-app php artisan schedule:list
# Manually trigger the scheduler
docker exec -it mercator-app php artisan schedule:run
# Clear configuration cache (after editing .env)
docker exec -it mercator-app php artisan config:clear
docker exec -it mercator-app php artisan config:cache
# Check CPE database status
docker exec -it mercator-db mysql -u mercator_user -p mercator \
-e "SELECT 'vendors' AS type, COUNT(*) AS count FROM cpe_vendors
UNION ALL SELECT 'products', COUNT(*) FROM cpe_products
UNION ALL SELECT 'versions', COUNT(*) FROM cpe_versions
UNION ALL SELECT 'last_sync', MAX(updated_at) FROM cpe_versions;"
Appendix B — Minimal .env example¶
APP_NAME=Mercator
APP_ENV=Production
APP_KEY=base64:your_key_generated_by_artisan_key_generate
APP_DEBUG=false
APP_URL=https://mercator.yourdomain.com
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=mercator
DB_USERNAME=mercator_user
DB_PASSWORD=secure_password
# Mail — see the Configuration page for full options
MAIL_MAILER=smtp
MAIL_HOST=smtp.yourdomain.com
MAIL_PORT=587
MAIL_USERNAME=noreply@yourdomain.com
MAIL_PASSWORD=smtp_password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@yourdomain.com
MAIL_FROM_NAME="Mercator"
# API
API_RATE_LIMIT=60
API_RATE_LIMIT_DECAY=1
# CPE / CVE
CPE_API_URL=https://services.nvd.nist.gov/rest/json/cpes/2.0
NVD_API_KEY=your_free_nvd_key