Fix pySigma RE2 compatibility in fresh installations
This commit is contained in:
1 parent
ff8dc9ee7a
commit
ae5a1a1e54
6 files changed
+56
-5
No files matched your search
@@ -31,6 +31,25 @@ netscaler-triage .\logs.7z
|
|||||||
|
|
||||||
Installation may require internet access. Analysis runs offline.
|
Installation may require internet access. Analysis runs offline.
|
||||||
|
|
||||||
|
### Update an existing installation
|
||||||
|
|
||||||
|
Activate the same virtual environment used to run the tool, then run from the
|
||||||
|
repository directory:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git pull
|
||||||
|
python -m pip install --upgrade .
|
||||||
|
netscaler-triage rules
|
||||||
|
```
|
||||||
|
|
||||||
|
For an environment managed by uv, use `uv sync --locked` after `git pull`.
|
||||||
|
Version 1.0.1 fixes installation failures reporting `invalid perl operator: (?=`
|
||||||
|
or `SigmaRegularExpressionError` when loading the bundled rules. pySigma 2 changed
|
||||||
|
its default validation engine to RE2, which rejects lookaheads. The package now
|
||||||
|
requires compatible pySigma 1.x; detection patterns and timed matching are
|
||||||
|
unchanged. Reinstalling with the command above also downgrades an incompatible
|
||||||
|
pySigma installation. Rerun any scan that stopped with this error.
|
||||||
|
|
||||||
## Everyday use
|
## Everyday use
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
@@ -162,3 +162,18 @@ source mapping and validation results remain outside the public release.
|
|||||||
A subsequent presentation correction exposes original-file SHA-256 matches in
|
A subsequent presentation correction exposes original-file SHA-256 matches in
|
||||||
SUMMARY.txt even without an event match. Three focused presentation tests passed,
|
SUMMARY.txt even without an event match. Three focused presentation tests passed,
|
||||||
including this separate hash-only case; Ruff, formatting and strict mypy passed.
|
including this separate hash-only case; Ruff, formatting and strict mypy passed.
|
||||||
|
|
||||||
|
DEPENDENCY COMPATIBILITY FIX — 2026-10-05
|
||||||
|
|
||||||
|
Version 1.0.0 was installed in an isolated environment with pySigma 2.0.0.
|
||||||
|
The bundled-rule validation reproduced the reported RE2 rejection of lookahead
|
||||||
|
syntax. Version 1.0.1 constrains pySigma to >=1.5.1,<2, keeping the existing
|
||||||
|
detection patterns and timeout-protected matching unchanged.
|
||||||
|
|
||||||
|
Reinstalling the corrected package in that same environment automatically
|
||||||
|
replaced pySigma 2.0.0 with 1.5.1. All 47 bundled Sigma rules validated, with
|
||||||
|
246 explicit active indicators. All 138 tests passed against the installed
|
||||||
|
package with Python warnings treated as errors. A new regression checks the
|
||||||
|
reported lookahead pattern against raw and decoded text, including negative
|
||||||
|
cases. Ruff lint, formatting and strict mypy across source and tests passed.
|
||||||
|
This verification did not rerun the complete private forensic datasets.
|
||||||
+3
-2
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "netscaler-triage"
|
name = "netscaler-triage"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
description = "Offline NetScaler evidence analysis with inspectable decoding and provenance"
|
description = "Offline NetScaler evidence analysis with inspectable decoding and provenance"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
@@ -17,7 +17,8 @@ dependencies = [
|
|||||||
"rich>=14.1",
|
"rich>=14.1",
|
||||||
"rich-argparse>=1.7",
|
"rich-argparse>=1.7",
|
||||||
"pyzipper>=0.3.6",
|
"pyzipper>=0.3.6",
|
||||||
"pysigma>=1.5.1",
|
# pySigma 2 defaults to RE2, which rejects the supported lookahead rules.
|
||||||
|
"pysigma>=1.5.1,<2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
"""Offline analysis; no discovered payload is ever executed."""
|
"""Offline analysis; no discovered payload is ever executed."""
|
||||||
|
|
||||||
__version__ = "1.0.0"
|
__version__ = "1.0.1"
|
||||||
@@ -13,6 +13,22 @@ def rule(detection: str, service: str = "") -> str:
|
|||||||
|
|
||||||
|
|
||||||
class SigmaTests(unittest.TestCase):
|
class SigmaTests(unittest.TestCase):
|
||||||
|
def test_lookahead_rule_on_raw_and_decoded_text(self) -> None:
|
||||||
|
matcher = SigmaMatcher.from_yaml(
|
||||||
|
rule(
|
||||||
|
" s:\n"
|
||||||
|
" raw|re: '(?im)^(?=.*(?:pitboss|NSPPE))"
|
||||||
|
"(?=.*(?:base64|PD9))(?=.*(?:2N|httpaccess))'\n"
|
||||||
|
" condition: s\n"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
sample = "pitboss NSPPE base64 httpaccess"
|
||||||
|
self.assertTrue(matcher.search({"raw": sample}))
|
||||||
|
hits = matcher.search_with_details({"raw": "encoded record"}, [sample])
|
||||||
|
self.assertEqual(hits[0]["basis"], ["decoded:0"])
|
||||||
|
for benign in ("pitboss NSPPE", "base64 httpaccess", "NSPPE base64"):
|
||||||
|
self.assertFalse(matcher.search({"raw": benign}))
|
||||||
|
|
||||||
def test_catalog_not_repeated_in_hit(self) -> None:
|
def test_catalog_not_repeated_in_hit(self) -> None:
|
||||||
text = rule(" s: [abc]\n condition: s\n")
|
text = rule(" s: [abc]\n condition: s\n")
|
||||||
text += "indicators:\n - type: ipv4\n value: 192.0.2.1\n status: reference_only\n"
|
text += "indicators:\n - type: ipv4\n value: 192.0.2.1\n status: reference_only\n"
|
||||||
|
|||||||
@@ -546,7 +546,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "netscaler-triage"
|
name = "netscaler-triage"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "py7zr" },
|
{ name = "py7zr" },
|
||||||
@@ -569,7 +569,7 @@ dev = [
|
|||||||
[package.metadata]
|
[package.metadata]
|
||||||
requires-dist = [
|
requires-dist = [
|
||||||
{ name = "py7zr", specifier = ">=1.0" },
|
{ name = "py7zr", specifier = ">=1.0" },
|
||||||
{ name = "pysigma", specifier = ">=1.5.1" },
|
{ name = "pysigma", specifier = ">=1.5.1,<2" },
|
||||||
{ name = "pyzipper", specifier = ">=0.3.6" },
|
{ name = "pyzipper", specifier = ">=0.3.6" },
|
||||||
{ name = "regex", specifier = ">=2025.11" },
|
{ name = "regex", specifier = ">=2025.11" },
|
||||||
{ name = "rich", specifier = ">=14.1" },
|
{ name = "rich", specifier = ">=14.1" },
|
||||||
|
|||||||
Reference in new issue
Block a user