Sending events to a SIEM
TechWatchAlert can stream your organization’s security events to your SIEM: a CVE that affects an asset, a decision tier that rises, reported exploitation, a fixed machine, a reopened case, a compliance or external attack surface finding. Your SOC correlates them with the rest of its logs, without opening the application.
Team and Enterprise plans The page is reserved for the organization’s administrators.
Adding a destination
Section titled “Adding a destination”- Open Organization settings › Security › SIEM.
- Choose the tool: Syslog (TLS), Splunk, Microsoft Sentinel or Elastic.
- Fill in the address and the secret (see below for each tool).
- Set What is sent: event types, minimum severity, projects.
- Click Test and save. The test checks the address, the certificate, the credentials, then sends one test event (
event_type=test). The destination is saved only if the test succeeds; Save anyway remains available if your SIEM is not ready yet.
An organization can have up to five destinations, for example a production Splunk and a staging syslog.
Settings for each tool
Section titled “Settings for each tool”- Transport: TCP encrypted with TLS 1.2 or later (RFC 5425), port 6514 by default, or your collector’s port (443, or 1024 to 65535).
- Framing: one frame per event, prefixed by its length in octets (octet counting, RFC 6587 § 3.4.1), the only framing allowed over TLS.
- Message: RFC 5424 header (
<PRI>1 timestamp host application - type -), no structured data, then the body in CEF (ArcSight, QRadar) or JSON (the schema below). - Certificate: verified, host name included. If your collector presents a certificate signed by your internal certificate authority, paste it in PEM format: only that CA is then accepted.
- Syslog facility:
authpriv(10) by default;auth,auditorlocal0tolocal7as you prefer. The syslog severity follows the event’s (critical → 2, high → 3, medium → 4, low → 5, information → 6).
- Address: your HTTP Event Collector, for example
https://splunk.example.com:8088, orhttps://http-inputs-<stack>.splunkcloud.comfor Splunk Cloud. Events are sent to/services/collector/event. - HEC token: create it in Settings › Data inputs › HTTP Event Collector, allowed on the index you want.
- Index (optional), sourcetype (
techwatchalert:eventby default) and source (techwatchalert). - Several events are sent in one request; each event’s time is its timestamp (
time, in seconds since the epoch). The request channel is provided; indexer acknowledgment is not awaited, leave it disabled on this token. - For Splunk to extract the JSON fields at search time, declare the sourcetype as follows (
props.conf), or choose the_jsonsourcetype:
[techwatchalert:event]KV_MODE = jsonEvents go through the Azure Monitor Logs Ingestion API, into a custom table of your Log Analytics workspace. The legacy, deprecated HTTP Data Collector API is not used.
- Entra ID application: register an application and create a client secret. Note the tenant ID and the application ID.
- Table: create the custom table
TechWatchAlert_CLwith the columns listed in Sentinel table columns. - Data collection rule (DCR): declare the stream
Custom-TechWatchAlert_CLwith the same columns, a destination to your Log Analytics workspace, and thesourcetransformation. The template is below. - Permissions: give the application the Monitoring Metrics Publisher role on the DCR.
- In TechWatchAlert, enter the ingestion endpoint (the DCR’s own, or a DCE if you use a private link), the DCR immutable ID (
dcr-…), the stream, the tenant, the application and the secret.
The token is obtained with the OAuth 2.0 client credentials flow. Each call stays under 1 MB, the API limit; a throttled call (429) is retried after the delay given by Azure.
{ "properties": { "streamDeclarations": { "Custom-TechWatchAlert_CL": { "columns": [ { "name": "TimeGenerated", "type": "datetime" }, { "name": "EventId", "type": "string" }, { "name": "EventType", "type": "string" }, { "name": "Category", "type": "string" }, { "name": "Severity", "type": "string" }, { "name": "SeverityScore", "type": "int" }, { "name": "Message", "type": "string" }, { "name": "OrganizationId", "type": "string" }, { "name": "ProjectId", "type": "string" }, { "name": "ProjectName", "type": "string" }, { "name": "CveId", "type": "string" }, { "name": "CvssScore", "type": "real" }, { "name": "Epss", "type": "real" }, { "name": "Kev", "type": "boolean" }, { "name": "Exploited", "type": "boolean" }, { "name": "DecisionTier", "type": "string" }, { "name": "HostId", "type": "string" }, { "name": "HostName", "type": "string" }, { "name": "FindingRule", "type": "string" }, { "name": "Url", "type": "string" }, { "name": "SchemaVersion", "type": "string" }, { "name": "Details", "type": "dynamic" } ] } }, "dataFlows": [ { "streams": ["Custom-TechWatchAlert_CL"], "destinations": ["<name of the Log Analytics destination>"], "transformKql": "source", "outputStream": "Custom-TechWatchAlert_CL" } ] }}- Address: your Elasticsearch endpoint, for example
https://my-deployment.es.europe-west1.gcp.elastic-cloud.comorhttps://es.example.com:9200. - Data stream:
logs-techwatchalert-defaultby default. Thelogs-*-*index template shipped by Elastic creates it on the first send. - API key: the encoded value given by Kibana (or
id:key). Minimum privileges:
{ "role_descriptors": { "techwatchalert": { "indices": [ { "names": ["logs-techwatchalert-*"], "privileges": ["create_doc", "auto_configure"] } ] } }}Documents are sent with the _bulk API, create action (the only one a data stream accepts), with the event identifier as _id: an event sent twice is not indexed twice.
Events
Section titled “Events”Type (event_type) |
When | Severity |
|---|---|---|
vulnerability.detected |
a CVE affects a monitored component or machine (the alert is created) | the CVE’s |
vulnerability.priority_changed |
a case’s decision tier changes, for example from D+60 to D+3 | from the new tier |
vulnerability.status_changed |
a case status changes (in remediation, fixed, risk accepted…) | information |
vulnerability.exploited |
added to the KEV catalog (CISA, VulnCheck), exploitation reported by CERT-FR, public PoC or ransomware, on a CVE that affects an asset | critical (high for a PoC) |
vulnerability.reopened |
a closed case reopens (machine vulnerable again, expired exception, fix not confirmed) | at least medium |
vulnerability.fix_verified |
the inventory confirms that no machine is exposed anymore | information |
host.vulnerable |
a machine becomes exposed to a CVE, or is exposed again | the CVE’s |
host.remediated |
the inventory sees a machine that is no longer exposed | information |
compliance.finding |
a hardening rule becomes non-compliant on a machine | the rule’s |
attack_surface.finding |
a finding opens on a monitored domain (vulnerable service, sensitive port, certificate…) | the finding’s |
audit.action |
an action of the organization’s audit log (optional, unchecked by default) | information |
Without a choice of types, a destination receives everything except the audit log. A project filter still lets organization events (audit log) through, since they have no project.
Schema
Section titled “Schema”Each event follows a stable, versioned schema (schema_version). Timestamps are in UTC (RFC 3339, milliseconds). event_id is stable: the same fact sent again keeps the same identifier, so your SIEM can deduplicate. The event is frozen at the time of the fact. Blocks that do not apply are absent.
{ "schema_version": "1.0", "event_id": "5e04c44f-419c-5e6a-b773-12f474678160", "event_type": "vulnerability.detected", "category": "vulnerability", "timestamp": "2026-10-25T09:30:15.123Z", "severity": "critical", "severity_score": 10, "message": "CVE-2026-1234567 affects a monitored asset", "organization": { "id": "11111111-2222-3333-4444-555555555555" }, "project": { "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", "name": "Portal" }, "vulnerability": { "id": "CVE-2026-1234567", "severity": "critical", "cvss_score": 9.8, "cvss_version": "3.1", "cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "epss": 0.43, "kev": true, "exploited": true, "exploitation_sources": ["cisa_kev", "certfr"], "poc": true, "ransomware": false, "reference": "https://www.cve.org/CVERecord?id=CVE-2026-1234567" }, "asset": { "name": "nginx 1.25.3" }, "url": "https://app.techwatchalert.com/fr/alerts/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/CVE-2026-1234567"}| Field | Content |
|---|---|
schema_version, event_id, event_type, category, timestamp |
schema version, stable identifier (UUID), type, family (vulnerability, host, compliance, attack_surface, audit), UTC timestamp |
severity, severity_score |
info, low, medium, high, critical; score 1, 3, 5, 8 or 10 |
message |
short sentence in English |
organization.id, project.id, project.name |
where the fact happens |
vulnerability.* |
CVE, severity, CVSS score and vector, EPSS, KEV, exploitation and its sources (cisa_kev, vulncheck_kev, certfr), PoC, ransomware, decision_tier (j3, j14, j60, differe) |
host.id, host.name |
the machine concerned |
asset.name, asset.software |
the exposed component or software |
change.field, change.from, change.to, change.reason |
what changed (tier, case status) |
exploitation.kind, exploitation.sources |
known_exploited, poc_published or ransomware |
finding.* |
rule or finding type, title, section, benchmark, target, port, service, product, version, related CVEs |
detection.historical, detection.reappeared |
alert of a component added for already published CVEs; machine exposed again |
actor.id, actor.email, actor.type, source.ip, audit.action, audit.target |
author and action (audit log, case decisions) |
url |
link to the application page |
Never sent: case comments, notes, justifications and attachments, nor the settings details of audit actions.
CEF mapping
Section titled “CEF mapping”Header: CEF:0|TechWatchAlert|TechWatchAlert|1.0|<event_type>|<readable name>|<severity_score>|. The header escapes \ and |; the extension escapes \, = and line breaks, as the standard requires.
| CEF key | Field |
|---|---|
rt |
timestamp (milliseconds since the epoch) |
externalId |
event_id |
cat, act, msg |
category, event_type, message |
dhost |
host.name |
suser, suid, src |
actor.email, actor.id, source.ip |
cs1 |
the object: CVE (cveId), rule (ruleId), finding type (findingType) or audit action (auditAction), named by cs1Label |
cs2 / cs4 / cs5 |
project.name / project.id / organization.id |
cs3 |
decisionTier, or a case’s newStatus |
cs6 |
url |
cfp1 / cfp2 |
CVSS score / EPSS |
cn1 / cn2 |
KEV (0 or 1) / confirmed exploitation (0 or 1) |
ECS mapping (Elastic)
Section titled “ECS mapping (Elastic)”| ECS field | Field |
|---|---|
@timestamp, message |
timestamp, message |
event.id, event.action, event.severity, event.kind, event.category, event.type |
event_id, event_type, severity_score; alert or event; vulnerability, host, configuration, network |
event.dataset, event.module, event.provider, event.reference |
techwatchalert; url |
vulnerability.id, .severity, .score.base, .score.version, .reference, .enumeration, .classification, .scanner.vendor |
the vulnerability block |
host.id, host.name; user.id, user.email; source.ip |
machine; author |
rule.id, rule.name, rule.category |
compliance or external attack surface finding |
organization.id, labels.project_id, labels.project_name |
organization, project |
observer.vendor, observer.product |
TechWatchAlert |
techwatchalert.* |
what has no ECS equivalent: EPSS, KEV, tier, change, exploitation, finding, detection |
Sentinel table columns
Section titled “Sentinel table columns”TimeGenerated, EventId, EventType, Category, Severity, SeverityScore, Message, OrganizationId, ProjectId, ProjectName, CveId, CvssScore, Epss, Kev, Exploited, DecisionTier, HostId, HostName, FindingRule, Url, SchemaVersion, and Details (dynamic), which carries the full event.
Query examples
Section titled “Query examples”// Exploited CVEs affecting an asset, over 7 daysTechWatchAlert_CL| where TimeGenerated > ago(7d)| where EventType == "vulnerability.exploited"| summarize Projects = make_set(ProjectName), Latest = max(TimeGenerated) by CveId, CvssScore, Kev| order by Latest desc// Machines exposed again (reappearance after a fix)TechWatchAlert_CL| where EventType == "host.vulnerable" and tobool(Details.detection.reappeared)| project TimeGenerated, HostName, CveId, ProjectName, Url// Tiers raised to D+3: to handle within three daysTechWatchAlert_CL| where EventType == "vulnerability.priority_changed" and DecisionTier == "j3"| project TimeGenerated, CveId, ProjectName, From = tostring(Details.change.from), Urlindex=security sourcetype="techwatchalert:event" event_type="vulnerability.exploited"| stats latest(_time) AS latest values(project.name) AS projects BY vulnerability.id vulnerability.cvss_score| sort - latestindex=security sourcetype="techwatchalert:event" event_type="host.*"| timechart span=1d count BY event_typeindex=security sourcetype="techwatchalert:event" event_type="compliance.finding" severity IN ("high","critical")| table _time host.name finding.rule finding.title project.nameFROM logs-techwatchalert-*| WHERE event.action == "vulnerability.exploited"| STATS latest = MAX(@timestamp) BY vulnerability.id, labels.project_name| SORT latest DESCReliability
Section titled “Reliability”- Nothing is lost at the first incident: events are queued together with the decision that produces them, then sent in batches. A SIEM outage (network,
5xx,429) is retried later, with a growing delay, honoring the delay requested by the SIEM. Even a settings refusal (revoked token, unknown index) is retried: fix the configuration and pending events will go out. - Cap: after several hours of failures, an event is dropped and counted as Dropped on the destination page. Each destination’s queue is also bounded.
- Visible status: the page shows the last send, the events sent, pending and dropped, the failures in a row and the cause of the last failure, without technical details.
- Syslog has no acknowledgment: a batch is considered sent once the collector has accepted all its frames on the TLS connection.
- Outside the plan, nothing is sent: pending events are discarded and the page says so. Destinations stay listed and can be deleted; they resume as they are if the plan comes back.
Security
Section titled “Security”- The token, secret or key is encrypted at rest, never shown again, never written to a log. Changing the address or the application requires entering it again.
- Encrypted connection, verified certificate, no redirects. The address is checked at every send.
- The address must be public: internal network addresses are refused. For an internal SIEM, expose a collector on a filtered public address (for example a TLS syslog open to TechWatchAlert’s addresses only); relaying through the agent is not available for SIEM yet.
- Every creation, change and deletion of a destination goes into the organization’s audit log.