fourisnotrandom 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. fourisnotrandom-0.1.0/LICENSE +21 -0
  2. fourisnotrandom-0.1.0/PKG-INFO +122 -0
  3. fourisnotrandom-0.1.0/README.md +102 -0
  4. fourisnotrandom-0.1.0/pyproject.toml +37 -0
  5. fourisnotrandom-0.1.0/setup.cfg +4 -0
  6. fourisnotrandom-0.1.0/src/fourisnotrandom/__init__.py +3 -0
  7. fourisnotrandom-0.1.0/src/fourisnotrandom/__main__.py +6 -0
  8. fourisnotrandom-0.1.0/src/fourisnotrandom/checks/__init__.py +1 -0
  9. fourisnotrandom-0.1.0/src/fourisnotrandom/checks/apps.py +81 -0
  10. fourisnotrandom-0.1.0/src/fourisnotrandom/checks/emudhra.py +535 -0
  11. fourisnotrandom-0.1.0/src/fourisnotrandom/checks/gitlab.py +152 -0
  12. fourisnotrandom-0.1.0/src/fourisnotrandom/checks/litellm.py +315 -0
  13. fourisnotrandom-0.1.0/src/fourisnotrandom/checks/php.py +429 -0
  14. fourisnotrandom-0.1.0/src/fourisnotrandom/cli.py +312 -0
  15. fourisnotrandom-0.1.0/src/fourisnotrandom/config_loader.py +79 -0
  16. fourisnotrandom-0.1.0/src/fourisnotrandom/data/__init__.py +1 -0
  17. fourisnotrandom-0.1.0/src/fourisnotrandom/data/compromised_hashes.json +55 -0
  18. fourisnotrandom-0.1.0/src/fourisnotrandom/data/fixed_versions.yaml +75 -0
  19. fourisnotrandom-0.1.0/src/fourisnotrandom/data/php_apps.yaml +42 -0
  20. fourisnotrandom-0.1.0/src/fourisnotrandom/models.py +43 -0
  21. fourisnotrandom-0.1.0/src/fourisnotrandom/report.py +61 -0
  22. fourisnotrandom-0.1.0/src/fourisnotrandom/targets.py +67 -0
  23. fourisnotrandom-0.1.0/src/fourisnotrandom/versioning.py +262 -0
  24. fourisnotrandom-0.1.0/src/fourisnotrandom.egg-info/PKG-INFO +122 -0
  25. fourisnotrandom-0.1.0/src/fourisnotrandom.egg-info/SOURCES.txt +34 -0
  26. fourisnotrandom-0.1.0/src/fourisnotrandom.egg-info/dependency_links.txt +1 -0
  27. fourisnotrandom-0.1.0/src/fourisnotrandom.egg-info/entry_points.txt +2 -0
  28. fourisnotrandom-0.1.0/src/fourisnotrandom.egg-info/requires.txt +9 -0
  29. fourisnotrandom-0.1.0/src/fourisnotrandom.egg-info/top_level.txt +1 -0
  30. fourisnotrandom-0.1.0/tests/test_emudhra_match.py +52 -0
  31. fourisnotrandom-0.1.0/tests/test_gitlab_compare.py +68 -0
  32. fourisnotrandom-0.1.0/tests/test_known_cves.py +327 -0
  33. fourisnotrandom-0.1.0/tests/test_litellm_pin.py +22 -0
  34. fourisnotrandom-0.1.0/tests/test_php_compare.py +35 -0
  35. fourisnotrandom-0.1.0/tests/test_targets.py +25 -0
  36. fourisnotrandom-0.1.0/tests/test_versioning.py +46 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 FourIsNotRandom
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,122 @@
1
+ Metadata-Version: 2.4
2
+ Name: fourisnotrandom
3
+ Version: 0.1.0
4
+ Summary: Detection-only CLI that fingerprints versions/config for known CVE exposure (no exploit payloads).
5
+ Author: FourIsNotRandom
6
+ License: MIT
7
+ Keywords: cve,security,fingerprint,detection-only
8
+ Requires-Python: >=3.10
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Requires-Dist: typer>=0.12
12
+ Requires-Dist: rich>=13
13
+ Requires-Dist: PyYAML>=6
14
+ Requires-Dist: cryptography>=42
15
+ Requires-Dist: requests>=2.31
16
+ Requires-Dist: packaging>=23
17
+ Provides-Extra: dev
18
+ Requires-Dist: pytest>=8; extra == "dev"
19
+ Dynamic: license-file
20
+
21
+ # FourIsNotRandom
22
+
23
+ Detection-only CLI (`fourisnotrandom`) that fingerprints software versions and TLS/CA configuration to report exposure to a small set of currently relevant advisories.
24
+
25
+ > **This tool performs read-only version/fingerprint checks only. It does not exploit, does not send attack payloads, and must only be run against systems you own or are authorized to assess.**
26
+
27
+ ## What it checks
28
+
29
+ | Area | Advisories | Detection methods |
30
+ |------|------------|-------------------|
31
+ | PHP | CVE-2026-109618, CVE-2026-109619 | Local `php -v`/`php -i`, HTTP headers, Docker/FS manifests, webroot app stacks |
32
+ | eMudhra CA | CVE-2026-111943 / related distrust | TLS chain digests, PEM/keystore files, Docker CA bundles, Go + certifi versions |
33
+ | GitLab | CVE-2026-110264, CVE-2026-97229 | Public `/help` or `/api/v4/version` (read-only) |
34
+ | LiteLLM | Malicious `1.107.0` release | Exact pin in pip env / requirements / lockfiles / Docker |
35
+
36
+ No CIDR sweeps: every run requires an explicit host, URL, path, image name, or a targets file of discrete entries.
37
+
38
+ ## Install
39
+
40
+ ```bash
41
+ python -m pip install -U pip
42
+ pip install -e ".[dev]"
43
+ fourisnotrandom --help
44
+ ```
45
+
46
+ ### Auditing this tool's own dependencies
47
+
48
+ Run `pip-audit` against the pinned requirements file - **not** bare `pip-audit`:
49
+
50
+ ```bash
51
+ pip-audit -r requirements.txt
52
+ ```
53
+
54
+ A bare `pip-audit` run audits your entire environment and will also flag the
55
+ venv's bootstrap `pip` package, which is unrelated to this tool's dependencies.
56
+ Use `pip-audit -r requirements.txt` so findings reflect only what this project
57
+ declares.
58
+
59
+ ## Usage
60
+
61
+ ```bash
62
+ # PHP
63
+ fourisnotrandom php --local
64
+ fourisnotrandom php --local --php-bin /usr/bin/php8.3
65
+ fourisnotrandom php --url https://example.com/
66
+ fourisnotrandom php --fs /var/www/html
67
+
68
+ # eMudhra / toolchains
69
+ fourisnotrandom emudhra --host example.com
70
+ fourisnotrandom emudhra --path /etc/ssl/certs
71
+ fourisnotrandom emudhra --docker my-image:tag
72
+ fourisnotrandom emudhra --toolchains
73
+
74
+ # GitLab (both CVSS 10.0 CVEs evaluated separately)
75
+ fourisnotrandom gitlab --url https://gitlab.example.com
76
+
77
+ # LiteLLM exact compromised pin
78
+ fourisnotrandom litellm --env
79
+ fourisnotrandom litellm --path .
80
+ fourisnotrandom litellm --docker ghcr.io/berriai/litellm:v1.107.0
81
+
82
+ # Explicit target list only (global flags before the subcommand)
83
+ fourisnotrandom --format json all --targets-file targets.txt
84
+ fourisnotrandom --format json emudhra toolchains
85
+ ```
86
+
87
+ Exit codes: `0` = no FAIL, `1` = at least one FAIL, `2` = tool/config error.
88
+
89
+ ## Advisory data (editable)
90
+
91
+ Bundled under `src/fourisnotrandom/data/`:
92
+
93
+ | File | Contents | How to refresh |
94
+ |------|----------|----------------|
95
+ | `fixed_versions.yaml` | PHP floors, GitLab per-CVE floors, Go floors, certifi floor, LiteLLM pin | Edit YAML; or pass `--config PATH` |
96
+ | `compromised_hashes.json` | Compromised eMudhra intermediate digests | Replace file or `fourisnotrandom update-hashes --from PATH` |
97
+ | `php_apps.yaml` | CMS/webroot path fingerprints | Edit YAML |
98
+
99
+ ### Data provenance
100
+
101
+ - **PHP floors**: PHP project security releases (8.2.35, 8.3.36, 8.4.27, 8.5.12). Branches ≤8.1 have no upstream fix.
102
+ - **GitLab**: Official critical patch notes for CVE-2026-110264 (Oct 21) and CVE-2026-97229 (Oct 12). Both are reported separately so an Oct-12-only patch does not look “fully covered.”
103
+ - **eMudhra hashes**: Certificate SHA-256 fingerprints from Cisco Talos “Compromised eMudhra intermediate certificates” (Oct 21, 2026), citing Mozilla Bugzilla 2083449. The scanner matches **either** full-cert SHA-256 **or** SPKI SHA-256 against the configured set (Talos publishes cert fingerprints; Go’s CVE-2026-111943 fix matches SPKI - dual match avoids assuming hash type after a refresh).
104
+ - **certifi**: Floor `2026.10.18` (first release blocking compromised roots). `2026.10.19` restores some legitimate emSign roots (stability), not a security boundary.
105
+ - **Go**: Fixed in 1.27.3 / 1.26.10 (CVE-2026-111943).
106
+ - **LiteLLM**: Exact malicious PyPI/Docker release `1.107.0` only.
107
+
108
+ ```bash
109
+ # Refresh eMudhra hash list from a JSON file with the same schema
110
+ fourisnotrandom update-hashes --from ./my-hashes.json
111
+ ```
112
+
113
+ ## Safety
114
+
115
+ > **Read-only / authorized use only.** This tool fingerprints versions and TLS/CA
116
+ > material. It does not exploit, does not send attack payloads, and must only be
117
+ > run against systems you own or are authorized to assess.
118
+
119
+ - Fingerprints only: versions, headers, banners, cert digests, read-only `php.ini` values.
120
+ - Does **not** send session.upload_progress exploits, memory-corruption probes, or any PoC payloads.
121
+ - Does **not** scan networks you did not name explicitly.
122
+ - Rejects CIDR ranges and bare wildcards - every target must be an explicit host, URL, or path.
@@ -0,0 +1,102 @@
1
+ # FourIsNotRandom
2
+
3
+ Detection-only CLI (`fourisnotrandom`) that fingerprints software versions and TLS/CA configuration to report exposure to a small set of currently relevant advisories.
4
+
5
+ > **This tool performs read-only version/fingerprint checks only. It does not exploit, does not send attack payloads, and must only be run against systems you own or are authorized to assess.**
6
+
7
+ ## What it checks
8
+
9
+ | Area | Advisories | Detection methods |
10
+ |------|------------|-------------------|
11
+ | PHP | CVE-2026-109618, CVE-2026-109619 | Local `php -v`/`php -i`, HTTP headers, Docker/FS manifests, webroot app stacks |
12
+ | eMudhra CA | CVE-2026-111943 / related distrust | TLS chain digests, PEM/keystore files, Docker CA bundles, Go + certifi versions |
13
+ | GitLab | CVE-2026-110264, CVE-2026-97229 | Public `/help` or `/api/v4/version` (read-only) |
14
+ | LiteLLM | Malicious `1.107.0` release | Exact pin in pip env / requirements / lockfiles / Docker |
15
+
16
+ No CIDR sweeps: every run requires an explicit host, URL, path, image name, or a targets file of discrete entries.
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ python -m pip install -U pip
22
+ pip install -e ".[dev]"
23
+ fourisnotrandom --help
24
+ ```
25
+
26
+ ### Auditing this tool's own dependencies
27
+
28
+ Run `pip-audit` against the pinned requirements file - **not** bare `pip-audit`:
29
+
30
+ ```bash
31
+ pip-audit -r requirements.txt
32
+ ```
33
+
34
+ A bare `pip-audit` run audits your entire environment and will also flag the
35
+ venv's bootstrap `pip` package, which is unrelated to this tool's dependencies.
36
+ Use `pip-audit -r requirements.txt` so findings reflect only what this project
37
+ declares.
38
+
39
+ ## Usage
40
+
41
+ ```bash
42
+ # PHP
43
+ fourisnotrandom php --local
44
+ fourisnotrandom php --local --php-bin /usr/bin/php8.3
45
+ fourisnotrandom php --url https://example.com/
46
+ fourisnotrandom php --fs /var/www/html
47
+
48
+ # eMudhra / toolchains
49
+ fourisnotrandom emudhra --host example.com
50
+ fourisnotrandom emudhra --path /etc/ssl/certs
51
+ fourisnotrandom emudhra --docker my-image:tag
52
+ fourisnotrandom emudhra --toolchains
53
+
54
+ # GitLab (both CVSS 10.0 CVEs evaluated separately)
55
+ fourisnotrandom gitlab --url https://gitlab.example.com
56
+
57
+ # LiteLLM exact compromised pin
58
+ fourisnotrandom litellm --env
59
+ fourisnotrandom litellm --path .
60
+ fourisnotrandom litellm --docker ghcr.io/berriai/litellm:v1.107.0
61
+
62
+ # Explicit target list only (global flags before the subcommand)
63
+ fourisnotrandom --format json all --targets-file targets.txt
64
+ fourisnotrandom --format json emudhra toolchains
65
+ ```
66
+
67
+ Exit codes: `0` = no FAIL, `1` = at least one FAIL, `2` = tool/config error.
68
+
69
+ ## Advisory data (editable)
70
+
71
+ Bundled under `src/fourisnotrandom/data/`:
72
+
73
+ | File | Contents | How to refresh |
74
+ |------|----------|----------------|
75
+ | `fixed_versions.yaml` | PHP floors, GitLab per-CVE floors, Go floors, certifi floor, LiteLLM pin | Edit YAML; or pass `--config PATH` |
76
+ | `compromised_hashes.json` | Compromised eMudhra intermediate digests | Replace file or `fourisnotrandom update-hashes --from PATH` |
77
+ | `php_apps.yaml` | CMS/webroot path fingerprints | Edit YAML |
78
+
79
+ ### Data provenance
80
+
81
+ - **PHP floors**: PHP project security releases (8.2.35, 8.3.36, 8.4.27, 8.5.12). Branches ≤8.1 have no upstream fix.
82
+ - **GitLab**: Official critical patch notes for CVE-2026-110264 (Oct 21) and CVE-2026-97229 (Oct 12). Both are reported separately so an Oct-12-only patch does not look “fully covered.”
83
+ - **eMudhra hashes**: Certificate SHA-256 fingerprints from Cisco Talos “Compromised eMudhra intermediate certificates” (Oct 21, 2026), citing Mozilla Bugzilla 2083449. The scanner matches **either** full-cert SHA-256 **or** SPKI SHA-256 against the configured set (Talos publishes cert fingerprints; Go’s CVE-2026-111943 fix matches SPKI - dual match avoids assuming hash type after a refresh).
84
+ - **certifi**: Floor `2026.10.18` (first release blocking compromised roots). `2026.10.19` restores some legitimate emSign roots (stability), not a security boundary.
85
+ - **Go**: Fixed in 1.27.3 / 1.26.10 (CVE-2026-111943).
86
+ - **LiteLLM**: Exact malicious PyPI/Docker release `1.107.0` only.
87
+
88
+ ```bash
89
+ # Refresh eMudhra hash list from a JSON file with the same schema
90
+ fourisnotrandom update-hashes --from ./my-hashes.json
91
+ ```
92
+
93
+ ## Safety
94
+
95
+ > **Read-only / authorized use only.** This tool fingerprints versions and TLS/CA
96
+ > material. It does not exploit, does not send attack payloads, and must only be
97
+ > run against systems you own or are authorized to assess.
98
+
99
+ - Fingerprints only: versions, headers, banners, cert digests, read-only `php.ini` values.
100
+ - Does **not** send session.upload_progress exploits, memory-corruption probes, or any PoC payloads.
101
+ - Does **not** scan networks you did not name explicitly.
102
+ - Rejects CIDR ranges and bare wildcards - every target must be an explicit host, URL, or path.
@@ -0,0 +1,37 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "fourisnotrandom"
7
+ version = "0.1.0"
8
+ description = "Detection-only CLI that fingerprints versions/config for known CVE exposure (no exploit payloads)."
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.10"
12
+ authors = [{ name = "FourIsNotRandom" }]
13
+ keywords = ["cve", "security", "fingerprint", "detection-only"]
14
+ dependencies = [
15
+ "typer>=0.12",
16
+ "rich>=13",
17
+ "PyYAML>=6",
18
+ "cryptography>=42",
19
+ "requests>=2.31",
20
+ "packaging>=23",
21
+ ]
22
+
23
+ [project.optional-dependencies]
24
+ dev = ["pytest>=8"]
25
+
26
+ [project.scripts]
27
+ fourisnotrandom = "fourisnotrandom.cli:app"
28
+
29
+ [tool.setuptools.packages.find]
30
+ where = ["src"]
31
+
32
+ [tool.setuptools.package-data]
33
+ fourisnotrandom = ["data/*.yaml", "data/*.json"]
34
+
35
+ [tool.pytest.ini_options]
36
+ testpaths = ["tests"]
37
+ pythonpath = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+ """FourIsNotRandom: detection-only CVE exposure fingerprinting."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,6 @@
1
+ from fourisnotrandom.cli import app
2
+
3
+ if __name__ == "__main__":
4
+ # Disable Click's Windows argv glob expansion so a literal "*" is rejected
5
+ # by TargetError instead of being expanded into a directory sweep.
6
+ app(windows_expand_args=False)
@@ -0,0 +1 @@
1
+ """Detection-only check modules."""
@@ -0,0 +1,81 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ from pathlib import Path
5
+ from typing import Any
6
+
7
+ from fourisnotrandom.config_loader import load_php_apps
8
+ from fourisnotrandom.models import Finding, Status
9
+
10
+
11
+ def detect_php_apps(
12
+ root: Path,
13
+ php_version: str | None = None,
14
+ php_status: str | None = None,
15
+ apps_config: dict[str, Any] | None = None,
16
+ ) -> list[Finding]:
17
+ """Detect common PHP application stacks under a webroot (read-only)."""
18
+ cfg = apps_config or load_php_apps()
19
+ findings: list[Finding] = []
20
+ root = Path(root)
21
+
22
+ for app in cfg.get("apps", []):
23
+ name = app.get("name", "unknown")
24
+ matched = False
25
+ version_hint = ""
26
+ for marker in app.get("markers", []):
27
+ rel = marker.get("path")
28
+ if not rel:
29
+ continue
30
+ path = root / rel
31
+ if not path.is_file():
32
+ continue
33
+ try:
34
+ text = path.read_text(encoding="utf-8", errors="ignore")
35
+ except OSError:
36
+ continue
37
+ contains = marker.get("contains")
38
+ if contains and contains not in text:
39
+ continue
40
+ pattern = marker.get("pattern")
41
+ if pattern:
42
+ m = re.search(pattern, text)
43
+ if not m:
44
+ continue
45
+ version_hint = m.group(1).strip() if m.lastindex else ""
46
+ matched = True
47
+ break
48
+
49
+ if not matched:
50
+ continue
51
+
52
+ if php_status == "FAIL":
53
+ status = Status.FAIL
54
+ remediation = (
55
+ f"{name} detected on vulnerable PHP {php_version or '?'}; "
56
+ "upgrade PHP (and review app compatibility)."
57
+ )
58
+ elif php_version:
59
+ status = Status.PASS if php_status == "PASS" else Status.UNKNOWN
60
+ remediation = (
61
+ f"{name} detected; confirm PHP {php_version} is on a fixed branch."
62
+ if status != Status.PASS
63
+ else f"{name} detected; PHP version appears fixed."
64
+ )
65
+ else:
66
+ status = Status.UNKNOWN
67
+ remediation = f"{name} detected; PHP version not determined - run a PHP check."
68
+
69
+ findings.append(
70
+ Finding(
71
+ status=status,
72
+ cve="CVE-2026-109618/CVE-2026-109619",
73
+ target=str(root),
74
+ installed=f"{name}" + (f" {version_hint}" if version_hint else ""),
75
+ fixed="PHP fixed branch (see php check)",
76
+ remediation=remediation,
77
+ detail="application_stack",
78
+ extra={"app": name, "app_version": version_hint, "php_version": php_version},
79
+ )
80
+ )
81
+ return findings