Skip to main content

OCSF assets

Every day, each running community sends its Sekoia workspace an inventory of its population, in the OCSF format Sekoia's asset connectors receive: the devices — the users' workstations and the servers —, the users, the vulnerabilities, the installed software, and the Sekoia Agent's own reports: its compliance and its software inventory.

That inventory is not a second population drawn beside the first. It is the projection of the one whose logs the community already sends: a device's hostname, address, OS, agent identifier, vendor and model are those of the entity the logs name. An analyst who goes from an alert to the asset finds the machine the logs talk about — not a namesake.

Nothing is drawn​

What the population does not carry — firewall enabled, disk encryption, MFA, enrolment date, boot time, last logon — is derived from the entity, never drawn. Two runs therefore give the same values. An inventory whose firewall changed state every morning would describe a fleet nobody administers, and nothing in it could be compared from one day to the next.

The same holds for what follows: which CVEs a device carries and which software it declares are derived too.

The connectors​

The catalogue is fixed in code: what a format produces is decided by the Sekoia connector that receives it, not by the operator. Only its instance is configured — which format, which connector of the workspace, active or not.

FormatCategoryProduct
HarfangLab EDRDevicesHarfangLab EDR
HarfangLab EDR SoftwareSoftwareHarfangLab EDR
Crowdstrike Falcon DevicesDevicesCrowdStrike Falcon
SentinelOne DevicesDevicesSentinelOne
Tenable vulnerability managementVulnerabilitiesTenable
Microsoft Entra IDUsersMicrosoft Entra ID

HarfangLab EDR Software is Sekoia's HarfangLab software connector: it sends one item per device and per application.

A device's identifier takes the form of that EDR's logs, so that the asset matches them: the raw agent identifier for HarfangLab and the Sekoia Agent, 32 hexadecimal characters for CrowdStrike and SentinelOne. An identifier of any other form would describe the right machine and never meet its logs.

The Sekoia Agent compliance​

The Sekoia Agent's compliance report (Sekoia Agent compliance) is not a connector you add: as in the original project, it leaves automatically for any community whose Sekoia Agent technology is enabled with its intake key. One request per device, to api/v1/xdr-agent/compliance — the agent's own entry point, not the asset-management API —, authenticated by that intake key, two requests being separated by the agent delay.

Its firewall_enabled is the same value as the device's compliance enrichment: the two reports cannot contradict each other about the same machine.

The Sekoia Agent software inventory​

Next to its compliance, the Sekoia Agent sends its installed software (Sekoia Agent software), under the same conditions: automatically, for any community whose Sekoia Agent technology is enabled with its intake key, with no connector to add. One request per device, to api/v1/xdr-agent/software, authenticated by that intake key and naming the agent in Sekoia-Agent-ID:

{
"hostname": "PC-JDOE-01",
"software": [
{
"uid": "6f1c…",
"name": "Google Chrome",
"version": "149.0.7827.53",
"vendor_name": "Google LLC",
"path": "C:\\Program Files\\Google\\Chrome\\Application",
"install_time": 1780466112.214,
"architecture": "x64",
"purl": "pkg:windows/google-chrome@149.0.7827.53",
"binary_name": "chrome.exe"
}
]
}
  • The applications are those of HarfangLab EDR Software for the same device, field for field — the package uid, name, version, publisher, directory, executable and architecture. Two sources describing one workstation cannot disagree about what it carries.
  • Without the operating system: a package inventory does not list the system. A device that declares only its OS — a Linux workstation, a server whose role installs nothing — still posts, with "software": [].
  • install_time is derived, never drawn: after the device's enrolment and after the release of the version it carries, within two weeks, in epoch seconds. Two runs give the same date.
  • purl is built from the application's name and version (pkg:windows/<name>@<version>, without a version when it is unknown).
  • At most 500 packages per request: a device beyond that sends several, all under its name.
  • Two requests are separated by the agent delay, the same as the compliance's.

Its run is recorded and audited like the others, one request per device.

Setting it up: the Assets tab​

Everything happens in the Assets tab of a community (/communautes/<id>) — except the access to the API, set in its Settings tab: a line stating that access, three cards and a preview.

Sekoia API​

The access lives in the Sekoia API card of the Settings tab. The Assets tab states it in one line — the key's mask, or its absence, and the API base the runs will target — with a link to that card.

The Sekoia API key field carries a key that belongs to the community — each one sends to its own workspace — and that leaves as Authorization: Bearer. It is the community's only Sekoia key: the same one creates its intakes and its asset connectors, so it needs the asset rights and the rights to configure intakes and connectors. It is not the key under Configuration → General settings, which only feeds the indicator catalogue.

Its contract is the intake keys': once saved it is never shown again, only its mask (••••1a2b); leaving the field empty keeps it, ticking the box to clear it erases it, typing a value replaces it. It is not encrypted in the database, and the screen says so — the decryption key would live on the same host as PostgreSQL. And it is read at the moment of posting, never before: a run can wait in the queue, and the key would sleep in Redis all that time.

The API base follows the community's destination. For a Sekoia region it is derived, and there is nothing to enter:

RegionAPI base
FRA1https://app.sekoia.io/
FRA2https://fra2.app.sekoia.io/
MCO1https://mco1.app.sekoia.io/
SGP1https://app.sgp1.sekoia.io/
UAE1https://app.uae1.sekoia.io/
USA1https://app.usa1.sekoia.io/
TESThttps://app.test.sekoia.io/

An intake receives logs, the API receives assets, and the two share neither host nor path: a custom webhook's address says nothing about where the API lives. For a custom destination only, the Sekoia API base URL (custom destination) field is therefore offered. Left empty, every run is skipped, and says why.

Asset connectors​

In the Asset connectors card, pick a format and fill in its Sekoia connector UUID — the last segment of the connector's address in Sekoia, api/v2/asset-management/asset-connector/{uuid} —, tick Active, then Save connectors. A format appears only once per community.

Each row also carries a Spacing (ms): the wait between two requests of a run, from 0 — back to back — to 60,000 milliseconds. A new connector starts at 1,000, and a new HarfangLab EDR Software one at 10,000: software is the only inventory that sends dozens of requests, one per group of hosts, where the other connectors send batches of 1,000 items. An emptied field keeps the saved value, and a connector saved before these defaults keeps its own. The spacing is read when the run starts, so a change applies from the next run, and the audit of a run shows the spacing it used.

The software row adds Hosts / request: how many hosts the software inventory groups into one request, 10 for a new connector, from 1 up to 1,000. A request still never carries more than 1,000 items, and a host is never split to fill one: the request leaves earlier, with fewer hosts. 120 devices ten per request make twelve requests instead of 120, so the spacing counts twelve times rather than 120 — but a batch Sekoia refuses for its content is refused for every host it carries, where one host per request names the single culprit. The field follows the spacing's contract — emptied, it keeps the saved value; read when the run starts — and the audit shows the grouping a run used. The other connectors send fixed batches of 1,000 and have no such field.

Saving the connectors does not re-plan the simulated day. The inventory changes nothing about what the day's logs contain, so the save leaves the community's modification date alone — the channel by which the configuration tells the scheduler its day plan is stale.

Creating a connector in Sekoia​

Rather than creating each connector by hand in Sekoia and copying its UUID back, SekoiaCraft can create it. A format without a connector shows a Create in Sekoia button next to its UUID field as soon as its box is ticked — no need to save first. It uses the community's Sekoia API key — the one the inventories are sent with and the intakes created with — so that key must also be allowed to configure connectors in the community's space: Sekoia's refusal says so if it is not. A click:

  1. reads the key's account (GET /v1/me) to find its Sekoia community;
  2. creates a module configuration (POST /v1/symphony/module-configurations), whose credentials are placeholders copied as they are;
  3. creates the connector (POST /v1/symphony/connector-configurations, type asset) that references it, and sets the UUID Sekoia returns — the row is saved at once, active, at the defaults of its format (10,000 ms and 10 hosts per request for the software inventory);
  4. stops its collection five seconds later (POST /v1/symphony/connector-configurations/<uuid>/stop): SekoiaCraft sends the inventories itself. As for the intakes, a connector still starting is waited for, fifteen seconds at most, and a missed stop does not fail the creation — a warning says to stop it in Sekoia.

Both are named after the format and the community — HarfangLab EDR Software Asset Connector Team3 —, so they are never mistaken for the intake of the same format. A few rules:

  • No button once a UUID is saved. To recreate one, untick the row, save, then tick it again.
  • Nothing is retried. If the connector is refused, the module configuration stays in Sekoia: the reason names it, with its UUID, so it can be deleted there. The next click creates a new one.
  • The refusal shows in the card, with the step Sekoia refused and its answer, the key redacted.
  • Enter in a field saves the connectors, never creates one: the buttons belong to another form.
  • One configuration gesture at a time per community: a creation waits for an intake being created on the same community, whose connector stop can hold it five to fifteen seconds.
  • Creating a connector does not re-plan the simulated day, like saving the connectors.

The UUIDs of the six connectors and modules come from requests captured in Sekoia. Two connector UUIDs — SentinelOne Devices (f47ac10b-…, the example UUID of RFC 4122) and Microsoft Entra ID (b6e2e2e2-…) — are still to be confirmed against a real call.

On a pool, the delivery grid offers the same button for each team, and creates the checked connectors of a team, or of every team, in one gesture — see Creating every asset connector in one gesture.

Sekoia Agent​

The Sekoia Agent card says whether the agent's two sends — its compliance and its software inventory — will leave, by the scheduler's own rule: the Sekoia Agent technology enabled with its intake key. They have no connector row, so their one setting lives here: the Delay between two requests (ms), shared by both sends.

  • 2,000 ms by default, for every community — including those created before the setting: these sends used to leave back to back. 0 sends back to back; 60,000 is the maximum.
  • One request per device, then the delay before the next: 120 devices take about four minutes per send. The delay is read when the run starts, and the audit shows the one a run used.
  • In a pool, each team sets its own: the delay says how a team delivers, not what it receives.
  • Saving writes the community, and only when the value changed: unlike the connectors, this touches its modification date, so the scheduler rebuilds its day plan — identical, a plan being deterministic.

Latest runs​

The Latest runs card lists the last 20 runs. A run is one record, however many batches it takes, and apart from the log dispatch history of /envois.

Each row carries an Audit link, which opens what the run built and posted — every item, kept for 24 hours; All the runs of this community, in Debug → Inventories lists them all.

The table updates itself, while the run sends. A run appears as Queued as soon as it is queued, turns to Sending when its first request leaves, then to its outcome when it ends — without reloading the page. While it sends, the row follows it request after request: Items sent climbs, Requests reads sent out of planned (37 / 120) above a progress bar, the batches refused so far are counted in red, and the last column gives the time it started. A software inventory of a hundred and twenty hosts, ten per request every ten seconds, is no longer two minutes of a frozen row. Without JavaScript the page stays complete, but only a reload shows the change.

StatusWhat it says
QueuedThe run waits for a slot — three runs send at once, all communities
SendingIts requests are leaving; the row shows how far it has got
SentEvery item was accepted
FailedWhat refused and what to check — the rest unfolds under Details
SkippedA deliberate abstention, with its reason

The progress is written at most once a second, the first request always. From a second of spacing — a new software connector waits ten, the Sekoia Agent two — that is every request; a connector or an agent delay set to send back to back moves by steps of a second instead. The run record is the truth, and the screen only re-reads it: a lost update leaves the row a step behind, never wrong. Requests keeps its planned count once the run is over, so a send that stopped early reads 21 / 25.

Skipped is not a failure. A failure calls for a diagnosis; an abstention calls for a gesture, and its reason names it:

  • the community has no Sekoia API key;
  • the destination is custom and has no API base URL;
  • the connector has been removed, or disabled after the run was queued;
  • the Sekoia Agent technology has no intake key, or is no longer enabled;
  • there is nothing to inventory.

A failure reads in two parts. The first line says what refused and what to check — the community's Sekoia API key, the connector UUID, the region. Details unfolds the rest: the endpoint called, the number of attempts, then Sekoia's response with any key masked — a message bounded to 500 characters, or, when items are refused, one validation error per line, with the value received and how many items it concerns. A refused batch also gives its position — and its host, for software —, how many batches were refused, by status, and which hosts; when the run stopped, it says how many batches never left. A refused Sekoia Agent run — compliance or software — counts its refusals by status and names the first agent refused.

Send now queues an extra run immediately, even if the community is stopped or the connector disabled: it is asked for precisely to send again what has already left.

Preview​

Preview shows what the next run would send, without sending anything: the number of items and batches, the first three items in full, and what was left out — named, never merely counted, since each list calls for a different gesture.

Named in the previewWhat it means
Entities without agent id or e-mailNo usable identity: they are not inventoried
OS with no known productNo vulnerability can be attached to them
Entities without archetypeTheir software inventory shrinks to the OS — unless their slice declares roles
Roles the population does not describeTheir entities only have their slice's baseline
Entities without a roleThey only have their slice's baseline
Unclassified binariesDeclared under their own name, outside any application
Linux workstationsThe engine lends them Windows processes; they declare their OS only

When it runs​

Once per local day, from 08:00 in the community's time zone (revises the original project's 08:00 UTC). The original served French communities; here each community lives in its own time zone, and an inventory is taken at 8 am at its place.

From, not at. The scheduler checks every five minutes whether today's run exists. A backend restarted at 3 pm therefore catches up the same day — a single mechanism, as for the planning of a simulated day.

“Start the generation” sends today's inventory at once, and “Start the pool” sends each team's, all describing the same instant. Starting waits neither for the next pass nor for 08:00: it queues the run the scheduler would have started, under the same identifier, so the 08:00 pass finds it done and sends nothing more. Started before 08:00, the day's inventory leaves earlier, not twice; started again the same day, nothing is resent — Send now remains the way to send once more. A community without a Sekoia API key at that moment abstains for the day, as it would at 08:00: set the key before starting.

Only running communities are scheduled: a stopped community — by hand, or because all its technologies were cut off — does not run, and neither does its inventory. Nothing is scheduled without an active connector or an eligible Sekoia Agent.

Items leave in a {version: 1, items} body: whole hosts for software, as many per request as the connector's Hosts / request — ten for a new connector — and never beyond 1,000 items — a device never straddles two requests, and a refused host can be named; a host beyond 1,000 applications, the API's cap, is split and travels alone —, batches of 1,000 for the other connectors. A software inventory of H hosts grouped G at a time therefore makes about H / G requests. Two requests of a run are separated by the connector's spacing — never before the first, nor after the last —, so a run of N requests lasts at least (N − 1) × the spacing; the Sekoia Agent's compliance and software inventory, which have no connector row, are spaced by the community's agent delay, two seconds by default. Each request has 30 seconds and up to five attempts, with an exponential backoff from 1 to 10 seconds that adds to the spacing; on a 429, a Retry-After is honoured, capped at one minute. An inventory is daily and has no urgency, and the API that receives it limits its rate.

Up to three runs play at once, all communities together: a spaced software inventory does not hold up the others. Within a run, requests still leave one after the other; two formats of the same community may however post at the same time, under the same key.

A batch refused for its own content does not stop the run: items Sekoia rejects, or a batch too large, say nothing about the next batch, so the following batches still leave and the audit names the refused ones — with every host they carried. A refused key, an unknown connector, a wrong endpoint or an API that stays unavailable holds for every batch, and stops the run.

Tracing a send​

Every request a run posts is written to the journal of api-asset, under the [AssetSenderService] context — one line per batch, or per Sekoia Agent report, as soon as it has its answer:

docker compose -f infrastructure/docker/docker-compose.dev.yml logs -f api-asset | grep AssetSenderService

On a deployed host, the same logs command targets that environment's compose file, as for the initial password. The lines are in French, like the rest of the journal:

« Acme » HarfangLab EDR Software · lot 3/120 · pc-jdoe-01 · 42 items → HTTP 200 en 184 ms · exécution a.<community>.harfanglab-edr-software.2026-09-15 · POST https://app.sekoia.io/api/v2/asset-management/asset-connector/<uuid>
« Acme » HarfangLab EDR Software · lot 4/120 · pc-mdupont · 38 items → tentative 1/5 : HTTP 503, nouvel essai dans 1 s · exécution … · POST …
« Acme » HarfangLab EDR Software · lot 4/120 · pc-mdupont · 38 items → HTTP 200 en 1293 ms, 2 tentatives · exécution … · POST …
« Acme » HarfangLab EDR Software · lot 2/12 · 10 hôtes (pc-adurand, pc-bmartin, pc-clefebvre, +7) · 412 items → HTTP 200 en 640 ms · exécution … · POST …
« Acme » Sekoia Agent compliance · rapport 2/80 · PC-JDOE-01 · agent <agentId> → refusé HTTP 404 en 95 ms · exécution … · POST https://app.sekoia.io/api/v1/xdr-agent/compliance
« Acme » Sekoia Agent software · inventaire 3/80 · PC-JDOE-01 · agent <agentId> · 18 paquets → HTTP 200 en 120 ms · exécution … · POST https://app.sekoia.io/api/v1/xdr-agent/software
  • The community and the format — hence the connector to look at in the Assets tab.
  • The request — its position in the run; for software, the host it carries — or, grouped, how many hosts and the first three —; for the Sekoia Agent, the workstation and its agent — and, for its software inventory, how many packages; then how many items it carries.
  • The outcome — the HTTP status, and how long the request took, attempts and waits included. An accepted request is an information line; a refused one, or one left without an answer (sans réponse), is a warning. When it stops the run, the line says how many requests never left.
  • Each retried attempt — a warning of its own, with what it received and the wait before the next one: a request held back by a Retry-After shows while it waits, not only once it is over.
  • The run — the identifier of its record, which tells apart the lines of three runs playing at once; then the endpoint called.

A line never carries the key, nor Sekoia's response: the reason for a refusal, with any key masked, unfolds under Details in the Latest runs card. Once the record is written, the worker closes the series under its own [AssetDispatchWorker] context: Inventaire <format> de <community id> : <status>.

Vulnerabilities​

A device's vulnerabilities are chosen by its real OS. The original project applied the CVEs of one hard-coded product, Windows 11, to every device; here a Windows Server 2022 receives server CVEs, and an Ubuntu workstation Ubuntu's.

The known products: Windows 7 SP1, Windows 8.1, Windows 10 22H2, Windows 11 22H2 and 23H2, Windows Server 2016, 2019 and 2022, Ubuntu 22.04 and 24.04, RHEL 9, Debian 12.

Each device receives 0 to 3 CVEs of its OS, stable per device. An OS with no product in that list receives none — and the preview names it, rather than letting an empty list pass for a patched machine.

An application that lags behind carries the real CVEs of its version — the version the software inventory declares. One or two per outdated application, on a budget of their own: a device's OS CVEs do not change when its applications gain some. An up-to-date application carries none, because the catalogue only keeps CVEs that a later release fixes, and the finding says so (is_fix_available). Sekoia's model has no field for the affected package: the application's publisher (vendor_name) and the CVE's title, which names the product, say which one it is.

The CVE catalogue​

The CVEs come from a catalogue with a seeded floor of real CVEs, each checked against NVD and carrying its NVD link: 31 for the operating systems, and 32 for the applications whose NVD entries name a fixed version — Adobe Acrobat, Google Chrome, Microsoft Edge and Mozilla Firefox. It is a dataset — “Vulnérabilités (CVE)”, slug cve-catalogue — editable from /datasets like any other.

An installation seeded earlier receives the new rows. The floor is created once and never rewritten; each seed adds the CVEs it lacks, and gives their version ranges to the seeded rows that have none. A row the feed or /datasets wrote is never touched.

Microsoft 365 Apps, OneDrive, AnyDesk, Chocolatey, Zscaler, Intune and Edge Update have no application CVE: NVD has none that a release of the catalogue fixes — Microsoft 365 Apps, for one, is never versioned there.

It can be refreshed daily from NVD, through the public CVE API 2.0 — no key needed. Under Configuration → General settings, CVE feed (NVD) card: tick Refresh the CVE catalogue daily from NVD, or click Refresh now. The refresh runs in the background and takes one to two minutes: NVD's public rate limit — five requests per thirty seconds — spaces the queries out.

Two rules keep it safe:

  • the feed only replaces the rows it wrote. A seeded row, or one entered from /datasets, survives every refresh;
  • an empty or failed refresh leaves the catalogue untouched. Replacing a dated catalogue with an empty one would be strictly worse — the rule the indicator feed already follows.

A CVE is attached to a product only if NVD marks that product itself vulnerable. NVD also lists the platforms a vulnerable component runs on: a flaw in an application may name Windows as its platform, and counting it would give every Windows device a CVE that is not Windows'.

Software​

A device's software inventory is what its role installs, as its population describes it — the roles of a user's organisational unit or of a server's role, on top of the slice's baseline. The same list bounds the processes its logs name, so the inventory and the logs cannot disagree: an application whose process the logs show is an application the inventory declares.

  • the inventory declares the operating system, then exactly the role's applications, with the companions their installer brings (Chrome brings Google Update);
  • an application its gestures launch is described by the path the logs show; one no gesture launches — SQL Server on a database server, Wireshark on an IT workstation — by the executable its installer lays down. Installed is not launched;
  • binaries of Windows' own directories belong to the OS package.

A slice of the population that declares no role keeps the earlier derivation: the inventory is what the engine can make the device's gestures execute — the very process tables the logs draw from —, grouped into applications. The six demonstration populations declare roles for both slices.

Each application is described by the executable an inventory cites: its file, directory, architecture and signature all come from that one path. The columns Sekoia shows are filled from the item's software object — the one Sekoia's own HarfangLab connector does not send, which is why they stayed empty while SekoiaCraft imitated it:

ColumnFilled from
Publisherthe company that publishes the application (software.vendor_name)
Versionthe device's version (software.version, and sbom.package.version)
Architecturethe path: a Store package's _x64, Program Files (x86) for 32-bit — Edge excepted
Filenamethe executable (software.binary_name); its directory goes to software.path
Signeda signer that a public source attests (software.signature.state)
Signed bythe certificate subject, when its authority is attested too (certificate.subject)
CPEthe product NVD's dictionary names, at the device's version (sbom.package.cpe_name)

The column-to-field mapping is read from the field names of Sekoia's model; Sekoia does not document it.

Versions are real. They come from each vendor's official release history — Chrome, Edge, Firefox, Microsoft 365 Apps, OneDrive, Acrobat, AnyDesk, Chocolatey, Zscaler, Edge Update, Teams, Visual Studio Code, Git for Windows, Docker Desktop, Notepad++, 7-Zip, PuTTY, WinSCP, Wireshark, KeePass, Zoom, SQL Server 2022 and Veeam — one per quarter since 2024. Most devices run the latest release out on the inventory day; about 15 % of (device, application) pairs lag one to three releases behind. That share is a modelling choice, stable from one inventory to the next and drawn per application: a device can be behind on Chrome and current on Firefox. An application no source dates keeps unknown.

The CPE names the product, at the version of the package. sbom.package.cpe_name is the field Sekoia's own HarfangLab connector maps from its cpe_prefix, and the only normalised identifier an inventory carries. The string comes from NVD's CPE dictionary, and one rule fills it: the device's version replaces the version slot when — and only when — the recorded string leaves it free (*). A - means NVD declares that product without a version — Microsoft 365 Apps, OneDrive on Windows, the Intune extension — and putting ours there would invent a product. An unknown version leaves the slot free. Nothing else is touched, so Acrobat's continuous edition and OneDrive's windows platform survive untouched. The OS package carries its product's identity as the dictionary writes it, never the widened string the CVE feed queries with, and its build is never substituted: a build is not a CPE version, and the release is already in the product name (windows_11_23h2).

The logs show the same version. Edge, OneDrive and a few others write their version in a directory (…\Edge\Application\122.0.2365.92\…). That directory takes the device's version in the logs as well — path, command line and hash — so a device behind on Edge shows the old version on both sides.

The signer is shared with the logs. SentinelOne, Cortex and HarfangLab name the same signer as the inventory, read from the same catalogue — SentinelOne writes the certificate subject in capitals (MICROSOFT WINDOWS), Cortex the company (Microsoft Corporation). A Windows binary is signed “Microsoft Windows” only in the system's own directories (System32, SysWOW64, WinSxS, …), never merely for sitting under C:\Windows\. The certificate's authority depends on the version: Edge, Edge Update and Firefox changed theirs during the period, and each device gets the one of its version.

Threat binaries are never declared. An implant's process running outside the inventory is exactly what an analyst should notice; declaring it would hide it among the legitimate software.

What this does not do​

  • Entra ID users match their logs through the UPN, not the identifier. The Entra ID logs still draw a random userId; the e-mail is what both carry.
  • SentinelOne's numeric agent identifier stays random. A SentinelOne device meets its logs through the 32-character identifier only.
  • Linux workstations declare their OS only, while the engine still lends them Windows processes in the logs. The preview names them.
  • Without roles, the set of applications is nearly uniform across Windows workstations: the process tables are shared. Declaring the population's roles is what sets workstations apart.
  • An application declared but never launched does not appear in the logs. The process pools only carry the applications the corpus showed; SQL Server and Veeam appear in a server's listening-port log, the others in the inventory only.
  • Destinations are not filtered. A mail gesture whose client (Outlook) is not installed keeps its destination and names no process.
  • A role without Microsoft 365 or without a browser empties the matching pool: opening an application, or browsing, then names no process, and each technology falls back on its own sample. The seeded populations always carry both.
  • A server's listening log follows its role, not its list. The 5154 of a database server names SQL Server whatever its role installs: removing SQL Server from that role makes the log name an application the inventory does not declare.
  • The version catalogue is frozen in code. It holds one release per quarter up to the day it was compiled; past that, devices stay on the last known release. Refreshing it means adding lines.
  • Google Update, the Azure VM agent, Phone Link and Mail and Calendar keep the version their directory writes. No source dates their releases — and the Azure agent's directory also carries its install date, which a rewritten version would contradict.
  • Some applications are signed without a certificate. Microsoft 365 Apps, the Store applications and Intune show a signer whose authority no source names; Adobe, Zscaler, OneDrive, the Azure agent, SAP GUI and Veeam show no signer at all, and 7-Zip is not signed by its publisher. Edge 145 to 147 fall between two recorded authorities; Git for Windows from 2.55, Wireshark from 4.6.5 and SQL Server before its September 2026 update are signed through authorities that change from one release to the next, or that no source dates.
  • SAP GUI keeps unknown. Its release dates live behind an SAP login, and its install path is attested by a third party only — as is Zoom's.
  • Seven applications carry no CPE. NVD's dictionary names no product for Google Update (it knows only google:updater 2.4.x, a different product), the Acrobat update service, Phone Link, Mail and Calendar, Chocolatey or the Azure VM agent; it names Git without the .windows.N suffix Git for Windows declares. Their items go without the field rather than borrow a near-namesake, which would match another product's CVEs.
  • No hash is sent for a software item. A binary without a version directory (chrome.exe) keeps the same hash in the logs from one version to the next; declaring it with an old version would contradict that.
  • Application CVEs come from the seeded floor only. The NVD refresh still covers the operating systems.
  • The mapping of Sekoia's columns to the item's fields is inferred from the field names of its model; only a real send confirms it.
  • last_logon does not re-read the simulated day: it is derived from the entity, not from the sign-ins the logs show.