maunprekshak 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.
- maunprekshak-0.1.0/LICENSE +21 -0
- maunprekshak-0.1.0/PKG-INFO +192 -0
- maunprekshak-0.1.0/README.md +151 -0
- maunprekshak-0.1.0/maunprekshak/__init__.py +3 -0
- maunprekshak-0.1.0/maunprekshak/cli/__init__.py +1 -0
- maunprekshak-0.1.0/maunprekshak/cli/main.py +84 -0
- maunprekshak-0.1.0/maunprekshak/scanner/__init__.py +37 -0
- maunprekshak-0.1.0/maunprekshak/scanner/deps.py +246 -0
- maunprekshak-0.1.0/maunprekshak/scanner/report.py +356 -0
- maunprekshak-0.1.0/maunprekshak/scanner/sast.py +246 -0
- maunprekshak-0.1.0/maunprekshak/scanner/secrets.py +103 -0
- maunprekshak-0.1.0/maunprekshak.egg-info/PKG-INFO +192 -0
- maunprekshak-0.1.0/maunprekshak.egg-info/SOURCES.txt +20 -0
- maunprekshak-0.1.0/maunprekshak.egg-info/dependency_links.txt +1 -0
- maunprekshak-0.1.0/maunprekshak.egg-info/entry_points.txt +3 -0
- maunprekshak-0.1.0/maunprekshak.egg-info/requires.txt +16 -0
- maunprekshak-0.1.0/maunprekshak.egg-info/top_level.txt +1 -0
- maunprekshak-0.1.0/pyproject.toml +55 -0
- maunprekshak-0.1.0/setup.cfg +4 -0
- maunprekshak-0.1.0/tests/test_deps.py +147 -0
- maunprekshak-0.1.0/tests/test_sast.py +103 -0
- maunprekshak-0.1.0/tests/test_secrets.py +85 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Praman Kasliwal & MaunPrekshak Contributors
|
|
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,192 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: maunprekshak
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: The Silent Observer — Open-source Python security scanner for dependencies, secrets & insecure code
|
|
5
|
+
Author-email: Praman Kasliwal <kasliwal.praman008@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/PramanKasliwal/maunprekshak
|
|
8
|
+
Project-URL: Repository, https://github.com/PramanKasliwal/maunprekshak
|
|
9
|
+
Project-URL: Issues, https://github.com/PramanKasliwal/maunprekshak/issues
|
|
10
|
+
Project-URL: Documentation, https://github.com/PramanKasliwal/maunprekshak#readme
|
|
11
|
+
Keywords: security,python,vulnerability,scanner,sast,secrets,cve,osv
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Topic :: Security
|
|
21
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: typer>=0.12.0
|
|
26
|
+
Requires-Dist: rich>=13.7.0
|
|
27
|
+
Requires-Dist: httpx>=0.27.0
|
|
28
|
+
Requires-Dist: packaging>=24.0
|
|
29
|
+
Requires-Dist: google-genai>=1.0.0
|
|
30
|
+
Requires-Dist: reportlab>=4.2.0
|
|
31
|
+
Requires-Dist: pyyaml>=6.0.1
|
|
32
|
+
Requires-Dist: toml>=0.10.2
|
|
33
|
+
Requires-Dist: python-dotenv>=1.2.2
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
36
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
|
|
37
|
+
Requires-Dist: pytest-cov>=5.0.0; extra == "dev"
|
|
38
|
+
Requires-Dist: ruff>=0.4.0; extra == "dev"
|
|
39
|
+
Requires-Dist: mypy>=1.10.0; extra == "dev"
|
|
40
|
+
Dynamic: license-file
|
|
41
|
+
|
|
42
|
+
# MaunPrekshak — मौन प्रेक्षक
|
|
43
|
+
|
|
44
|
+
> *"The Silent Observer. Nothing hides from it."*
|
|
45
|
+
|
|
46
|
+
[](https://opensource.org/licenses/MIT)
|
|
47
|
+
[](https://www.python.org/downloads/)
|
|
48
|
+
[](https://badge.fury.io/py/maunprekshak)
|
|
49
|
+
[](https://github.com/PramanKasliwal/maunprekshak/actions)
|
|
50
|
+
|
|
51
|
+
**MaunPrekshak** (मौन = *Silent*, प्रेक्षक = *Observer*) is a fast, privacy-first Python security toolkit designed to catch vulnerabilities, exposed credentials, and insecure code patterns right in your terminal.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## ⚡ Highlights
|
|
56
|
+
|
|
57
|
+
- 🔍 **Dependency Vulnerabilities (SCA)**: Real-time CVE discovery against [OSV.dev](https://osv.dev) for `requirements.txt`, `pyproject.toml`, and `Pipfile`.
|
|
58
|
+
- 🔑 **Secrets & Credential Detection**: 40+ high-precision regex detectors for AWS keys, GCP keys, GitHub tokens, Stripe keys, RSA/SSH private keys, JWTs, and database URIs with false-positive suppression.
|
|
59
|
+
- 🛡️ **Static Code Analysis (SAST)**: Python AST visitor checking for `eval()`, `exec()`, `pickle.loads()`, `subprocess(..., shell=True)`, `yaml.load()`, insecure hashing (`MD5`/`SHA1`), and command injection.
|
|
60
|
+
- 🎨 **Rich Terminal UX**: Beautiful formatted console output, severity badges, and export to **JSON** or **Markdown**.
|
|
61
|
+
- 🔒 **100% Privacy & Local-First**: Scans run entirely on your local CPU. Your source code never leaves your computer.
|
|
62
|
+
- 🤖 **Optional AI Remediation**: Plug in your own Google Gemini API key to get an instant executive summary and tailored remediation steps.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 🚀 Quick Start
|
|
67
|
+
|
|
68
|
+
### Installation
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pip install maunprekshak
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 🐧 Linux (1-Line Standalone Install — No Python Required)
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
curl -sSL https://raw.githubusercontent.com/PramanKasliwal/maunprekshak/main/install.sh | bash
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 🐍 Via PyPI (Any OS)
|
|
81
|
+
```bash
|
|
82
|
+
pip install maunprekshak
|
|
83
|
+
# or using pipx (recommended for Ubuntu 24.04+)
|
|
84
|
+
pipx install maunprekshak
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Basic Scan
|
|
88
|
+
|
|
89
|
+
Scan the current directory:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
mp scan .
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Fast Scan without AI (No API Key Required)
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
mp scan . --no-ai
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Export Results to JSON or Markdown
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Export as JSON for pipelines
|
|
105
|
+
mp scan ./my-project --output json > report.json
|
|
106
|
+
|
|
107
|
+
# Export formatted Markdown
|
|
108
|
+
mp scan ./my-project --output markdown > SECURITY.md
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### CI/CD Mode (Exit with Non-Zero on Threshold Breach)
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# Fail CI build if any CRITICAL issue is found
|
|
115
|
+
mp scan . --ci --fail-on critical
|
|
116
|
+
|
|
117
|
+
# Fail CI build on HIGH or CRITICAL issues
|
|
118
|
+
mp scan . --ci --fail-on high
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 🖥️ Sample Console Output
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
127
|
+
│ Risk Level: HIGH (Score: 78) │
|
|
128
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
129
|
+
|
|
130
|
+
┌──────────────────────────────────────────────────────────────────────────────┐
|
|
131
|
+
│ Scan Summary │
|
|
132
|
+
├──────────────┬──────────┬─────────┬────────┬───────┬────────────────────────┤
|
|
133
|
+
│ Module │ CRITICAL │ HIGH │ MEDIUM │ LOW │ Total │
|
|
134
|
+
├──────────────┼──────────┼─────────┼────────┼───────┼────────────────────────┤
|
|
135
|
+
│ Dependencies │ 1 │ 2 │ 0 │ 0 │ 3 vulnerabilities │
|
|
136
|
+
│ Secrets │ 1 │ 1 │ 0 │ 0 │ 2 exposed credentials │
|
|
137
|
+
│ SAST │ 0 │ 3 │ 4 │ 1 │ 8 insecure patterns │
|
|
138
|
+
└──────────────┴──────────┴─────────┴────────┴───────┴────────────────────────┘
|
|
139
|
+
|
|
140
|
+
Top Findings:
|
|
141
|
+
[CRITICAL] CVE-2023-32681 — requests==2.25.1 (Fixed in 2.31.0)
|
|
142
|
+
[HIGH] AWS Access Key ID exposed in config.py:12
|
|
143
|
+
[HIGH] MP004: subprocess.run() called with shell=True in deploy.py:45
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## 📖 CLI Command Reference
|
|
149
|
+
|
|
150
|
+
| Option | Default | Description |
|
|
151
|
+
| :--- | :---: | :--- |
|
|
152
|
+
| `path` | `.` | Directory or project path to scan |
|
|
153
|
+
| `--only` | `all` | Restrict scan to: `deps`, `secrets`, or `sast` |
|
|
154
|
+
| `--output` | `console` | Output format: `console`, `json`, `markdown` |
|
|
155
|
+
| `--output-file` | `stdout` | Write report directly to a file |
|
|
156
|
+
| `--ci` | `false` | Compact machine-readable summary + exit code |
|
|
157
|
+
| `--fail-on` | `critical` | Threshold: `critical`, `high`, `medium`, `low` |
|
|
158
|
+
| `--no-ai` | `false` | Skip AI summary generation (instant execution) |
|
|
159
|
+
| `--exclude` | `None` | Comma-separated directories to exclude |
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 🤖 Bringing Your Own Gemini AI Key (Optional)
|
|
164
|
+
|
|
165
|
+
If you'd like AI-generated remediation summaries, set your Gemini API key in your environment or a `.env` file:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
export GEMINI_API_KEY="AIzaSy..."
|
|
169
|
+
mp scan .
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Get a free API key at [Google AI Studio](https://aistudio.google.com/app/apikey).
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## 🤝 Contributing
|
|
177
|
+
|
|
178
|
+
We welcome community contributions! Please read our [CONTRIBUTING.md](CONTRIBUTING.md) to get started.
|
|
179
|
+
|
|
180
|
+
- Found a bug or missing a secret pattern? [Open an Issue](https://github.com/PramanKasliwal/maunprekshak/issues).
|
|
181
|
+
- Want to contribute a new SAST check? PRs are warmly welcomed!
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## 📄 License
|
|
186
|
+
|
|
187
|
+
Distributed under the **MIT License**. See [LICENSE](LICENSE) for details.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
> *In ancient Sanskrit, मौन (Maun) signifies the all-knowing silence, and प्रेक्षक (Prekshak) is the ever-vigilant observer.*
|
|
192
|
+
> *MaunPrekshak protects your code quietly, thoroughly, and without compromise.*
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# MaunPrekshak — मौन प्रेक्षक
|
|
2
|
+
|
|
3
|
+
> *"The Silent Observer. Nothing hides from it."*
|
|
4
|
+
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://www.python.org/downloads/)
|
|
7
|
+
[](https://badge.fury.io/py/maunprekshak)
|
|
8
|
+
[](https://github.com/PramanKasliwal/maunprekshak/actions)
|
|
9
|
+
|
|
10
|
+
**MaunPrekshak** (मौन = *Silent*, प्रेक्षक = *Observer*) is a fast, privacy-first Python security toolkit designed to catch vulnerabilities, exposed credentials, and insecure code patterns right in your terminal.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## ⚡ Highlights
|
|
15
|
+
|
|
16
|
+
- 🔍 **Dependency Vulnerabilities (SCA)**: Real-time CVE discovery against [OSV.dev](https://osv.dev) for `requirements.txt`, `pyproject.toml`, and `Pipfile`.
|
|
17
|
+
- 🔑 **Secrets & Credential Detection**: 40+ high-precision regex detectors for AWS keys, GCP keys, GitHub tokens, Stripe keys, RSA/SSH private keys, JWTs, and database URIs with false-positive suppression.
|
|
18
|
+
- 🛡️ **Static Code Analysis (SAST)**: Python AST visitor checking for `eval()`, `exec()`, `pickle.loads()`, `subprocess(..., shell=True)`, `yaml.load()`, insecure hashing (`MD5`/`SHA1`), and command injection.
|
|
19
|
+
- 🎨 **Rich Terminal UX**: Beautiful formatted console output, severity badges, and export to **JSON** or **Markdown**.
|
|
20
|
+
- 🔒 **100% Privacy & Local-First**: Scans run entirely on your local CPU. Your source code never leaves your computer.
|
|
21
|
+
- 🤖 **Optional AI Remediation**: Plug in your own Google Gemini API key to get an instant executive summary and tailored remediation steps.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 🚀 Quick Start
|
|
26
|
+
|
|
27
|
+
### Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install maunprekshak
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 🐧 Linux (1-Line Standalone Install — No Python Required)
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
curl -sSL https://raw.githubusercontent.com/PramanKasliwal/maunprekshak/main/install.sh | bash
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 🐍 Via PyPI (Any OS)
|
|
40
|
+
```bash
|
|
41
|
+
pip install maunprekshak
|
|
42
|
+
# or using pipx (recommended for Ubuntu 24.04+)
|
|
43
|
+
pipx install maunprekshak
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Basic Scan
|
|
47
|
+
|
|
48
|
+
Scan the current directory:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
mp scan .
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Fast Scan without AI (No API Key Required)
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
mp scan . --no-ai
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Export Results to JSON or Markdown
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Export as JSON for pipelines
|
|
64
|
+
mp scan ./my-project --output json > report.json
|
|
65
|
+
|
|
66
|
+
# Export formatted Markdown
|
|
67
|
+
mp scan ./my-project --output markdown > SECURITY.md
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### CI/CD Mode (Exit with Non-Zero on Threshold Breach)
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Fail CI build if any CRITICAL issue is found
|
|
74
|
+
mp scan . --ci --fail-on critical
|
|
75
|
+
|
|
76
|
+
# Fail CI build on HIGH or CRITICAL issues
|
|
77
|
+
mp scan . --ci --fail-on high
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 🖥️ Sample Console Output
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
86
|
+
│ Risk Level: HIGH (Score: 78) │
|
|
87
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
88
|
+
|
|
89
|
+
┌──────────────────────────────────────────────────────────────────────────────┐
|
|
90
|
+
│ Scan Summary │
|
|
91
|
+
├──────────────┬──────────┬─────────┬────────┬───────┬────────────────────────┤
|
|
92
|
+
│ Module │ CRITICAL │ HIGH │ MEDIUM │ LOW │ Total │
|
|
93
|
+
├──────────────┼──────────┼─────────┼────────┼───────┼────────────────────────┤
|
|
94
|
+
│ Dependencies │ 1 │ 2 │ 0 │ 0 │ 3 vulnerabilities │
|
|
95
|
+
│ Secrets │ 1 │ 1 │ 0 │ 0 │ 2 exposed credentials │
|
|
96
|
+
│ SAST │ 0 │ 3 │ 4 │ 1 │ 8 insecure patterns │
|
|
97
|
+
└──────────────┴──────────┴─────────┴────────┴───────┴────────────────────────┘
|
|
98
|
+
|
|
99
|
+
Top Findings:
|
|
100
|
+
[CRITICAL] CVE-2023-32681 — requests==2.25.1 (Fixed in 2.31.0)
|
|
101
|
+
[HIGH] AWS Access Key ID exposed in config.py:12
|
|
102
|
+
[HIGH] MP004: subprocess.run() called with shell=True in deploy.py:45
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## 📖 CLI Command Reference
|
|
108
|
+
|
|
109
|
+
| Option | Default | Description |
|
|
110
|
+
| :--- | :---: | :--- |
|
|
111
|
+
| `path` | `.` | Directory or project path to scan |
|
|
112
|
+
| `--only` | `all` | Restrict scan to: `deps`, `secrets`, or `sast` |
|
|
113
|
+
| `--output` | `console` | Output format: `console`, `json`, `markdown` |
|
|
114
|
+
| `--output-file` | `stdout` | Write report directly to a file |
|
|
115
|
+
| `--ci` | `false` | Compact machine-readable summary + exit code |
|
|
116
|
+
| `--fail-on` | `critical` | Threshold: `critical`, `high`, `medium`, `low` |
|
|
117
|
+
| `--no-ai` | `false` | Skip AI summary generation (instant execution) |
|
|
118
|
+
| `--exclude` | `None` | Comma-separated directories to exclude |
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## 🤖 Bringing Your Own Gemini AI Key (Optional)
|
|
123
|
+
|
|
124
|
+
If you'd like AI-generated remediation summaries, set your Gemini API key in your environment or a `.env` file:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
export GEMINI_API_KEY="AIzaSy..."
|
|
128
|
+
mp scan .
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Get a free API key at [Google AI Studio](https://aistudio.google.com/app/apikey).
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## 🤝 Contributing
|
|
136
|
+
|
|
137
|
+
We welcome community contributions! Please read our [CONTRIBUTING.md](CONTRIBUTING.md) to get started.
|
|
138
|
+
|
|
139
|
+
- Found a bug or missing a secret pattern? [Open an Issue](https://github.com/PramanKasliwal/maunprekshak/issues).
|
|
140
|
+
- Want to contribute a new SAST check? PRs are warmly welcomed!
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## 📄 License
|
|
145
|
+
|
|
146
|
+
Distributed under the **MIT License**. See [LICENSE](LICENSE) for details.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
> *In ancient Sanskrit, मौन (Maun) signifies the all-knowing silence, and प्रेक्षक (Prekshak) is the ever-vigilant observer.*
|
|
151
|
+
> *MaunPrekshak protects your code quietly, thoroughly, and without compromise.*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""CLI package for MaunPrekshak."""
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
import os
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from dotenv import load_dotenv
|
|
5
|
+
from rich.console import Console
|
|
6
|
+
from rich.table import Table
|
|
7
|
+
from rich.panel import Panel
|
|
8
|
+
from maunprekshak import __version__
|
|
9
|
+
from maunprekshak.scanner import scan_project
|
|
10
|
+
from maunprekshak.scanner.report import to_json, to_markdown, to_pdf, generate_ai_summary
|
|
11
|
+
|
|
12
|
+
# Auto-load .env from the current directory or any parent directory
|
|
13
|
+
# This means `mp scan .` will pick up .env automatically
|
|
14
|
+
load_dotenv(dotenv_path=Path.cwd() / ".env", override=False)
|
|
15
|
+
load_dotenv(override=False) # Also check current working dir
|
|
16
|
+
|
|
17
|
+
app = typer.Typer(help="MaunPrekshak — The Silent Observer")
|
|
18
|
+
console = Console()
|
|
19
|
+
|
|
20
|
+
@app.command()
|
|
21
|
+
def scan(
|
|
22
|
+
path: str,
|
|
23
|
+
only: str = typer.Option(None, help="Run only: deps, secrets, sast"),
|
|
24
|
+
output: str = typer.Option("console", help="Output format: console, json, markdown, pdf"),
|
|
25
|
+
output_file: str = typer.Option(None, help="Save output to this file path"),
|
|
26
|
+
ci: bool = typer.Option(False, help="CI mode: compact output, non-zero exit on threshold breach"),
|
|
27
|
+
fail_on: str = typer.Option("critical", help="Fail CI if severity reached: critical, high, medium, low"),
|
|
28
|
+
no_ai: bool = typer.Option(False, help="Skip Gemini AI summary generation"),
|
|
29
|
+
exclude: str = typer.Option(None, help="Comma-separated dirs to exclude (e.g. tests,fixtures)"),
|
|
30
|
+
):
|
|
31
|
+
exclude_list = [e.strip() for e in exclude.split(",") if e.strip()] if exclude else None
|
|
32
|
+
with console.status("[bold green]Scanning project...") as status:
|
|
33
|
+
result = scan_project(path, exclude=exclude_list, only=only)
|
|
34
|
+
|
|
35
|
+
if not no_ai:
|
|
36
|
+
status.update("[bold green]Generating AI summary...")
|
|
37
|
+
result.ai_summary = generate_ai_summary(result)
|
|
38
|
+
|
|
39
|
+
if output == "json":
|
|
40
|
+
out_str = to_json(result)
|
|
41
|
+
if output_file:
|
|
42
|
+
with open(output_file, "w") as f:
|
|
43
|
+
f.write(out_str)
|
|
44
|
+
else:
|
|
45
|
+
print(out_str)
|
|
46
|
+
elif output == "markdown":
|
|
47
|
+
out_str = to_markdown(result)
|
|
48
|
+
if output_file:
|
|
49
|
+
with open(output_file, "w") as f:
|
|
50
|
+
f.write(out_str)
|
|
51
|
+
else:
|
|
52
|
+
print(out_str)
|
|
53
|
+
elif output == "pdf" and output_file:
|
|
54
|
+
to_pdf(result, output_file)
|
|
55
|
+
console.print(f"[bold green]Saved PDF to {output_file}[/bold green]")
|
|
56
|
+
else:
|
|
57
|
+
# Console output
|
|
58
|
+
console.print(Panel(f"[bold red]Risk Level: {result.risk_score.level}[/bold red] (Score: {result.risk_score.score})"))
|
|
59
|
+
if result.ai_summary:
|
|
60
|
+
console.print("\n[bold]AI Summary:[/bold]")
|
|
61
|
+
console.print(result.ai_summary)
|
|
62
|
+
|
|
63
|
+
if ci:
|
|
64
|
+
severity_map = {"low": 1, "medium": 21, "high": 51, "critical": 100}
|
|
65
|
+
threshold = severity_map.get(fail_on.lower(), 100)
|
|
66
|
+
if result.risk_score.score >= threshold:
|
|
67
|
+
console.print(f"[bold red]CI Check Failed: Score {result.risk_score.score} >= {threshold}[/bold red]")
|
|
68
|
+
raise typer.Exit(code=1)
|
|
69
|
+
|
|
70
|
+
@app.command()
|
|
71
|
+
def version():
|
|
72
|
+
"""Print the current version."""
|
|
73
|
+
console.print(f"MaunPrekshak v{__version__}")
|
|
74
|
+
|
|
75
|
+
@app.command()
|
|
76
|
+
def auth_login():
|
|
77
|
+
"""Save API key."""
|
|
78
|
+
key = typer.prompt("Enter API Key", hide_input=True)
|
|
79
|
+
with open(os.path.expanduser("~/.maunprekshak.yaml"), "w") as f:
|
|
80
|
+
f.write(f"api_key: {key}")
|
|
81
|
+
console.print("[green]API Key saved.[/green]")
|
|
82
|
+
|
|
83
|
+
if __name__ == "__main__":
|
|
84
|
+
app()
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from typing import List, Optional
|
|
3
|
+
from maunprekshak.scanner.report import ScanResult, aggregate
|
|
4
|
+
from maunprekshak.scanner.deps import scan_dependencies
|
|
5
|
+
from maunprekshak.scanner.secrets import scan_secrets
|
|
6
|
+
from maunprekshak.scanner.sast import scan_sast
|
|
7
|
+
|
|
8
|
+
def scan_project(
|
|
9
|
+
path: str,
|
|
10
|
+
exclude: Optional[List[str]] = None,
|
|
11
|
+
only: Optional[str] = None,
|
|
12
|
+
) -> ScanResult:
|
|
13
|
+
"""
|
|
14
|
+
Orchestrate the scanning of dependencies, secrets, and SAST.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
path: Path to the project root directory
|
|
18
|
+
exclude: Optional list of directories to exclude
|
|
19
|
+
only: Run only a specific module ('deps', 'secrets', 'sast')
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
A unified ScanResult containing all findings.
|
|
23
|
+
"""
|
|
24
|
+
deps = []
|
|
25
|
+
secrets = []
|
|
26
|
+
sast = []
|
|
27
|
+
|
|
28
|
+
if only is None or only == "deps":
|
|
29
|
+
deps = asyncio.run(scan_dependencies(path))
|
|
30
|
+
|
|
31
|
+
if only is None or only == "secrets":
|
|
32
|
+
secrets = scan_secrets(path, exclude=exclude)
|
|
33
|
+
|
|
34
|
+
if only is None or only == "sast":
|
|
35
|
+
sast = scan_sast(path, exclude=exclude)
|
|
36
|
+
|
|
37
|
+
return aggregate(deps, secrets, sast)
|