aisbom-cli 0.4.1__tar.gz → 0.4.2__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.
- {aisbom_cli-0.4.1 → aisbom_cli-0.4.2}/PKG-INFO +2 -1
- {aisbom_cli-0.4.1 → aisbom_cli-0.4.2}/aisbom/cli.py +44 -0
- aisbom_cli-0.4.2/aisbom/version_check.py +50 -0
- {aisbom_cli-0.4.1 → aisbom_cli-0.4.2}/pyproject.toml +2 -1
- {aisbom_cli-0.4.1 → aisbom_cli-0.4.2}/LICENSE +0 -0
- {aisbom_cli-0.4.1 → aisbom_cli-0.4.2}/README.md +0 -0
- {aisbom_cli-0.4.1 → aisbom_cli-0.4.2}/aisbom/__init__.py +0 -0
- {aisbom_cli-0.4.1 → aisbom_cli-0.4.2}/aisbom/diff.py +0 -0
- {aisbom_cli-0.4.1 → aisbom_cli-0.4.2}/aisbom/mock_generator.py +0 -0
- {aisbom_cli-0.4.1 → aisbom_cli-0.4.2}/aisbom/remote.py +0 -0
- {aisbom_cli-0.4.1 → aisbom_cli-0.4.2}/aisbom/safety.py +0 -0
- {aisbom_cli-0.4.1 → aisbom_cli-0.4.2}/aisbom/scanner.py +0 -0
- {aisbom_cli-0.4.1 → aisbom_cli-0.4.2}/aisbom/spdx_gen.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aisbom-cli
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: An AI Supply Chain security tool that that detects Pickle bombs and generates CycloneDX SBOMs for Machine Learning models.
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Author: Ajoy L
|
|
@@ -13,6 +13,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.14
|
|
14
14
|
Requires-Dist: click (<8.2.0)
|
|
15
15
|
Requires-Dist: cyclonedx-python-lib (>=8.5.0,<9.0.0)
|
|
16
|
+
Requires-Dist: packaging (>=24.0,<25.0)
|
|
16
17
|
Requires-Dist: pip-requirements-parser (>=32.0.1,<33.0.0)
|
|
17
18
|
Requires-Dist: requests (>=2.32.3,<3.0.0)
|
|
18
19
|
Requires-Dist: rich (>=13.7.1,<15.0.0)
|
|
@@ -17,9 +17,40 @@ import importlib.metadata
|
|
|
17
17
|
from .scanner import DeepScanner
|
|
18
18
|
from .diff import SBOMDiff
|
|
19
19
|
|
|
20
|
+
import threading
|
|
21
|
+
from .version_check import check_latest_version
|
|
22
|
+
|
|
20
23
|
app = typer.Typer()
|
|
21
24
|
console = Console()
|
|
22
25
|
|
|
26
|
+
# Thread-safe storage for update checks
|
|
27
|
+
update_result = {"version": None}
|
|
28
|
+
|
|
29
|
+
def run_version_check_wrapper():
|
|
30
|
+
"""Wrapper to run version check and store result."""
|
|
31
|
+
update_result["version"] = check_latest_version()
|
|
32
|
+
|
|
33
|
+
def _check_update_status():
|
|
34
|
+
"""Checks if update thread finished and prints message if needed."""
|
|
35
|
+
# We join with a tiny timeout to see if it's done without blocking
|
|
36
|
+
# Since we call this at the END of the command, the network request likely finished.
|
|
37
|
+
# If it's still hung, we skip showing the message to avoid delay.
|
|
38
|
+
# Note: Threads in Python are daemon by default? No, we need to set daemon=True
|
|
39
|
+
# so it doesn't block exit if network hangs. But here we just want to check results.
|
|
40
|
+
if update_result["version"]:
|
|
41
|
+
ver = update_result["version"]
|
|
42
|
+
try:
|
|
43
|
+
curr = importlib.metadata.version("aisbom-cli")
|
|
44
|
+
except:
|
|
45
|
+
curr = "unknown"
|
|
46
|
+
|
|
47
|
+
console.print(Panel(
|
|
48
|
+
f"💡 [bold yellow]Update Available:[/bold yellow] You are on v{curr}. v{ver} is available.\n"
|
|
49
|
+
f"Run [bold white]pip install --upgrade aisbom-cli[/bold white] to update.",
|
|
50
|
+
border_style="yellow",
|
|
51
|
+
expand=False
|
|
52
|
+
))
|
|
53
|
+
|
|
23
54
|
class OutputFormat(str, Enum):
|
|
24
55
|
JSON = "json"
|
|
25
56
|
MARKDOWN = "markdown"
|
|
@@ -71,6 +102,10 @@ def scan(
|
|
|
71
102
|
"""
|
|
72
103
|
Deep Introspection Scan: Analyzes binary headers and dependency manifests.
|
|
73
104
|
"""
|
|
105
|
+
# Start background check
|
|
106
|
+
t = threading.Thread(target=run_version_check_wrapper, daemon=True)
|
|
107
|
+
t.start()
|
|
108
|
+
|
|
74
109
|
console.print(Panel.fit(f"🚀 [bold cyan]AIsbom[/bold cyan] Scanning: [underline]{target}[/underline]"))
|
|
75
110
|
|
|
76
111
|
# 1. Run the Logic
|
|
@@ -220,6 +255,9 @@ def scan(
|
|
|
220
255
|
elif exit_code == 1:
|
|
221
256
|
console.print("[bold yellow]Errors encountered during scan.[/bold yellow] Exiting with code 1.")
|
|
222
257
|
|
|
258
|
+
# Check update status before exiting
|
|
259
|
+
_check_update_status()
|
|
260
|
+
|
|
223
261
|
# Non-zero exit codes for CI/CD when high risk or errors are present
|
|
224
262
|
raise typer.Exit(code=exit_code)
|
|
225
263
|
|
|
@@ -293,6 +331,10 @@ def diff(
|
|
|
293
331
|
"""
|
|
294
332
|
Compare two SBOM files (CycloneDX JSON) and detect drift in risks, licenses, dependencies, or model hashes.
|
|
295
333
|
"""
|
|
334
|
+
# Start background check
|
|
335
|
+
t = threading.Thread(target=run_version_check_wrapper, daemon=True)
|
|
336
|
+
t.start()
|
|
337
|
+
|
|
296
338
|
path_old = Path(old_file)
|
|
297
339
|
path_new = Path(new_file)
|
|
298
340
|
|
|
@@ -388,6 +430,8 @@ def diff(
|
|
|
388
430
|
raise typer.Exit(code=1)
|
|
389
431
|
|
|
390
432
|
console.print("\n[bold green]Success: No critical regression detected.[/bold green]")
|
|
433
|
+
|
|
434
|
+
_check_update_status()
|
|
391
435
|
|
|
392
436
|
if __name__ == "__main__":
|
|
393
437
|
app()
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import platform
|
|
3
|
+
import importlib.metadata
|
|
4
|
+
import requests
|
|
5
|
+
from packaging.version import parse as parse_version
|
|
6
|
+
|
|
7
|
+
API_URL = "https://api.aisbom.io/v1/version"
|
|
8
|
+
|
|
9
|
+
def check_latest_version() -> str | None:
|
|
10
|
+
"""
|
|
11
|
+
Checks for the latest version of aisbom-cli.
|
|
12
|
+
Returns the latest version string if an update is available, otherwise None.
|
|
13
|
+
Respects AISBOM_NO_TELEMETRY env var.
|
|
14
|
+
"""
|
|
15
|
+
# 1. Privacy Check
|
|
16
|
+
if os.getenv("AISBOM_NO_TELEMETRY"):
|
|
17
|
+
return None
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
# 2. Get Current Version & Context
|
|
21
|
+
current_version = importlib.metadata.version("aisbom-cli")
|
|
22
|
+
system = platform.system()
|
|
23
|
+
py_ver = platform.python_version()
|
|
24
|
+
is_ci = "true" if (os.getenv("GITHUB_ACTIONS") or os.getenv("CI")) else "false"
|
|
25
|
+
|
|
26
|
+
user_agent = f"aisbom-cli/{current_version} ({system}; python {py_ver}; ci={is_ci})"
|
|
27
|
+
|
|
28
|
+
# 3. Request
|
|
29
|
+
response = requests.get(
|
|
30
|
+
API_URL,
|
|
31
|
+
headers={"User-Agent": user_agent},
|
|
32
|
+
timeout=1.0 # Strict timeout
|
|
33
|
+
)
|
|
34
|
+
response.raise_for_status()
|
|
35
|
+
|
|
36
|
+
data = response.json()
|
|
37
|
+
latest_version = data.get("latest")
|
|
38
|
+
|
|
39
|
+
if not latest_version:
|
|
40
|
+
return None
|
|
41
|
+
|
|
42
|
+
# 4. Compare
|
|
43
|
+
if parse_version(latest_version) > parse_version(current_version):
|
|
44
|
+
return latest_version
|
|
45
|
+
|
|
46
|
+
except Exception:
|
|
47
|
+
# Fail silently for any network/parsing issue
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
return None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "aisbom-cli"
|
|
3
|
-
version = "0.4.
|
|
3
|
+
version = "0.4.2"
|
|
4
4
|
description = "An AI Supply Chain security tool that that detects Pickle bombs and generates CycloneDX SBOMs for Machine Learning models."
|
|
5
5
|
authors = ["Ajoy L <lab700xdev@gmail.com>"]
|
|
6
6
|
readme = "README.md"
|
|
@@ -15,6 +15,7 @@ cyclonedx-python-lib = "^8.5.0"
|
|
|
15
15
|
pip-requirements-parser = "^32.0.1"
|
|
16
16
|
click = "<8.2.0"
|
|
17
17
|
spdx-tools = "^0.8.3"
|
|
18
|
+
packaging = "^24.0"
|
|
18
19
|
|
|
19
20
|
[tool.poetry.dependencies.requests]
|
|
20
21
|
version = "^2.32.3"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|