jmo-security 0.3.0__tar.gz → 0.3.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.
Files changed (42) hide show
  1. {jmo_security-0.3.0 → jmo_security-0.3.2}/PKG-INFO +85 -2
  2. {jmo_security-0.3.0 → jmo_security-0.3.2}/README.md +82 -0
  3. {jmo_security-0.3.0 → jmo_security-0.3.2}/jmo_security.egg-info/PKG-INFO +85 -2
  4. jmo_security-0.3.2/jmo_security.egg-info/SOURCES.txt +39 -0
  5. {jmo_security-0.3.0 → jmo_security-0.3.2}/jmo_security.egg-info/entry_points.txt +1 -0
  6. {jmo_security-0.3.0 → jmo_security-0.3.2}/pyproject.toml +5 -2
  7. jmo_security-0.3.2/scripts/cli/__init__.py +6 -0
  8. jmo_security-0.3.2/scripts/cli/clone_from_tsv.py +182 -0
  9. jmo_security-0.3.2/scripts/cli/jmo.py +801 -0
  10. jmo_security-0.3.2/scripts/cli/jmotools.py +252 -0
  11. jmo_security-0.3.2/scripts/core/__init__.py +1 -0
  12. jmo_security-0.3.2/scripts/core/adapters/__init__.py +1 -0
  13. jmo_security-0.3.2/scripts/core/adapters/bandit_adapter.py +80 -0
  14. jmo_security-0.3.2/scripts/core/adapters/checkov_adapter.py +68 -0
  15. jmo_security-0.3.2/scripts/core/adapters/gitleaks_adapter.py +80 -0
  16. jmo_security-0.3.2/scripts/core/adapters/hadolint_adapter.py +54 -0
  17. jmo_security-0.3.2/scripts/core/adapters/noseyparker_adapter.py +62 -0
  18. jmo_security-0.3.2/scripts/core/adapters/osv_adapter.py +91 -0
  19. jmo_security-0.3.2/scripts/core/adapters/semgrep_adapter.py +73 -0
  20. jmo_security-0.3.2/scripts/core/adapters/syft_adapter.py +102 -0
  21. jmo_security-0.3.2/scripts/core/adapters/tfsec_adapter.py +56 -0
  22. jmo_security-0.3.2/scripts/core/adapters/trivy_adapter.py +62 -0
  23. jmo_security-0.3.2/scripts/core/adapters/trufflehog_adapter.py +103 -0
  24. jmo_security-0.3.2/scripts/core/common_finding.py +41 -0
  25. jmo_security-0.3.2/scripts/core/config.py +78 -0
  26. jmo_security-0.3.2/scripts/core/generate_dashboard.py +620 -0
  27. jmo_security-0.3.2/scripts/core/normalize_and_report.py +236 -0
  28. jmo_security-0.3.2/scripts/core/reporters/__init__.py +1 -0
  29. jmo_security-0.3.2/scripts/core/reporters/basic_reporter.py +45 -0
  30. jmo_security-0.3.2/scripts/core/reporters/html_reporter.py +266 -0
  31. jmo_security-0.3.2/scripts/core/reporters/sarif_reporter.py +64 -0
  32. jmo_security-0.3.2/scripts/core/reporters/suppression_reporter.py +27 -0
  33. jmo_security-0.3.2/scripts/core/reporters/yaml_reporter.py +18 -0
  34. jmo_security-0.3.2/scripts/core/schema_utils.py +36 -0
  35. jmo_security-0.3.2/scripts/core/suppress.py +56 -0
  36. jmo_security-0.3.0/jmo_security.egg-info/SOURCES.txt +0 -10
  37. {jmo_security-0.3.0 → jmo_security-0.3.2}/LICENSE +0 -0
  38. {jmo_security-0.3.0 → jmo_security-0.3.2}/jmo_security.egg-info/dependency_links.txt +0 -0
  39. {jmo_security-0.3.0 → jmo_security-0.3.2}/jmo_security.egg-info/requires.txt +0 -0
  40. {jmo_security-0.3.0 → jmo_security-0.3.2}/jmo_security.egg-info/top_level.txt +0 -0
  41. {jmo_security-0.3.0 → jmo_security-0.3.2}/scripts/__init__.py +0 -0
  42. {jmo_security-0.3.0 → jmo_security-0.3.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: jmo-security
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: JMo Security Audit Suite (terminal-first, multi-tool, unified outputs)
5
5
  Author-email: James Moceri <general@jmogaming.com>
6
6
  License: MIT
@@ -13,6 +13,7 @@ License-File: LICENSE
13
13
  Provides-Extra: reporting
14
14
  Requires-Dist: PyYAML>=6.0; extra == "reporting"
15
15
  Requires-Dist: jsonschema>=4.0; extra == "reporting"
16
+ Dynamic: license-file
16
17
 
17
18
  # JMo's Security Audit Tool Suite
18
19
 
@@ -20,14 +21,77 @@ Requires-Dist: jsonschema>=4.0; extra == "reporting"
20
21
  <img src="assets/jmo-logo.png" alt="JMo Security Audit Tool Suite" width="220" />
21
22
  </p>
22
23
 
24
+ [![Tests](https://github.com/jimmy058910/jmo-security-repo/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/jimmy058910/jmo-security-repo/actions/workflows/tests.yml?query=branch%3Amain)
25
+ [![Website](https://img.shields.io/website?url=https%3A%2F%2Fjmotools.com)](https://jmotools.com)
26
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
27
+ [![Python](https://img.shields.io/badge/Python-%E2%89%A53.8-3776AB?logo=python&logoColor=white)](#)
28
+ [![Contributions welcome](https://img.shields.io/badge/Contributions-welcome-brightgreen.svg)](https://github.com/jimmy058910/jmo-security-repo/issues)
29
+ [![Buy me an energy drink](https://img.shields.io/badge/Buy%20me%20an-energy%20drink-%23ff4d00)](https://ko-fi.com/jmogaming)
30
+
31
+ <!-- CI/coverage/package badges (enable once configured)
32
+ [![CI](https://img.shields.io/badge/CI-GitHub%20Actions-coming--soon-lightgrey)](#)
33
+ <!-- If/when a workflow exists, switch to:
23
34
  [![Tests](https://github.com/jimmy058910/jmo-security-repo/actions/workflows/tests.yml/badge.svg)](https://github.com/jimmy058910/jmo-security-repo/actions/workflows/tests.yml)
35
+ -->
36
+ <!-- Codecov (enable after uploading coverage):
24
37
  [![codecov](https://codecov.io/gh/jimmy058910/jmo-security-repo/branch/main/graph/badge.svg)](https://codecov.io/gh/jimmy058910/jmo-security-repo)
38
+ -->
39
+ <!-- PyPI (enable after first release):
25
40
  [![PyPI - Version](https://img.shields.io/pypi/v/jmo-security)](https://pypi.org/project/jmo-security/)
41
+ -->
26
42
 
27
43
  A terminal-first, cross-platform security audit toolkit that orchestrates multiple scanners (secrets, SAST, SBOM, IaC, Dockerfile) with a unified Python CLI, normalized outputs, and an HTML dashboard.
28
44
 
29
45
  👉 New here? Read the comprehensive User Guide: [docs/USER_GUIDE.md](docs/USER_GUIDE.md)
30
46
  Docs hub: [docs/index.md](docs/index.md)
47
+ Project homepage: [jmotools.com](https://jmotools.com)
48
+
49
+ > Origin story: This started as part of a Cybersecurity Capstone Project. It has since grown into a general-purpose toolkit. I’d love for folks with deeper expertise to jump in—issues and PRs are welcome!
50
+
51
+ Thinking about contributing? See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, coding standards, and release steps.
52
+
53
+ Roadmap & history:
54
+ - Completed steps (summary): see [RELEASE_NOTES.md](RELEASE_NOTES.md) → “Roadmap Summary (Steps 1–13)”
55
+ - Active/planned work: see [ROADMAP.md](ROADMAP.md)
56
+
57
+ For scanning a list of repos from a TSV end-to-end (clone + unshallow + full toolchain), see: [docs/examples/scan_from_tsv.md](docs/examples/scan_from_tsv.md)
58
+
59
+ ## 🧪 New: Simple wrapper commands
60
+
61
+ If you're just getting started, use the beginner-friendly wrapper:
62
+
63
+ - `jmotools fast` — quick scan (fast profile)
64
+ - `jmotools balanced` — default balanced scan
65
+ - `jmotools full` — deep scan with more tools
66
+
67
+ Examples:
68
+
69
+ ```bash
70
+ # Fast profile over repos listed in a TSV (auto-clone) and open dashboard when done
71
+ jmotools fast --tsv ai-search/candidates.tsv --dest ./repos-tsv
72
+
73
+ # Full (deep) profile targeting an existing directory of repos
74
+ jmotools full --repos-dir ./repos-tsv --allow-missing-tools
75
+ ```
76
+
77
+ Under the hood, these commands verify your OS/tools, optionally clone from a TSV, run `jmo ci` with the appropriate profile, and open `dashboard.html` and `SUMMARY.md` on completion.
78
+
79
+ Setup tools quickly:
80
+
81
+ ```bash
82
+ # Check tools or auto-install on Linux/WSL (where supported)
83
+ jmotools setup --check
84
+ jmotools setup --auto-install # or --print-commands, --force-reinstall
85
+ ```
86
+
87
+ Makefile shortcuts:
88
+
89
+ ```bash
90
+ make setup # jmotools setup --check (installs package if needed)
91
+ make fast DIR=~/repos # jmotools fast --repos-dir ~/repos
92
+ make balanced DIR=~/repos
93
+ make full DIR=~/repos
94
+ ```
31
95
 
32
96
  ## 🎯 Overview
33
97
 
@@ -55,6 +119,12 @@ make verify-env # check OS/WSL/macOS and tool availability
55
119
  make dev-deps # install Python dev dependencies
56
120
  ```
57
121
 
122
+ Optional: install the package locally to get `jmo` and `jmotools` commands on your PATH:
123
+
124
+ ```bash
125
+ pip install -e .
126
+ ```
127
+
58
128
  ### Quick Start (Unified CLI)
59
129
 
60
130
  1) Verify your environment (Linux/WSL/macOS) and see install hints for optional tools:
@@ -76,7 +146,10 @@ make dev-deps
76
146
  python3 scripts/cli/jmo.py scan --repos-dir ~/repos --profile-name balanced --human-logs
77
147
 
78
148
  # Aggregate and write unified outputs to results/summaries
149
+ # (positional or --results-dir are both accepted)
79
150
  python3 scripts/cli/jmo.py report ./results --profile --human-logs
151
+ # or
152
+ python3 scripts/cli/jmo.py report --results-dir ./results --profile --human-logs
80
153
 
81
154
  # Or do both in one step for CI with a failure threshold
82
155
  python3 scripts/cli/jmo.py ci --repos-dir ~/repos --profile-name fast --fail-on HIGH --profile --human-logs
@@ -128,6 +201,8 @@ cat ~/security-results-*/SUMMARY_REPORT.md
128
201
  # Linux: xdg-open ~/security-results-*/dashboard.html
129
202
  ```
130
203
 
204
+ Looking for screenshots and how to capture them? See: [docs/screenshots/README.md](docs/screenshots/README.md)
205
+
131
206
  ## 📚 Documentation
132
207
 
133
208
  ### Workflow (at a glance)
@@ -559,6 +634,14 @@ The HTML dashboard provides:
559
634
 
560
635
  Contributions are welcome! Please feel free to submit pull requests or open issues for bugs and feature requests.
561
636
 
637
+ ## ❤️ Support
638
+
639
+ If this toolkit saves you time, consider fueling development with an energy drink.
640
+
641
+ - Prefer one-time tips? Ko‑fi: https://ko-fi.com/jmogaming
642
+ - When you’re ready, replace the badge target with your preferred platform: GitHub Sponsors (industry standard), Open Collective, Ko-fi, or Stripe Checkout.
643
+ - GitHub Sponsors integrates directly with your GitHub profile and repository sidebar once enabled.
644
+
562
645
  ## 📝 License
563
646
 
564
647
  MIT License. See LICENSE.
@@ -4,14 +4,77 @@
4
4
  <img src="assets/jmo-logo.png" alt="JMo Security Audit Tool Suite" width="220" />
5
5
  </p>
6
6
 
7
+ [![Tests](https://github.com/jimmy058910/jmo-security-repo/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/jimmy058910/jmo-security-repo/actions/workflows/tests.yml?query=branch%3Amain)
8
+ [![Website](https://img.shields.io/website?url=https%3A%2F%2Fjmotools.com)](https://jmotools.com)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
10
+ [![Python](https://img.shields.io/badge/Python-%E2%89%A53.8-3776AB?logo=python&logoColor=white)](#)
11
+ [![Contributions welcome](https://img.shields.io/badge/Contributions-welcome-brightgreen.svg)](https://github.com/jimmy058910/jmo-security-repo/issues)
12
+ [![Buy me an energy drink](https://img.shields.io/badge/Buy%20me%20an-energy%20drink-%23ff4d00)](https://ko-fi.com/jmogaming)
13
+
14
+ <!-- CI/coverage/package badges (enable once configured)
15
+ [![CI](https://img.shields.io/badge/CI-GitHub%20Actions-coming--soon-lightgrey)](#)
16
+ <!-- If/when a workflow exists, switch to:
7
17
  [![Tests](https://github.com/jimmy058910/jmo-security-repo/actions/workflows/tests.yml/badge.svg)](https://github.com/jimmy058910/jmo-security-repo/actions/workflows/tests.yml)
18
+ -->
19
+ <!-- Codecov (enable after uploading coverage):
8
20
  [![codecov](https://codecov.io/gh/jimmy058910/jmo-security-repo/branch/main/graph/badge.svg)](https://codecov.io/gh/jimmy058910/jmo-security-repo)
21
+ -->
22
+ <!-- PyPI (enable after first release):
9
23
  [![PyPI - Version](https://img.shields.io/pypi/v/jmo-security)](https://pypi.org/project/jmo-security/)
24
+ -->
10
25
 
11
26
  A terminal-first, cross-platform security audit toolkit that orchestrates multiple scanners (secrets, SAST, SBOM, IaC, Dockerfile) with a unified Python CLI, normalized outputs, and an HTML dashboard.
12
27
 
13
28
  👉 New here? Read the comprehensive User Guide: [docs/USER_GUIDE.md](docs/USER_GUIDE.md)
14
29
  Docs hub: [docs/index.md](docs/index.md)
30
+ Project homepage: [jmotools.com](https://jmotools.com)
31
+
32
+ > Origin story: This started as part of a Cybersecurity Capstone Project. It has since grown into a general-purpose toolkit. I’d love for folks with deeper expertise to jump in—issues and PRs are welcome!
33
+
34
+ Thinking about contributing? See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, coding standards, and release steps.
35
+
36
+ Roadmap & history:
37
+ - Completed steps (summary): see [RELEASE_NOTES.md](RELEASE_NOTES.md) → “Roadmap Summary (Steps 1–13)”
38
+ - Active/planned work: see [ROADMAP.md](ROADMAP.md)
39
+
40
+ For scanning a list of repos from a TSV end-to-end (clone + unshallow + full toolchain), see: [docs/examples/scan_from_tsv.md](docs/examples/scan_from_tsv.md)
41
+
42
+ ## 🧪 New: Simple wrapper commands
43
+
44
+ If you're just getting started, use the beginner-friendly wrapper:
45
+
46
+ - `jmotools fast` — quick scan (fast profile)
47
+ - `jmotools balanced` — default balanced scan
48
+ - `jmotools full` — deep scan with more tools
49
+
50
+ Examples:
51
+
52
+ ```bash
53
+ # Fast profile over repos listed in a TSV (auto-clone) and open dashboard when done
54
+ jmotools fast --tsv ai-search/candidates.tsv --dest ./repos-tsv
55
+
56
+ # Full (deep) profile targeting an existing directory of repos
57
+ jmotools full --repos-dir ./repos-tsv --allow-missing-tools
58
+ ```
59
+
60
+ Under the hood, these commands verify your OS/tools, optionally clone from a TSV, run `jmo ci` with the appropriate profile, and open `dashboard.html` and `SUMMARY.md` on completion.
61
+
62
+ Setup tools quickly:
63
+
64
+ ```bash
65
+ # Check tools or auto-install on Linux/WSL (where supported)
66
+ jmotools setup --check
67
+ jmotools setup --auto-install # or --print-commands, --force-reinstall
68
+ ```
69
+
70
+ Makefile shortcuts:
71
+
72
+ ```bash
73
+ make setup # jmotools setup --check (installs package if needed)
74
+ make fast DIR=~/repos # jmotools fast --repos-dir ~/repos
75
+ make balanced DIR=~/repos
76
+ make full DIR=~/repos
77
+ ```
15
78
 
16
79
  ## 🎯 Overview
17
80
 
@@ -39,6 +102,12 @@ make verify-env # check OS/WSL/macOS and tool availability
39
102
  make dev-deps # install Python dev dependencies
40
103
  ```
41
104
 
105
+ Optional: install the package locally to get `jmo` and `jmotools` commands on your PATH:
106
+
107
+ ```bash
108
+ pip install -e .
109
+ ```
110
+
42
111
  ### Quick Start (Unified CLI)
43
112
 
44
113
  1) Verify your environment (Linux/WSL/macOS) and see install hints for optional tools:
@@ -60,7 +129,10 @@ make dev-deps
60
129
  python3 scripts/cli/jmo.py scan --repos-dir ~/repos --profile-name balanced --human-logs
61
130
 
62
131
  # Aggregate and write unified outputs to results/summaries
132
+ # (positional or --results-dir are both accepted)
63
133
  python3 scripts/cli/jmo.py report ./results --profile --human-logs
134
+ # or
135
+ python3 scripts/cli/jmo.py report --results-dir ./results --profile --human-logs
64
136
 
65
137
  # Or do both in one step for CI with a failure threshold
66
138
  python3 scripts/cli/jmo.py ci --repos-dir ~/repos --profile-name fast --fail-on HIGH --profile --human-logs
@@ -112,6 +184,8 @@ cat ~/security-results-*/SUMMARY_REPORT.md
112
184
  # Linux: xdg-open ~/security-results-*/dashboard.html
113
185
  ```
114
186
 
187
+ Looking for screenshots and how to capture them? See: [docs/screenshots/README.md](docs/screenshots/README.md)
188
+
115
189
  ## 📚 Documentation
116
190
 
117
191
  ### Workflow (at a glance)
@@ -543,6 +617,14 @@ The HTML dashboard provides:
543
617
 
544
618
  Contributions are welcome! Please feel free to submit pull requests or open issues for bugs and feature requests.
545
619
 
620
+ ## ❤️ Support
621
+
622
+ If this toolkit saves you time, consider fueling development with an energy drink.
623
+
624
+ - Prefer one-time tips? Ko‑fi: https://ko-fi.com/jmogaming
625
+ - When you’re ready, replace the badge target with your preferred platform: GitHub Sponsors (industry standard), Open Collective, Ko-fi, or Stripe Checkout.
626
+ - GitHub Sponsors integrates directly with your GitHub profile and repository sidebar once enabled.
627
+
546
628
  ## 📝 License
547
629
 
548
630
  MIT License. See LICENSE.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: jmo-security
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: JMo Security Audit Suite (terminal-first, multi-tool, unified outputs)
5
5
  Author-email: James Moceri <general@jmogaming.com>
6
6
  License: MIT
@@ -13,6 +13,7 @@ License-File: LICENSE
13
13
  Provides-Extra: reporting
14
14
  Requires-Dist: PyYAML>=6.0; extra == "reporting"
15
15
  Requires-Dist: jsonschema>=4.0; extra == "reporting"
16
+ Dynamic: license-file
16
17
 
17
18
  # JMo's Security Audit Tool Suite
18
19
 
@@ -20,14 +21,77 @@ Requires-Dist: jsonschema>=4.0; extra == "reporting"
20
21
  <img src="assets/jmo-logo.png" alt="JMo Security Audit Tool Suite" width="220" />
21
22
  </p>
22
23
 
24
+ [![Tests](https://github.com/jimmy058910/jmo-security-repo/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/jimmy058910/jmo-security-repo/actions/workflows/tests.yml?query=branch%3Amain)
25
+ [![Website](https://img.shields.io/website?url=https%3A%2F%2Fjmotools.com)](https://jmotools.com)
26
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
27
+ [![Python](https://img.shields.io/badge/Python-%E2%89%A53.8-3776AB?logo=python&logoColor=white)](#)
28
+ [![Contributions welcome](https://img.shields.io/badge/Contributions-welcome-brightgreen.svg)](https://github.com/jimmy058910/jmo-security-repo/issues)
29
+ [![Buy me an energy drink](https://img.shields.io/badge/Buy%20me%20an-energy%20drink-%23ff4d00)](https://ko-fi.com/jmogaming)
30
+
31
+ <!-- CI/coverage/package badges (enable once configured)
32
+ [![CI](https://img.shields.io/badge/CI-GitHub%20Actions-coming--soon-lightgrey)](#)
33
+ <!-- If/when a workflow exists, switch to:
23
34
  [![Tests](https://github.com/jimmy058910/jmo-security-repo/actions/workflows/tests.yml/badge.svg)](https://github.com/jimmy058910/jmo-security-repo/actions/workflows/tests.yml)
35
+ -->
36
+ <!-- Codecov (enable after uploading coverage):
24
37
  [![codecov](https://codecov.io/gh/jimmy058910/jmo-security-repo/branch/main/graph/badge.svg)](https://codecov.io/gh/jimmy058910/jmo-security-repo)
38
+ -->
39
+ <!-- PyPI (enable after first release):
25
40
  [![PyPI - Version](https://img.shields.io/pypi/v/jmo-security)](https://pypi.org/project/jmo-security/)
41
+ -->
26
42
 
27
43
  A terminal-first, cross-platform security audit toolkit that orchestrates multiple scanners (secrets, SAST, SBOM, IaC, Dockerfile) with a unified Python CLI, normalized outputs, and an HTML dashboard.
28
44
 
29
45
  👉 New here? Read the comprehensive User Guide: [docs/USER_GUIDE.md](docs/USER_GUIDE.md)
30
46
  Docs hub: [docs/index.md](docs/index.md)
47
+ Project homepage: [jmotools.com](https://jmotools.com)
48
+
49
+ > Origin story: This started as part of a Cybersecurity Capstone Project. It has since grown into a general-purpose toolkit. I’d love for folks with deeper expertise to jump in—issues and PRs are welcome!
50
+
51
+ Thinking about contributing? See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, coding standards, and release steps.
52
+
53
+ Roadmap & history:
54
+ - Completed steps (summary): see [RELEASE_NOTES.md](RELEASE_NOTES.md) → “Roadmap Summary (Steps 1–13)”
55
+ - Active/planned work: see [ROADMAP.md](ROADMAP.md)
56
+
57
+ For scanning a list of repos from a TSV end-to-end (clone + unshallow + full toolchain), see: [docs/examples/scan_from_tsv.md](docs/examples/scan_from_tsv.md)
58
+
59
+ ## 🧪 New: Simple wrapper commands
60
+
61
+ If you're just getting started, use the beginner-friendly wrapper:
62
+
63
+ - `jmotools fast` — quick scan (fast profile)
64
+ - `jmotools balanced` — default balanced scan
65
+ - `jmotools full` — deep scan with more tools
66
+
67
+ Examples:
68
+
69
+ ```bash
70
+ # Fast profile over repos listed in a TSV (auto-clone) and open dashboard when done
71
+ jmotools fast --tsv ai-search/candidates.tsv --dest ./repos-tsv
72
+
73
+ # Full (deep) profile targeting an existing directory of repos
74
+ jmotools full --repos-dir ./repos-tsv --allow-missing-tools
75
+ ```
76
+
77
+ Under the hood, these commands verify your OS/tools, optionally clone from a TSV, run `jmo ci` with the appropriate profile, and open `dashboard.html` and `SUMMARY.md` on completion.
78
+
79
+ Setup tools quickly:
80
+
81
+ ```bash
82
+ # Check tools or auto-install on Linux/WSL (where supported)
83
+ jmotools setup --check
84
+ jmotools setup --auto-install # or --print-commands, --force-reinstall
85
+ ```
86
+
87
+ Makefile shortcuts:
88
+
89
+ ```bash
90
+ make setup # jmotools setup --check (installs package if needed)
91
+ make fast DIR=~/repos # jmotools fast --repos-dir ~/repos
92
+ make balanced DIR=~/repos
93
+ make full DIR=~/repos
94
+ ```
31
95
 
32
96
  ## 🎯 Overview
33
97
 
@@ -55,6 +119,12 @@ make verify-env # check OS/WSL/macOS and tool availability
55
119
  make dev-deps # install Python dev dependencies
56
120
  ```
57
121
 
122
+ Optional: install the package locally to get `jmo` and `jmotools` commands on your PATH:
123
+
124
+ ```bash
125
+ pip install -e .
126
+ ```
127
+
58
128
  ### Quick Start (Unified CLI)
59
129
 
60
130
  1) Verify your environment (Linux/WSL/macOS) and see install hints for optional tools:
@@ -76,7 +146,10 @@ make dev-deps
76
146
  python3 scripts/cli/jmo.py scan --repos-dir ~/repos --profile-name balanced --human-logs
77
147
 
78
148
  # Aggregate and write unified outputs to results/summaries
149
+ # (positional or --results-dir are both accepted)
79
150
  python3 scripts/cli/jmo.py report ./results --profile --human-logs
151
+ # or
152
+ python3 scripts/cli/jmo.py report --results-dir ./results --profile --human-logs
80
153
 
81
154
  # Or do both in one step for CI with a failure threshold
82
155
  python3 scripts/cli/jmo.py ci --repos-dir ~/repos --profile-name fast --fail-on HIGH --profile --human-logs
@@ -128,6 +201,8 @@ cat ~/security-results-*/SUMMARY_REPORT.md
128
201
  # Linux: xdg-open ~/security-results-*/dashboard.html
129
202
  ```
130
203
 
204
+ Looking for screenshots and how to capture them? See: [docs/screenshots/README.md](docs/screenshots/README.md)
205
+
131
206
  ## 📚 Documentation
132
207
 
133
208
  ### Workflow (at a glance)
@@ -559,6 +634,14 @@ The HTML dashboard provides:
559
634
 
560
635
  Contributions are welcome! Please feel free to submit pull requests or open issues for bugs and feature requests.
561
636
 
637
+ ## ❤️ Support
638
+
639
+ If this toolkit saves you time, consider fueling development with an energy drink.
640
+
641
+ - Prefer one-time tips? Ko‑fi: https://ko-fi.com/jmogaming
642
+ - When you’re ready, replace the badge target with your preferred platform: GitHub Sponsors (industry standard), Open Collective, Ko-fi, or Stripe Checkout.
643
+ - GitHub Sponsors integrates directly with your GitHub profile and repository sidebar once enabled.
644
+
562
645
  ## 📝 License
563
646
 
564
647
  MIT License. See LICENSE.
@@ -0,0 +1,39 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ jmo_security.egg-info/PKG-INFO
5
+ jmo_security.egg-info/SOURCES.txt
6
+ jmo_security.egg-info/dependency_links.txt
7
+ jmo_security.egg-info/entry_points.txt
8
+ jmo_security.egg-info/requires.txt
9
+ jmo_security.egg-info/top_level.txt
10
+ scripts/__init__.py
11
+ scripts/cli/__init__.py
12
+ scripts/cli/clone_from_tsv.py
13
+ scripts/cli/jmo.py
14
+ scripts/cli/jmotools.py
15
+ scripts/core/__init__.py
16
+ scripts/core/common_finding.py
17
+ scripts/core/config.py
18
+ scripts/core/generate_dashboard.py
19
+ scripts/core/normalize_and_report.py
20
+ scripts/core/schema_utils.py
21
+ scripts/core/suppress.py
22
+ scripts/core/adapters/__init__.py
23
+ scripts/core/adapters/bandit_adapter.py
24
+ scripts/core/adapters/checkov_adapter.py
25
+ scripts/core/adapters/gitleaks_adapter.py
26
+ scripts/core/adapters/hadolint_adapter.py
27
+ scripts/core/adapters/noseyparker_adapter.py
28
+ scripts/core/adapters/osv_adapter.py
29
+ scripts/core/adapters/semgrep_adapter.py
30
+ scripts/core/adapters/syft_adapter.py
31
+ scripts/core/adapters/tfsec_adapter.py
32
+ scripts/core/adapters/trivy_adapter.py
33
+ scripts/core/adapters/trufflehog_adapter.py
34
+ scripts/core/reporters/__init__.py
35
+ scripts/core/reporters/basic_reporter.py
36
+ scripts/core/reporters/html_reporter.py
37
+ scripts/core/reporters/sarif_reporter.py
38
+ scripts/core/reporters/suppression_reporter.py
39
+ scripts/core/reporters/yaml_reporter.py
@@ -1,2 +1,3 @@
1
1
  [console_scripts]
2
2
  jmo = scripts.cli.jmo:main
3
+ jmotools = scripts.cli.jmotools:main
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "jmo-security"
7
- version = "0.3.0"
7
+ version = "0.3.2"
8
8
  description = "JMo Security Audit Suite (terminal-first, multi-tool, unified outputs)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -22,7 +22,10 @@ reporting = ["PyYAML>=6.0", "jsonschema>=4.0"]
22
22
 
23
23
  [project.scripts]
24
24
  jmo = "scripts.cli.jmo:main"
25
+ jmotools = "scripts.cli.jmotools:main"
25
26
 
26
27
  [tool.setuptools]
27
- packages = ["scripts"]
28
28
  include-package-data = true
29
+
30
+ [tool.setuptools.packages.find]
31
+ include = ["scripts*"]
@@ -0,0 +1,6 @@
1
+ """CLI package for jmo-security.
2
+
3
+ This file ensures setuptools treats `scripts/cli` as a proper Python package
4
+ so that the console entry point `jmo = scripts.cli.jmo:main` resolves correctly
5
+ when installed from PyPI.
6
+ """
@@ -0,0 +1,182 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Clone repositories listed in a TSV and emit a targets file for jmo scan.
4
+
5
+ Inputs
6
+ - --tsv: Path to a TSV file with a header containing either 'url' or 'full_name' columns.
7
+ Example header: full_name url stars language description created_at updated_at matched_by
8
+ Rows may have blank description; this script only cares about url/full_name.
9
+
10
+ Outputs
11
+ - Clones repos under --dest (default: ./repos-tsv/<owner>/<repo>)
12
+ - Writes a newline-delimited list of absolute repo paths to --targets-out (default: results/targets.tsv.txt)
13
+
14
+ Behavior
15
+ - If a repo already exists, perform a fetch and ensure it is not shallow ("unshallowed")
16
+ - Prefer the 'url' column when present; otherwise construct https://github.com/<full_name>.git
17
+ - Limits cloning to --max (default: all)
18
+ """
19
+ from __future__ import annotations
20
+
21
+ import argparse
22
+ import csv
23
+ import subprocess
24
+ import sys
25
+ from pathlib import Path
26
+ from typing import List, Optional, Tuple
27
+
28
+
29
+ def log(msg: str, level: str = "INFO", human: bool = True) -> None:
30
+ level = level.upper()
31
+ if human:
32
+ color = {"DEBUG": "\x1b[36m", "INFO": "\x1b[32m", "WARN": "\x1b[33m", "ERROR": "\x1b[31m"}.get(level, "")
33
+ reset = "\x1b[0m"
34
+ sys.stderr.write(f"{color}{level:5}{reset} {msg}\n")
35
+ else:
36
+ import json
37
+ import datetime
38
+ rec = {"ts": datetime.datetime.utcnow().isoformat() + "Z", "level": level, "msg": msg}
39
+ sys.stderr.write(json.dumps(rec) + "\n")
40
+
41
+
42
+ def run(cmd: List[str], cwd: Optional[Path] = None, ok_rcs: Tuple[int, ...] = (0,)) -> Tuple[int, str, str]:
43
+ try:
44
+ cp = subprocess.run(
45
+ cmd,
46
+ cwd=str(cwd) if cwd else None,
47
+ stdout=subprocess.PIPE,
48
+ stderr=subprocess.PIPE,
49
+ text=True,
50
+ check=False,
51
+ )
52
+ rc = cp.returncode
53
+ if rc not in ok_rcs:
54
+ return rc, cp.stdout or "", cp.stderr or ""
55
+ return rc, cp.stdout or "", cp.stderr or ""
56
+ except FileNotFoundError as e:
57
+ return 127, "", str(e)
58
+
59
+
60
+ def ensure_unshallowed(repo_dir: Path) -> None:
61
+ # Determine if shallow and unshallow if needed
62
+ rc, out, err = run(["git", "rev-parse", "--is-shallow-repository"], cwd=repo_dir)
63
+ if rc != 0:
64
+ log(f"git rev-parse failed for {repo_dir.name}: {err.strip()}", "WARN")
65
+ return
66
+ shallow = (out.strip().lower() == "true")
67
+ if shallow:
68
+ # Attempt to unshallow
69
+ rc, _, err = run(["git", "fetch", "--unshallow"], cwd=repo_dir)
70
+ if rc != 0:
71
+ # Some setups require specifying the remote; try origin
72
+ rc2, _, err2 = run(["git", "fetch", "origin", "--unshallow"], cwd=repo_dir)
73
+ if rc2 != 0:
74
+ log(f"Failed to unshallow {repo_dir.name}: {err.strip() or err2.strip()}", "WARN")
75
+ # Also fetch tags/prune to be thorough
76
+ run(["git", "fetch", "--all", "--tags", "--prune"], cwd=repo_dir)
77
+
78
+
79
+ def clone_or_update(url: str, dest_root: Path) -> Optional[Path]:
80
+ # Derive a stable folder path like <dest_root>/<owner>/<repo>
81
+ try:
82
+ # Strip trailing .git for folder naming
83
+ stem = url.split("//", 1)[-1]
84
+ # stem like github.com/owner/repo(.git)
85
+ parts = stem.split("/")
86
+ owner, repo = parts[-2], parts[-1]
87
+ if repo.endswith(".git"):
88
+ repo = repo[:-4]
89
+ except Exception:
90
+ owner, repo = "misc", url.replace("://", "_").replace("/", "-")
91
+ target = dest_root / owner / repo
92
+ target.parent.mkdir(parents=True, exist_ok=True)
93
+ if target.exists():
94
+ log(f"Updating existing repo {owner}/{repo}")
95
+ rc, _, err = run(["git", "remote", "-v"], cwd=target)
96
+ if rc != 0:
97
+ log(f"Not a git repo at {target}: {err.strip()}", "ERROR")
98
+ return None
99
+ run(["git", "fetch", "--all", "--tags", "--prune"], cwd=target)
100
+ ensure_unshallowed(target)
101
+ return target
102
+ log(f"Cloning {owner}/{repo}")
103
+ rc, _, err = run(["git", "clone", url, str(target)])
104
+ if rc != 0:
105
+ log(f"Clone failed for {url}: {err.strip()}", "ERROR")
106
+ return None
107
+ ensure_unshallowed(target)
108
+ return target
109
+
110
+
111
+ def parse_tsv(tsv_path: Path, max_count: Optional[int]) -> List[str]:
112
+ urls: List[str] = []
113
+ with tsv_path.open("r", encoding="utf-8") as f:
114
+ # Sniff delimiter; default to tab
115
+ sample = f.read(4096)
116
+ f.seek(0)
117
+ dialect = csv.Sniffer().sniff(sample, delimiters="\t,;") if sample else csv.excel_tab
118
+ reader = csv.DictReader(f, dialect=dialect)
119
+ cols = [c.strip().lower() for c in (reader.fieldnames or [])]
120
+ if not cols:
121
+ raise RuntimeError("TSV file has no header row")
122
+ use_url = "url" in cols
123
+ use_full = "full_name" in cols
124
+ if not use_url and not use_full:
125
+ raise RuntimeError("TSV must include either 'url' or 'full_name' columns")
126
+ for row in reader:
127
+ if max_count and len(urls) >= max_count:
128
+ break
129
+ u = (row.get("url") or "").strip() if use_url else ""
130
+ if not u and use_full:
131
+ fn = (row.get("full_name") or "").strip()
132
+ if fn:
133
+ u = f"https://github.com/{fn}.git"
134
+ if u:
135
+ urls.append(u)
136
+ return urls
137
+
138
+
139
+ def main(argv: Optional[List[str]] = None) -> int:
140
+ ap = argparse.ArgumentParser(description="Clone repos listed in a TSV and emit a jmo targets file")
141
+ ap.add_argument("--tsv", required=True, help="Path to candidates.tsv with 'url' or 'full_name' header")
142
+ ap.add_argument("--dest", default="repos-tsv", help="Destination directory to clone into (default: repos-tsv)")
143
+ ap.add_argument("--targets-out", default=str(Path("results") / "targets.tsv.txt"), help="Path to write newline-delimited repo paths (default: results/targets.tsv.txt)")
144
+ ap.add_argument("--max", type=int, default=None, help="Optional max number of repos to process")
145
+ ap.add_argument("--human-logs", action="store_true", help="Use human-friendly logs")
146
+ args = ap.parse_args(argv)
147
+
148
+ tsv_path = Path(args.tsv).expanduser().resolve()
149
+ dest = Path(args.dest).expanduser().resolve()
150
+ targets_out = Path(args.targets_out).expanduser().resolve()
151
+ targets_out.parent.mkdir(parents=True, exist_ok=True)
152
+
153
+ if not tsv_path.exists():
154
+ log(f"TSV not found: {tsv_path}", "ERROR")
155
+ return 2
156
+
157
+ urls = parse_tsv(tsv_path, args.max)
158
+ if not urls:
159
+ log("No repository URLs found in TSV", "ERROR")
160
+ return 2
161
+
162
+ paths: List[Path] = []
163
+ for url in urls:
164
+ p = clone_or_update(url, dest)
165
+ if p:
166
+ paths.append(p)
167
+
168
+ if not paths:
169
+ log("No repositories cloned/updated successfully", "ERROR")
170
+ return 1
171
+
172
+ # Write absolute paths to targets file
173
+ with targets_out.open("w", encoding="utf-8") as f:
174
+ for p in paths:
175
+ f.write(str(p) + "\n")
176
+ log(f"Wrote targets file: {targets_out}")
177
+ log(f"Cloned/updated {len(paths)} repos into {dest}")
178
+ return 0
179
+
180
+
181
+ if __name__ == "__main__":
182
+ raise SystemExit(main())