surinort-ast
Typed AST parser and analysis toolkit for Suricata/Snort rules
Overview
surinort-ast is a Python toolkit to parse, validate, serialize, and analyze IDS/IPS rules from Suricata, Snort2, and Snort3. It provides a typed AST, CLI workflows, and machine-readable outputs including JSON and SARIF 2.1.0.
Key Features
| Feature | Description |
|---|---|
| Typed AST | Full Pydantic-backed AST for headers, options, and metadata |
| Multi-dialect | Suricata, Snort2, and Snort3 support |
| Validation | Syntax/semantic diagnostics with severity levels |
| Serialization | JSON and protobuf support |
| SARIF 2.1.0 | Parse/validate/analysis findings export for Code Scanning |
| CLI + Library | Use as command-line tool or Python package |
| Coverage/Optimization Analysis | Built-in analyzers for coverage and optimization insights |
| Streaming Mode | Memory-efficient parsing for large rule sets |
Supported Outputs
AST Data JSON, protobuf
Diagnostics Human-readable tables, SARIF 2.1.0
Analysis Text reports, SARIF 2.1.0 findings
CI Integration SARIF artifact + GitHub Code Scanning upload
Installation
From PyPI (Recommended)
pip install surinort-ast
From Source
git clone https://github.com/seifreed/surinort-ast.git
cd surinort-ast
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -e .
Optional Extras
The regular package includes the parser, CLI, analysis, and serialization
modules. Install development tooling separately with pip install -e '.[dev]'.
Quick Start
# Parse rule file
surinort parse rules/local.rules
# Validate with strict mode
surinort validate rules/local.rules --strict
# Validate several files as one ruleset
surinort validate rules/*.rules rules/vendor/*.rules
# Export parse findings to SARIF
surinort parse rules/local.rules --format sarif -o parse-results.sarif
Usage
Command Line Interface
# Parse to JSON
surinort parse rules/local.rules --json -o rules.json
# Validate and export SARIF
surinort validate rules/local.rules --format sarif -o validate-results.sarif
# Stats and coverage findings in SARIF
surinort stats rules/local.rules --format sarif -o stats-results.sarif
Available Options (Main Commands)
| Command | Description |
|---|---|
surinort parse |
Parse rules (text, json, sarif) |
surinort validate |
Validate rules with optional strict mode and SARIF output |
surinort stats |
Rule statistics and optional SARIF coverage findings |
surinort fmt |
Canonical formatting for rule files |
surinort to-json |
Convert rules to JSON |
surinort from-json |
Convert JSON back to rule text |
surinort schema |
Print AST JSON schema |
SARIF Flags
| Option | Description |
|---|---|
--format sarif |
Print SARIF content as command output |
--sarif-out <file> |
Write SARIF report while keeping default output mode |
-o, --output <file> |
Write primary output to file |
Python Library
Basic Usage
from surinort_ast import parse_rule, validate_rule, to_json
rule = parse_rule('alert tcp any any -> any 80 (msg:"HTTP"; sid:1;)')
diags = validate_rule(rule)
print(to_json(rule))
for diag in diags:
print(diag.level, diag.code, diag.message)
SARIF API Usage
from surinort_ast import (
diagnostics_to_sarif,
parse_file,
validate_rule,
)
rules = parse_file("rules/local.rules")
diagnostics = []
for rule in rules:
diagnostics.extend(validate_rule(rule))
sarif = diagnostics_to_sarif(diagnostics, default_file_path="rules/local.rules")
with open("results.sarif", "w", encoding="utf-8") as f:
f.write(sarif)
Additional SARIF Helpers
from surinort_ast import (
coverage_report_to_sarif,
optimization_results_to_sarif,
to_sarif,
)
CI and GitHub Code Scanning (SARIF)
The project CI supports SARIF generation and upload:
- Generate
results.sariffrom real validation diagnostics. - Upload SARIF as a workflow artifact.
The repository also provides a composite action for rule validation:
# Add `pull-requests: write` only when `comment` is enabled.
permissions:
contents: read
pull-requests: write
steps:
- name: Validate rules
id: surinort
uses: seifreed/surinort-ast@740b7c6c9fb74af6c927f31c0ae05e28d1d94139
with:
rules: rules/**/*.rules
dialect: suricata
engine: suricata
engine-version: 8.0.6
capability-file: conformance/capabilities/4.0.0-local.json
sarif: true
engine-verify: true
engine-command: 'suricata -T -S {file}'
baseline: .github/surinort-baseline.sarif
comment: true
Upload the generated ${{ steps.surinort.outputs.sarif-file }} with
github/codeql-action/upload-sarif when code scanning annotations are desired.
Replace the commit pin with @v4.0.0 after that public release tag exists.
- Upload SARIF to GitHub Code Scanning.
Pre-commit and GitLab CI
Use the repository hook from a pre-commit configuration:
repos:
- repo: https://github.com/seifreed/surinort-ast
rev: v4.0.0
hooks:
- id: surinort-validate
The repository also includes .gitlab-ci.yml, which validates every *.rules
file under RULES_PATH (default: rules) with the same CLI.
For editor integration, install the dependency-free client from
editors/vscode after installing this package so surinort-lsp is available.
Minimal workflow example:
- name: Generate SARIF report
run: |
python - <<'PY'
from pathlib import Path
from surinort_ast import diagnostics_to_sarif, parse_file, validate_rule
fixture_path = Path("tests/fixtures/simple_rules.txt")
rules = parse_file(fixture_path)
diagnostics = []
for rule in rules:
diagnostics.extend(validate_rule(rule))
Path("results.sarif").write_text(
diagnostics_to_sarif(diagnostics, default_file_path=str(fixture_path)),
encoding="utf-8",
)
PY
- name: Upload SARIF to GitHub Code Scanning
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
Requirements
- Python 3.11+
- See pyproject.toml for dependencies and extras
Contributing
Contributions are welcome.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Support the Project
If this project is useful in your workflows, you can support development:
License
This project is licensed under the GPL-3.0-or-later license. See LICENSE. The current licensing decision is documented in the license decision.
Attribution
- Author: Marc Rivero López | @seifreed
- Repository: github.com/seifreed/surinort-ast
Built for practical IDS/IPS rule engineering and security automation
Metadata
Release files for surinort-ast 4.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| surinort_ast-4.0.0.tar.gz | 643.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| surinort_ast-4.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 973.7 kB
Release files / surinort_ast-4.0.0.tar.gz
| Download URL | surinort_ast-4.0.0.tar.gz |
|---|---|
| Size | 643.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8929da8b581c8003658bf2a7455dd4bef247c62aa76a6871c705ead71fec06ea
|
|
BLAKE2b-256 checksum How to use checksums |
874a949635df65992e91691312abdcfc1618fc159a4ebf7e26c7dc239a117f61
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency logRelease files / surinort_ast-4.0.0-py3-none-any.whl
| Download URL | surinort_ast-4.0.0-py3-none-any.whl |
|---|---|
| Size | 330.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3358f8cdea6be7dc9ce1bae4b29029a29117b5226016f6b01e665c22ba6644e8
|
|
BLAKE2b-256 checksum How to use checksums |
82b0ac7454f1ed8c2c91b515a48e9709d6d9e1f867a1780ba3acd3cab0f70077
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency log