Azure / Azure/Azure-Sentinel

ASIM: documented 'line to add' for Im_<Schema>Custom doesn't match the shipped stub signatures (5/11 schemas; 3 hard-fail, 1 fails silently)

Open
#14,880 3 comments 0 reactions 3 assignees Claimed by @hunngu-ms View on GitHub
ASIM
Dominant language
Python
Stars
6.1k
Forks
3.8k
Avg merge
4d 7h
Merged PRs (30d)
125

Description

### Summary

The documented "line to add" for patching an `Im_Custom` stub does not match the `functionParameters` of the stubs **shipped in this repository** at [`ASIM/deploy/EmptyCustomUnifyingParsers/`](https://github.com/Azure/Azure-Sentinel/tree/master/ASIM/deploy/EmptyCustomUnifyingParsers).

For **5 of the 11 documented schemas** the argument list is wrong. Three fail hard, one fails **silently**, one loses a filter. Two further shipped stubs have no documented line at all.

I originally filed this against the docs repo as [MicrosoftDocs/defender-docs#520](https://github.com/MicrosoftDocs/defender-docs/issues/520) (2026-06-11). It has had no response in two months, and the artifacts on the wrong end of the comparison live *here* — the stubs were added by #13494, which itself cites that docs page — so I'm re-raising it where the ASIM maintainers are. Either side could be the one to change; that's the decision I'm asking for.

### Verification

- **Stubs**: `ASIM/deploy/EmptyCustomUnifyingParsers/Im_Custom.json` at `ed7ca42` (2026-08-04), read mechanically from each template's `functionParameters`.
- **Docs**: [Manage ASIM parsers → Add a custom parser to a built-in unifying parser](https://learn.microsoft.com/en-us/azure/sentinel/normalization-manage-parsers#add-a-custom-parser-to-a-built-in-unifying-parser), live page as of 2026-08-11 (`ms.date: 2026-07-01`, `updated_at: 2026-08-08`, gitcommit `422ccb92`).

### The five divergences

**1. Authentication — hard failure.** Five documented parameters do not exist in the stub, and two that do exist are absent from the docs.

```
docs: starttime, endtime, targetusername_has_any, actorusername_has_any, srcipaddr_has_any_prefix,
srchostname_has_any, targetipaddr_has_any_prefix, dvcipaddr_has_any_prefix, dvchostname_has_any,
eventtype_in, eventresultdetails_in, eventresult
stub: starttime, endtime, username_has_any, targetappname_has_any, srcipaddr_has_any_prefix,
srchostname_has_any, eventtype_in, eventresultdetails_in, eventresult, disabled, pack
```

`targetusername_has_any`, `actorusername_has_any`, `targetipaddr_has_any_prefix`, `dvcipaddr_has_any_prefix` and `dvchostname_has_any` appear in no shipped `Im_AuthenticationCustom` stub and in no `vimAuthentication*` parser in this repo. Reordering cannot fix this row — it needs the stub's real interface.

**2. ProcessEvent — hard failure.** Docs insert `targetusername_has`; the stub declares only `actorusername_has`.

**3. RegistryEvent — hard failure.** Docs say `registryvaluedata_has_any`; the stub declares `registrydata_has_any`.

For these three, the patched function references an undeclared parameter, so every invocation fails with `Failed to resolve scalar expression named ''`. The portal's *Save as function* rejects the body; an ARM deployment does **not** validate and happily deploys a function that errors on every use — including when reached through the built-in `_Im_`.

**4. AuditEvent — SILENT failure.** Same parameter set, different order.

```
docs: …, srcipaddr_has_any_prefix, eventtype_in, eventresult, actorusername_has_any, operation_has_any, …
stub: …, srcipaddr_has_any_prefix, actorusername_has_any, operation_has_any, eventtype_in, eventresult, …
```

Positional binding puts `eventtype_in` into the leaf's `actorusername_has_any` slot and `eventresult` (a `string`) into `operation_has_any` (a `dynamic`). **The default invocation still works**, so the deployment looks healthy — but any caller passing filters (e.g. a performance-optimized analytic rule calling `_Im_AuditEvent(actorusername_has_any=…)`) gets silently wrong or empty results. Nothing surfaces an error.

**5. WebSession — lost filter.** Docs omit the stub's `eventresultdetails_has_any` (declared after `eventresult`), so that filter can never be forwarded and rows the caller asked to exclude come back.

### Two additional gaps

**6. `disabled` is never forwarded — all 11 rows.** Every stub declares `disabled:bool=false`, and no documented line passes it. The parameter is therefore dead on the custom leaf: `Exclude…` watchlist entries and an explicit `disabled=true` have no effect on it. (Note the built-in unifiers *do* forward it — e.g. `imAuditEvent.yaml`.)

**7. Two shipped stubs have no documented row.** The table covers 11 schemas; this repo ships 13 stubs. `Im_AgentEventCustom` and `Im_AssetEntityCustom` have no "line to add", so there is no documented way to patch them.

### Why the testers don't catch any of this

`ASimSchemaTester` / `ASimDataTester` invoke the parser **without filter arguments**. So the mis-ordered AuditEvent patch produces byte-identical tester output to a correct one, and the unresolvable-parameter patches kill the tester query itself rather than reporting a finding. Neither failure mode is reachable through the normal validation path — which is why #4 in particular can sit in a workspace indefinitely.

### Suggested fix

1. **Regenerate the table from the shipped `functionParameters`** — those are the only signatures that resolve at runtime.
2. **Better: document named-argument invocation.** It is immune to declaration order on both sides, and it is what the built-in unifying parsers already do:

```kusto
MyNewAuditEventParser(starttime=starttime, endtime=endtime, srcipaddr_has_any_prefix=srcipaddr_has_any_prefix, actorusername_has_any=actorusername_has_any, operation_has_any=operation_has_any, eventtype_in=eventtype_in, eventresult=eventresult, object_has_any=object_has_any, newvalue_has_any=newvalue_has_any, disabled=disabled)
```

This also fixes the dead `disabled` parameter for free, and makes the table robust against any future signature change on either side.
3. **Authentication needs its row rewritten**, not reordered.
4. Add rows for `AgentEvent` and `AssetEntity`.

Happy to open a PR against either the stubs or the docs table once you've decided which side should move.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.