Skip to main content

surinort-ast

surinort-ast

Typed AST parser and analysis toolkit for Suricata/Snort rules

PyPI Version Python Versions License CI Status SARIF

GitHub Stars GitHub Issues Buy Me a Coffee


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

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.sarif from 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


Contributing

Contributions are welcome.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Support the Project

If this project is useful in your workflows, you can support development:

Buy Me A Coffee

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


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)

Source distribution for surinort-ast 4.0.0
File Size Uploaded
surinort_ast-4.0.0.tar.gz 643.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for surinort-ast 4.0.0
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

4.0.0 This release

2 release files

3.0.4

2 release files

3.0.3

2 release files

3.0.2

2 release files

3.0.1

2 release files

3.0.0

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page