sentinel-one/ai-siem/sdl-log-parser
Claude Code and agent skill by sentinel-one/ai-siem
- community
Checking that the SKILL.md file is still in the repository.
Use whenever the user wants to author, edit, debug, validate, or explain a SentinelOne Singularity Data Lake (SDL) log parser, the augmented-JSON files at /logParsers/ that extract fields from raw log text before ingestion. Trigger on "SDL parser", "Skylight parser", "log parser", "parser editor", "write a parser", "test parser", or any pasted raw log the user wants turned into structured fields. Also trigger on parser-DSL keywords like `formats:`, `patterns:`, `lineGroupers:`, `rewrites:`, `di…
Install
npx vskill@latest install sentinel-one/ai-siem/sdl-log-parserSKILL.md
SentinelOne SDL Log Parser Authoring
<!-- CONFIG-FILE-ADDRESSING v1 -->
SDL config files: address by `udoId`, and do not trust a REST listing.RESTlistFiles/getFilecannot see udoId-addressed/dashboards/files, sogetFilereturns404on a dashboard the console is displaying and the listing under-reports (measured onone tenant: REST 8, GraphQL 17, console 48 files). **If a listing disagrees with what the UIshows, the listing is wrong until proven otherwise**, change read path before concluding theobject is missing or the token lacks scope. Use the GraphQLconfigFiles/configFilesurface.A name-addressedaddConfigFileto/dashboards/creates a duplicate instead of updating;address dashboards byudoIdwithexpectedVersion.contentis HJSON, not JSON.S1-Scopechanges which files exist as far as the caller can tell.Full detail: `sdl-api/references/config-file-graphql.md`
This skill turns raw log samples into deployed, validated SDL parser definitions. A parser is an augmented-JSON file at /logParsers/<name> on the SDL tenant that extracts fields from each ingested line. The parser editor and the Test Parser button in the console run the parser client-side in JavaScript; this skill mirrors that workflow programmatically and finishes by ingesting a sample through the deployed parser to confirm the actual ingest path works.
Deploy and validate through the `s1-secops-mcp` MCP tools.sdl_get_file/sdl_put_fileread and deploy the parser,powerquery_runvalidates on the live stream, andhec_ingestruns the synthetic-ingest fallback. The server runs on the user's machine, so it reaches*.sentinelone.netwhere the Cowork sandbox cannot, and it reads credentials from environment variables or the OS keychain. If the tools are missing, point the user to the s1-secops-mcp README (s1-secops-mcp/README.mdin the s1-secops-skills source repo,mcp/s1-secops-mcp/README.mdin ai-siem; not shipped inside the plugin).
Gate 0: can an SDL parser run on this source at all? (check this first)
The SDL parser sees exactly two attributes on an event: message and parser. Every other attribute on the event is invisible to it. The value of the parser attribute names which parser to apply, and that parser is applied to the content of message. That one fact decides whether writing a parser is the right move, so settle it before you invest in authoring.
| What a sample event carries | What happens | So do this | |
|---|---|---|---|
| `parser` and `message` both present | The SDL parser runs: the parser named by parser is applied to the content of message | Author or edit /logParsers/<parser>. Normal path, continue with this skill. | |
| `message` present, `parser` absent | The SDL parser has no name to select, so nothing runs | Set a parser attribute on the event in Data Pipeline Management (DPM). Once DPM sets it, the SDL parser parses whatever is in message under that parser name. This is usually the cheapest fix and the default recommendation. | |
| Neither present | The SDL parser cannot be used at all | Parse in DPM instead. Do not author an SDL parser. | |
| Logs already parsed in DPM | Events arrive pre-parsed with their fields already promoted; no SDL parser is involved | Nothing to author here. Neither attribute needs to exist. |
An SDL parser cannot reach fields that live outside `message`. If the fields you want to transform are already promoted to top level on the event, an SDL parser is the wrong tool however it is written: it has no way to read them. That work belongs in DPM.
Determine which case a source is in by inspecting a sample event for the presence of message and parser. The PowerQuery probes for that, plus how to set the parser attribute from DPM, are in references/parser-eligibility.md.
Two hard rules (every parser, every time)
These two rules apply to every parser you write or edit, regardless of source, regardless of whether you're starting from scratch or copying from the catalog. Violating either produces a non-conformant parser even if extraction works.
Rule 1: The 4 mandatory attributes are always present.
dataSource.category is fixed at "security". Not application, not network, not system, not audit. The catalog has parsers that violate this; you do not.
metadata.version is mandatory and follows semver (MAJOR.MINOR.PATCH, with optional pre-release suffix like -rc1 or -beta1). Increment it on every build. Patch bump for fixes, minor for additive changes, major for breaking schema changes. It can also be set inside mappings via a constant op when the source itself carries a vendor schema version you'd rather propagate per-event:
A constant in mappings overrides the parser-root attributes: value when it fires, which is useful when one parser handles multiple vendor schema versions and you want each event tagged with the right one.
Rule 2: Every OCSF field name comes from `references/ocsf-schema-documentation.md`.
Before emitting any OCSF dotted path (src_endpoint.ip, actor.user.name, metadata.product.vendor_name, etc.), grep references/ocsf-schema-documentation.md for the exact string. Do not invent field names. Do not copy from a catalog parser without verifying. Do not rely on memory. The reference is the single source of truth for the ~25,759 documented OCSF field names across the 7 categories.
The rest of this skill assumes both rules are upheld. If either is unclear for a given parser, stop and resolve before continuing.
Critical pitfalls (read before authoring)
These are the DSL traps that cost the most iteration cycles when authoring parsers on the current S1 tenant. They are repeated in the long gotcha list below with more context, but if you're about to write a new parser, internalize these first. Items 1-9 are tenant-validated as of 2026-05-26; items 10-12 as of 2026-06-22.
- Key=value catch-all REQUIRES leading `.*`. The canonical form is
".*$_=identifier$=$_=quoteOrSpace$"withrepeat: true. Without the.*the format anchors at position 0 of the message and fires zero times on any line starting with a syslog priority<NNN>, a CEF header, an XML envelope, or a timestamp, i.e. virtually every real log source. The leading.*lets the engine scan forward to the firstkey=valuepair and thenrepeat: truewalks the rest. This is the same pattern the built-inkeyValueparser uses. Also: `{parse=keyValue}` is NOT a valid sub-parser directive; built-in parsers likekeyValueare only usable via root-levelaliasTo:. - v1 mappings are FIRST-MATCH-WINS, which means renames must be duplicated into every per-subtype block alongside the constants. A catch-all
predicate: "true"rename block placed at the end NEVER fires for events that matched an earlier per-subtype block, only the truly-unmatched events get those renames. If you have per-subtypeconstantblocks for OCSF class/activity fan-out (e.g.subtype=='forward'→activity_id=6), you must put the full rename list inside EACH of those blocks. Verbose but correct. - v0 constants take `field`, not `output`. A v0
constants:entry keyedoutput(the key v0renames:andcopies:use) is rejected byputFile("Expected a field", surfaced by the MCP as "Content is invalid json"). Keyedfield({ field: "class_uid", value: 4001, type: "int" }) it deploys and applies, which is the shape every marketplace v0 parser uses. Live-validated 2026-10-13; this corrects an earlier note that all v0constants:were rejected. For new parsers prefer v1 ({ constant: { field, value } }) anyway. - Same-name v1 rename silently NULLS the field (a same-name v0
renamesentry keeps the value, live-validated 2026-10-13). Writing{ rename: { from: "action", to: "action" } }to "keep" a captured raw field under its own name actually deletes the value. The KV catch-all already extracts raw vendor field names directly into the event, to "keep" one, OMIT the rename. Only write a rename when the target name is genuinely different from the source. - Unquoted numerics from `quoteOrSpace` are auto-typed as NUMBER columns. A FortiGate
srcport=44321 sentbyte=8421line going through the KV catch-all producessrcport: 44321(number),sentbyte: 8421(number), queryable withavg()/sum()/> Nwithoutnumber()wrapping. Quoted values stay as strings even if they look numeric (level="6"→ string). Caveat: SDL column type-locking still applies, so wrap numerics withnumber()in dashboard panels and STAR rule bodies if the column has ever been written as string in this tenant's history.
Two related queryability rules (not DSL traps, but they matter for any consumer of the parser):
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassedPattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingplugins/s1-secops-skills/skills/sdl-log-parser/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/sentinel-one/ai-siem/sdl-log-parser)