> ## Documentation Index
> Fetch the complete documentation index at: https://docs.contraforce.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Parallel Incident Deduplication

> How ContraForce keeps a single copy of an incident that exists in both Microsoft Defender XDR and Microsoft Sentinel, and what that means for notifications, agents, webhooks, and metrics.

Microsoft keeps a Defender XDR incident and its Microsoft Sentinel counterpart synchronised, and presents them to you as one "parallel incident". ContraForce reads both APIs, so without a rule that same real-world incident arrives twice under two different vendor IDs.

ContraForce resolves this **per incident**: it keeps the incident on the side it originated and discards the mirror. No configuration is required, and there is no toggle to set.

<Info>
  Deduplication only applies to a workspace with **both** the Microsoft Defender XDR and Microsoft Sentinel detection modules connected. See [Detection module state](#detection-module-state).
</Info>

## How ContraForce decides

Both systems label the origin of an incident, and ContraForce reads those labels directly. There is no cross-API lookup, no correlation database, and no dependence on which copy arrives first.

| Side                   | The incident is discarded when                                                                                 |
| :--------------------- | :------------------------------------------------------------------------------------------------------------- |
| Microsoft Sentinel     | `providerName` is `Microsoft 365 Defender`, or is `Microsoft XDR` and the alert products are Defender-produced |
| Microsoft Defender XDR | every alert on the incident has `serviceSource` of `microsoftSentinel`                                         |
| Either                 | Nothing else. Anything not positively identified as a mirror is kept.                                          |

That last row is deliberate. An unreadable label, an unfamiliar provider, or a provider call that fails all mean "show the incident". A duplicate is a visible annoyance; a discarded incident is silent data loss.

### The providerName values you will see

| Value                    | Meaning                                                                                                                 |
| :----------------------- | :---------------------------------------------------------------------------------------------------------------------- |
| `Azure Sentinel`         | Created in Sentinel. Never treated as a mirror.                                                                         |
| `Microsoft 365 Defender` | Forwarded into Sentinel by the Defender XDR connector. The Defender incident is the original.                           |
| `Microsoft XDR`          | The workspace is onboarded to the Defender portal, so both representations exist. The alert products decide the origin. |

## The three forwarding scenarios

<Tabs>
  <Tab title="Defender to Sentinel">
    The Defender XDR data connector in Microsoft Sentinel has **Connect incidents & alerts** enabled, so Defender incidents are pushed into Sentinel.

    Those forwarded copies carry `providerName` of `Microsoft 365 Defender`.

    * **Kept:** the Defender XDR incident, attributed to Defender.
    * **Discarded:** the Sentinel copy.
    * **Unaffected:** incidents created natively in Sentinel, which carry `Azure Sentinel` and are never mirrors.

    In the portal, an incident that originated in Defender shows **Microsoft Defender XDR** as its source, even though a copy also exists in your Sentinel workspace.
  </Tab>

  <Tab title="Sentinel to Defender">
    The Sentinel workspace is onboarded to the Microsoft Defender portal, so Sentinel analytic rules surface as Defender incidents. Those incidents carry `providerName` of `Microsoft XDR`, and their alerts have a `serviceSource` of `microsoftSentinel`.

    * **Kept:** the Sentinel incident, attributed to Sentinel.
    * **Discarded:** the Defender mirror.
    * **Unaffected:** genuinely Defender-produced incidents in the same workspace, which are kept and attributed to Defender.

    <Note>
      Incidents created manually, through the API, or by a playbook exist **only** in Sentinel even in a fully onboarded workspace. They carry `Azure Sentinel` and are always kept. This is why ContraForce deduplicates per incident rather than suppressing a whole source.
    </Note>
  </Tab>

  <Tab title="No forwarding">
    Neither connector is forwarding. Each system holds its own incidents and there are no mirrors.

    * **Kept:** everything, from both sources.
    * Nothing is discarded, and behaviour is identical to a workspace with a single detection module.

    A workspace can move into this state and back out of it without any configuration change in ContraForce, because the decision is made per incident at the time it arrives.
  </Tab>
</Tabs>

<Warning>
  Forwarding in **both** directions at once is common, not exceptional. A workspace onboarded to the Defender portal will typically show Sentinel-origin incidents in Defender **and** Defender-origin incidents in Sentinel. Because the rule is applied per incident, each one is resolved on its own evidence and the correct copy survives in both directions simultaneously.
</Warning>

## Detection module state

Deduplication is only safe when ContraForce actually reads both systems. Before discarding a mirror, ContraForce checks that the **counterpart detection module is connected and enabled** on the workspace.

| Workspace modules             | Behaviour                                                                                                                                   |
| :---------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------ |
| Defender XDR **and** Sentinel | Deduplication applies in both directions.                                                                                                   |
| Defender XDR only             | Nothing is discarded. A Sentinel-origin incident is the only copy ContraForce will ever fetch, so it is kept and attributed to Defender.    |
| Sentinel only                 | Nothing is discarded. A forwarded Defender incident is the only copy ContraForce will ever fetch, so it is kept and attributed to Sentinel. |
| Neither                       | Not applicable.                                                                                                                             |

<Warning>
  Disabling one of the two detection modules changes deduplication behaviour immediately. A workspace that was discarding mirrors will start keeping them, because the counterpart is no longer being read. Incident volume in the queue will rise accordingly. This is correct: it is better to show a duplicate than to hide the only copy.
</Warning>

## Downstream effects

The decision is made **once, at ingestion**, before any other processing occurs. A discarded mirror never becomes an incident in ContraForce, so it creates no state anywhere downstream.

| Area                     | Effect on a discarded mirror                                                                                                             |
| :----------------------- | :--------------------------------------------------------------------------------------------------------------------------------------- |
| Incident queue           | Never appears. Only the surviving copy is listed.                                                                                        |
| Email notifications      | None sent. Recipients receive one notification per real-world incident.                                                                  |
| Agent runs               | Not triggered. An agent runs once, against the surviving incident.                                                                       |
| Gamebook auto-run        | Not triggered.                                                                                                                           |
| Webhooks                 | No event is delivered. Subscribers receive one event per real-world incident.                                                            |
| Real-time portal updates | Not pushed.                                                                                                                              |
| Audit trail              | No **Incident Detected** entry is written.                                                                                               |
| SLA tracking             | No timer is started and no SLA state is created.                                                                                         |
| Metrics and dashboards   | Not counted. Incident counts, classification breakdowns, and closure statistics reflect real-world incidents rather than vendor records. |

<Info>
  If your incident counts fell when this behaviour was introduced, that is the duplication being removed. The count now reflects distinct real-world incidents. Historical aggregates computed before the change still include the duplicates and are not retroactively corrected.
</Info>

### Direct links still work

Deduplication is applied when **listing** incidents, not when fetching one. A direct link to a mirrored incident still opens and displays it. This is intentional: a link shared in a ticket, an email, or a chat message continues to resolve rather than returning "not found".

## What this replaced

Earlier versions of ContraForce offered a per-workspace toggle to suppress an entire source. That approach was withdrawn because it cannot be made correct:

* A workspace commonly forwards in both directions, so there is no single source that is safely redundant.
* Suppressing Microsoft Sentinel discards incidents that never reach Defender at all, including any created manually, through the API, by a playbook, or in a secondary workspace.

The toggle no longer exists and no action is required. Any previously configured value is ignored.

## Troubleshooting

<AccordionGroup>
  <Accordion title="I see the same incident twice">
    Confirm both detection modules are connected and enabled on the workspace. With only one connected, ContraForce keeps every incident by design.

    If both are connected, check the `providerName` on the Sentinel incident. A value other than the three listed above is not recognised as a mirror and the incident is kept deliberately, so that an unfamiliar label never causes data loss.
  </Accordion>

  <Accordion title="An incident is attributed to the source I did not expect">
    Attribution follows origin, not arrival. An incident created by a Sentinel analytic rule is attributed to Sentinel even when it also appears in the Defender portal, and an incident created by Defender is attributed to Defender even when it also appears in your Sentinel workspace.
  </Accordion>

  <Accordion title="An incident is missing from the queue">
    Deduplication never removes the last copy, so a missing incident is unlikely to be caused by it. Check the time filter first: the incident list filters on incident **creation** time, while the Microsoft Defender portal displays last activity time. An older incident with recent activity appears recent in Defender and falls outside a short creation-time window in ContraForce.
  </Accordion>
</AccordionGroup>
