owasp-audit-agent 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.
- owasp_audit_agent-0.1.0/LICENSE +21 -0
- owasp_audit_agent-0.1.0/PKG-INFO +236 -0
- owasp_audit_agent-0.1.0/README.md +192 -0
- owasp_audit_agent-0.1.0/agent/__init__.py +38 -0
- owasp_audit_agent-0.1.0/agent/base_checker.py +39 -0
- owasp_audit_agent-0.1.0/agent/cli.py +80 -0
- owasp_audit_agent-0.1.0/agent/config.py +161 -0
- owasp_audit_agent-0.1.0/agent/dependency_scanner.py +172 -0
- owasp_audit_agent-0.1.0/agent/graph.py +205 -0
- owasp_audit_agent-0.1.0/agent/history.py +68 -0
- owasp_audit_agent-0.1.0/agent/llm.py +118 -0
- owasp_audit_agent-0.1.0/agent/models.py +46 -0
- owasp_audit_agent-0.1.0/agent/registry.py +139 -0
- owasp_audit_agent-0.1.0/agent/report.py +286 -0
- owasp_audit_agent-0.1.0/agent/rule_fixer.py +147 -0
- owasp_audit_agent-0.1.0/agent/sarif_exporter.py +91 -0
- owasp_audit_agent-0.1.0/agent/state.py +29 -0
- owasp_audit_agent-0.1.0/agent/tools/__init__.py +0 -0
- owasp_audit_agent-0.1.0/agent/tools/access_control_checker.py +56 -0
- owasp_audit_agent-0.1.0/agent/tools/auth_checker.py +56 -0
- owasp_audit_agent-0.1.0/agent/tools/crypto_checker.py +60 -0
- owasp_audit_agent-0.1.0/agent/tools/exception_checker.py +78 -0
- owasp_audit_agent-0.1.0/agent/tools/injection_checker.py +59 -0
- owasp_audit_agent-0.1.0/agent/tools/insecure_design_checker.py +61 -0
- owasp_audit_agent-0.1.0/agent/tools/integrity_checker.py +61 -0
- owasp_audit_agent-0.1.0/agent/tools/logging_checker.py +56 -0
- owasp_audit_agent-0.1.0/agent/tools/misconfig_checker.py +56 -0
- owasp_audit_agent-0.1.0/agent/tools/supply_chain_checker.py +61 -0
- owasp_audit_agent-0.1.0/owasp_audit_agent.egg-info/PKG-INFO +236 -0
- owasp_audit_agent-0.1.0/owasp_audit_agent.egg-info/SOURCES.txt +39 -0
- owasp_audit_agent-0.1.0/owasp_audit_agent.egg-info/dependency_links.txt +1 -0
- owasp_audit_agent-0.1.0/owasp_audit_agent.egg-info/entry_points.txt +2 -0
- owasp_audit_agent-0.1.0/owasp_audit_agent.egg-info/requires.txt +28 -0
- owasp_audit_agent-0.1.0/owasp_audit_agent.egg-info/top_level.txt +1 -0
- owasp_audit_agent-0.1.0/pyproject.toml +80 -0
- owasp_audit_agent-0.1.0/setup.cfg +4 -0
- owasp_audit_agent-0.1.0/tests/test_checkers_per_category.py +47 -0
- owasp_audit_agent-0.1.0/tests/test_config.py +83 -0
- owasp_audit_agent-0.1.0/tests/test_llm.py +56 -0
- owasp_audit_agent-0.1.0/tests/test_pipeline.py +39 -0
- owasp_audit_agent-0.1.0/tests/test_registry.py +84 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rio Nelson
|
|
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,236 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: owasp-audit-agent
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Agentic AI framework untuk audit keamanan kode Python berbasis OWASP Top 10 (2025).
|
|
5
|
+
Author-email: Rio Nelson <rionelson1802@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/rionelson/owasp-audit-agent
|
|
8
|
+
Project-URL: Repository, https://github.com/rionelson/owasp-audit-agent
|
|
9
|
+
Keywords: owasp,security,static-analysis,sast,langgraph,agent,audit
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Security
|
|
19
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: langgraph<2,>=1.2
|
|
24
|
+
Requires-Dist: langchain-groq<2,>=1.1
|
|
25
|
+
Requires-Dist: pydantic<3,>=2.10
|
|
26
|
+
Requires-Dist: python-dotenv>=1.0
|
|
27
|
+
Requires-Dist: fpdf2>=2.8
|
|
28
|
+
Requires-Dist: tomli>=2.0; python_version < "3.11"
|
|
29
|
+
Provides-Extra: ui
|
|
30
|
+
Requires-Dist: streamlit>=1.50; extra == "ui"
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
33
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
34
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
35
|
+
Provides-Extra: openai
|
|
36
|
+
Requires-Dist: langchain-openai>=0.2; extra == "openai"
|
|
37
|
+
Provides-Extra: anthropic
|
|
38
|
+
Requires-Dist: langchain-anthropic>=0.2; extra == "anthropic"
|
|
39
|
+
Provides-Extra: google
|
|
40
|
+
Requires-Dist: langchain-google-genai>=2.0; extra == "google"
|
|
41
|
+
Provides-Extra: ollama
|
|
42
|
+
Requires-Dist: langchain-ollama>=0.2; extra == "ollama"
|
|
43
|
+
Dynamic: license-file
|
|
44
|
+
|
|
45
|
+
# owasp-audit-agent
|
|
46
|
+
|
|
47
|
+
Framework *agentic AI* untuk audit keamanan kode Python berbasis **OWASP Top 10 (2025)**.
|
|
48
|
+
Menganalisis kode sumber, mendeteksi kerentanan di 10 kategori OWASP, menghasilkan
|
|
49
|
+
ringkasan eksekutif dari LLM, mencoba memperbaiki secara otomatis, lalu memverifikasi ulang.
|
|
50
|
+
|
|
51
|
+
Orkestrasi dibangun di atas **LangGraph**; deteksi memakai *checker* modular yang
|
|
52
|
+
ditemukan secara otomatis sehingga menambah aturan baru tidak menyentuh kode inti.
|
|
53
|
+
|
|
54
|
+
## Instalasi
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install -e . # library + CLI
|
|
58
|
+
pip install -e ".[ui]" # + UI Streamlit
|
|
59
|
+
pip install -e ".[dev]" # + pytest
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Buat file `.env` berisi kredensial LLM:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
GROQ_API_KEY=your_key_here
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Pemakaian sebagai library
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from agent import audit_code
|
|
72
|
+
|
|
73
|
+
result = audit_code(open("app.py").read(), "app.py")
|
|
74
|
+
|
|
75
|
+
for f in result["findings"]:
|
|
76
|
+
print(f.severity.value, f.owasp_category.value, f.title, f.line_number)
|
|
77
|
+
|
|
78
|
+
print(result["summary"])
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## CLI
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
owasp-audit app.py # audit satu file
|
|
85
|
+
owasp-audit app.py --json # keluaran JSON
|
|
86
|
+
owasp-audit --list-checkers # daftar checker terdaftar
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## UI (Streamlit)
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
streamlit run app.py
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Konfigurasi
|
|
96
|
+
|
|
97
|
+
Perilaku audit diatur lewat file `audit.toml` di root project (opsional) dan/atau
|
|
98
|
+
environment variable. Salin `audit.example.toml` menjadi `audit.toml` lalu sesuaikan:
|
|
99
|
+
|
|
100
|
+
```toml
|
|
101
|
+
[llm]
|
|
102
|
+
provider = "groq"
|
|
103
|
+
model = "llama-3.1-8b-instant"
|
|
104
|
+
temperature = 0.0
|
|
105
|
+
|
|
106
|
+
[audit]
|
|
107
|
+
escalation_threshold = 3 # eskalasi jika jumlah CRITICAL > nilai ini
|
|
108
|
+
max_fix_iterations = 2
|
|
109
|
+
auto_fix = true
|
|
110
|
+
|
|
111
|
+
[checkers]
|
|
112
|
+
enabled = [] # kosong = semua; mis. ["A01","A05","A07"]
|
|
113
|
+
disabled = ["A09"] # kode kategori yang dimatikan
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Env var menimpa file (berguna untuk CI): `OWASP_LLM_MODEL`,
|
|
117
|
+
`OWASP_ESCALATION_THRESHOLD`, `OWASP_MAX_FIX_ITERATIONS`, `OWASP_AUTO_FIX`,
|
|
118
|
+
`OWASP_ENABLED_CHECKERS`, `OWASP_DISABLED_CHECKERS`, `OWASP_CONFIG` (path file config).
|
|
119
|
+
|
|
120
|
+
Dari kode, config bisa dimuat manual:
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from agent import AuditConfig
|
|
124
|
+
cfg = AuditConfig.load() # audit.toml + env
|
|
125
|
+
print(cfg.escalation_threshold, cfg.llm_model, cfg.is_checker_enabled("A05"))
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Provider LLM
|
|
129
|
+
|
|
130
|
+
Provider dipilih lewat `[llm] provider` di `audit.toml` (atau env `OWASP_LLM_PROVIDER`).
|
|
131
|
+
Built-in: `groq` (default, sudah termasuk), `openai`, `anthropic`, `google`, `ollama`.
|
|
132
|
+
Paket integrasi di-import lazy — install hanya yang dipakai:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
pip install -e ".[openai]" # atau .[anthropic] / .[google] / .[ollama]
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
```toml
|
|
139
|
+
[llm]
|
|
140
|
+
provider = "openai"
|
|
141
|
+
model = "gpt-4o-mini"
|
|
142
|
+
# base_url = "http://localhost:11434" # untuk Ollama / endpoint OpenAI-compatible
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
API key dibaca dari env sesuai provider (`GROQ_API_KEY`, `OPENAI_API_KEY`,
|
|
146
|
+
`ANTHROPIC_API_KEY`, dst). Menambah provider kustom:
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
from agent import register_provider
|
|
150
|
+
|
|
151
|
+
@register_provider("myllm")
|
|
152
|
+
def _build(config):
|
|
153
|
+
from my_pkg import MyChat
|
|
154
|
+
return MyChat(model=config.llm_model, temperature=config.llm_temperature)
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Lalu set `provider = "myllm"` di config.
|
|
158
|
+
|
|
159
|
+
## Kategori OWASP yang dicakup
|
|
160
|
+
|
|
161
|
+
| Kode | Kategori |
|
|
162
|
+
|------|----------|
|
|
163
|
+
| A01 | Broken Access Control |
|
|
164
|
+
| A02 | Security Misconfiguration |
|
|
165
|
+
| A03 | Software Supply Chain Failures |
|
|
166
|
+
| A04 | Cryptographic Failures |
|
|
167
|
+
| A05 | Injection |
|
|
168
|
+
| A06 | Insecure Design |
|
|
169
|
+
| A07 | Authentication Failures |
|
|
170
|
+
| A08 | Software or Data Integrity Failures |
|
|
171
|
+
| A09 | Security Logging and Alerting Failures |
|
|
172
|
+
| A10 | Mishandling of Exceptional Conditions |
|
|
173
|
+
|
|
174
|
+
## Menulis checker baru
|
|
175
|
+
|
|
176
|
+
Buat subclass `BaseChecker` dan implementasi `category`, `name`, dan `analyze()`:
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
# agent/tools/my_checker.py
|
|
180
|
+
from typing import List
|
|
181
|
+
from agent.base_checker import BaseChecker
|
|
182
|
+
from agent.models import Finding, OWASPCategory, SeverityLevel
|
|
183
|
+
|
|
184
|
+
class MyChecker(BaseChecker):
|
|
185
|
+
@property
|
|
186
|
+
def category(self) -> OWASPCategory:
|
|
187
|
+
return OWASPCategory.A05
|
|
188
|
+
|
|
189
|
+
@property
|
|
190
|
+
def name(self) -> str:
|
|
191
|
+
return "My Custom Checker"
|
|
192
|
+
|
|
193
|
+
def analyze(self, code: str, filename: str) -> List[Finding]:
|
|
194
|
+
findings = []
|
|
195
|
+
# ... logika deteksi ...
|
|
196
|
+
return findings
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Cukup letakkan file di `agent/tools/` — **auto-discovery** akan mendaftarkannya
|
|
200
|
+
otomatis saat `registry.discover()` dipanggil. Tidak perlu mengubah `graph.py`
|
|
201
|
+
maupun `registry.py`.
|
|
202
|
+
|
|
203
|
+
### Plugin eksternal (paket terpisah)
|
|
204
|
+
|
|
205
|
+
Checker juga bisa didistribusikan sebagai paket pihak ketiga tanpa menyentuh
|
|
206
|
+
repo ini. Deklarasikan *entry point* pada group `owasp_audit_agent.checkers`:
|
|
207
|
+
|
|
208
|
+
```toml
|
|
209
|
+
# pyproject.toml paket plugin kamu
|
|
210
|
+
[project.entry-points."owasp_audit_agent.checkers"]
|
|
211
|
+
my_checker = "my_package.my_module:MyChecker"
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Setelah paket terpasang, `registry.discover_entry_points()` akan memuatnya otomatis.
|
|
215
|
+
|
|
216
|
+
## Arsitektur
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
agent/
|
|
220
|
+
├── base_checker.py # abstract BaseChecker (kontrak checker)
|
|
221
|
+
├── registry.py # CheckerRegistry + auto-discovery + entry points
|
|
222
|
+
├── models.py # Finding, OWASPCategory, SeverityLevel (Pydantic)
|
|
223
|
+
├── state.py # AuditState (state LangGraph)
|
|
224
|
+
├── graph.py # workflow LangGraph + audit_code()
|
|
225
|
+
├── rule_fixer.py # perbaikan berbasis aturan
|
|
226
|
+
├── sarif_exporter.py # ekspor hasil ke SARIF
|
|
227
|
+
├── dependency_scanner.py
|
|
228
|
+
├── history.py # riwayat scan
|
|
229
|
+
├── report.py # laporan PDF
|
|
230
|
+
├── cli.py # command owasp-audit
|
|
231
|
+
└── tools/ # satu file per checker (auto-discovered)
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Lisensi
|
|
235
|
+
|
|
236
|
+
MIT — lihat [LICENSE](LICENSE).
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# owasp-audit-agent
|
|
2
|
+
|
|
3
|
+
Framework *agentic AI* untuk audit keamanan kode Python berbasis **OWASP Top 10 (2025)**.
|
|
4
|
+
Menganalisis kode sumber, mendeteksi kerentanan di 10 kategori OWASP, menghasilkan
|
|
5
|
+
ringkasan eksekutif dari LLM, mencoba memperbaiki secara otomatis, lalu memverifikasi ulang.
|
|
6
|
+
|
|
7
|
+
Orkestrasi dibangun di atas **LangGraph**; deteksi memakai *checker* modular yang
|
|
8
|
+
ditemukan secara otomatis sehingga menambah aturan baru tidak menyentuh kode inti.
|
|
9
|
+
|
|
10
|
+
## Instalasi
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install -e . # library + CLI
|
|
14
|
+
pip install -e ".[ui]" # + UI Streamlit
|
|
15
|
+
pip install -e ".[dev]" # + pytest
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Buat file `.env` berisi kredensial LLM:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
GROQ_API_KEY=your_key_here
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Pemakaian sebagai library
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
from agent import audit_code
|
|
28
|
+
|
|
29
|
+
result = audit_code(open("app.py").read(), "app.py")
|
|
30
|
+
|
|
31
|
+
for f in result["findings"]:
|
|
32
|
+
print(f.severity.value, f.owasp_category.value, f.title, f.line_number)
|
|
33
|
+
|
|
34
|
+
print(result["summary"])
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## CLI
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
owasp-audit app.py # audit satu file
|
|
41
|
+
owasp-audit app.py --json # keluaran JSON
|
|
42
|
+
owasp-audit --list-checkers # daftar checker terdaftar
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## UI (Streamlit)
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
streamlit run app.py
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Konfigurasi
|
|
52
|
+
|
|
53
|
+
Perilaku audit diatur lewat file `audit.toml` di root project (opsional) dan/atau
|
|
54
|
+
environment variable. Salin `audit.example.toml` menjadi `audit.toml` lalu sesuaikan:
|
|
55
|
+
|
|
56
|
+
```toml
|
|
57
|
+
[llm]
|
|
58
|
+
provider = "groq"
|
|
59
|
+
model = "llama-3.1-8b-instant"
|
|
60
|
+
temperature = 0.0
|
|
61
|
+
|
|
62
|
+
[audit]
|
|
63
|
+
escalation_threshold = 3 # eskalasi jika jumlah CRITICAL > nilai ini
|
|
64
|
+
max_fix_iterations = 2
|
|
65
|
+
auto_fix = true
|
|
66
|
+
|
|
67
|
+
[checkers]
|
|
68
|
+
enabled = [] # kosong = semua; mis. ["A01","A05","A07"]
|
|
69
|
+
disabled = ["A09"] # kode kategori yang dimatikan
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Env var menimpa file (berguna untuk CI): `OWASP_LLM_MODEL`,
|
|
73
|
+
`OWASP_ESCALATION_THRESHOLD`, `OWASP_MAX_FIX_ITERATIONS`, `OWASP_AUTO_FIX`,
|
|
74
|
+
`OWASP_ENABLED_CHECKERS`, `OWASP_DISABLED_CHECKERS`, `OWASP_CONFIG` (path file config).
|
|
75
|
+
|
|
76
|
+
Dari kode, config bisa dimuat manual:
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from agent import AuditConfig
|
|
80
|
+
cfg = AuditConfig.load() # audit.toml + env
|
|
81
|
+
print(cfg.escalation_threshold, cfg.llm_model, cfg.is_checker_enabled("A05"))
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Provider LLM
|
|
85
|
+
|
|
86
|
+
Provider dipilih lewat `[llm] provider` di `audit.toml` (atau env `OWASP_LLM_PROVIDER`).
|
|
87
|
+
Built-in: `groq` (default, sudah termasuk), `openai`, `anthropic`, `google`, `ollama`.
|
|
88
|
+
Paket integrasi di-import lazy — install hanya yang dipakai:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
pip install -e ".[openai]" # atau .[anthropic] / .[google] / .[ollama]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```toml
|
|
95
|
+
[llm]
|
|
96
|
+
provider = "openai"
|
|
97
|
+
model = "gpt-4o-mini"
|
|
98
|
+
# base_url = "http://localhost:11434" # untuk Ollama / endpoint OpenAI-compatible
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
API key dibaca dari env sesuai provider (`GROQ_API_KEY`, `OPENAI_API_KEY`,
|
|
102
|
+
`ANTHROPIC_API_KEY`, dst). Menambah provider kustom:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from agent import register_provider
|
|
106
|
+
|
|
107
|
+
@register_provider("myllm")
|
|
108
|
+
def _build(config):
|
|
109
|
+
from my_pkg import MyChat
|
|
110
|
+
return MyChat(model=config.llm_model, temperature=config.llm_temperature)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Lalu set `provider = "myllm"` di config.
|
|
114
|
+
|
|
115
|
+
## Kategori OWASP yang dicakup
|
|
116
|
+
|
|
117
|
+
| Kode | Kategori |
|
|
118
|
+
|------|----------|
|
|
119
|
+
| A01 | Broken Access Control |
|
|
120
|
+
| A02 | Security Misconfiguration |
|
|
121
|
+
| A03 | Software Supply Chain Failures |
|
|
122
|
+
| A04 | Cryptographic Failures |
|
|
123
|
+
| A05 | Injection |
|
|
124
|
+
| A06 | Insecure Design |
|
|
125
|
+
| A07 | Authentication Failures |
|
|
126
|
+
| A08 | Software or Data Integrity Failures |
|
|
127
|
+
| A09 | Security Logging and Alerting Failures |
|
|
128
|
+
| A10 | Mishandling of Exceptional Conditions |
|
|
129
|
+
|
|
130
|
+
## Menulis checker baru
|
|
131
|
+
|
|
132
|
+
Buat subclass `BaseChecker` dan implementasi `category`, `name`, dan `analyze()`:
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
# agent/tools/my_checker.py
|
|
136
|
+
from typing import List
|
|
137
|
+
from agent.base_checker import BaseChecker
|
|
138
|
+
from agent.models import Finding, OWASPCategory, SeverityLevel
|
|
139
|
+
|
|
140
|
+
class MyChecker(BaseChecker):
|
|
141
|
+
@property
|
|
142
|
+
def category(self) -> OWASPCategory:
|
|
143
|
+
return OWASPCategory.A05
|
|
144
|
+
|
|
145
|
+
@property
|
|
146
|
+
def name(self) -> str:
|
|
147
|
+
return "My Custom Checker"
|
|
148
|
+
|
|
149
|
+
def analyze(self, code: str, filename: str) -> List[Finding]:
|
|
150
|
+
findings = []
|
|
151
|
+
# ... logika deteksi ...
|
|
152
|
+
return findings
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Cukup letakkan file di `agent/tools/` — **auto-discovery** akan mendaftarkannya
|
|
156
|
+
otomatis saat `registry.discover()` dipanggil. Tidak perlu mengubah `graph.py`
|
|
157
|
+
maupun `registry.py`.
|
|
158
|
+
|
|
159
|
+
### Plugin eksternal (paket terpisah)
|
|
160
|
+
|
|
161
|
+
Checker juga bisa didistribusikan sebagai paket pihak ketiga tanpa menyentuh
|
|
162
|
+
repo ini. Deklarasikan *entry point* pada group `owasp_audit_agent.checkers`:
|
|
163
|
+
|
|
164
|
+
```toml
|
|
165
|
+
# pyproject.toml paket plugin kamu
|
|
166
|
+
[project.entry-points."owasp_audit_agent.checkers"]
|
|
167
|
+
my_checker = "my_package.my_module:MyChecker"
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Setelah paket terpasang, `registry.discover_entry_points()` akan memuatnya otomatis.
|
|
171
|
+
|
|
172
|
+
## Arsitektur
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
agent/
|
|
176
|
+
├── base_checker.py # abstract BaseChecker (kontrak checker)
|
|
177
|
+
├── registry.py # CheckerRegistry + auto-discovery + entry points
|
|
178
|
+
├── models.py # Finding, OWASPCategory, SeverityLevel (Pydantic)
|
|
179
|
+
├── state.py # AuditState (state LangGraph)
|
|
180
|
+
├── graph.py # workflow LangGraph + audit_code()
|
|
181
|
+
├── rule_fixer.py # perbaikan berbasis aturan
|
|
182
|
+
├── sarif_exporter.py # ekspor hasil ke SARIF
|
|
183
|
+
├── dependency_scanner.py
|
|
184
|
+
├── history.py # riwayat scan
|
|
185
|
+
├── report.py # laporan PDF
|
|
186
|
+
├── cli.py # command owasp-audit
|
|
187
|
+
└── tools/ # satu file per checker (auto-discovered)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Lisensi
|
|
191
|
+
|
|
192
|
+
MIT — lihat [LICENSE](LICENSE).
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""
|
|
2
|
+
owasp-audit-agent — framework audit keamanan kode Python berbasis OWASP Top 10 (2025).
|
|
3
|
+
|
|
4
|
+
API publik yang stabil:
|
|
5
|
+
|
|
6
|
+
from agent import audit_code, build_graph, registry
|
|
7
|
+
from agent import BaseChecker, Finding, OWASPCategory, SeverityLevel
|
|
8
|
+
|
|
9
|
+
Menulis checker baru: subclass `BaseChecker`, taruh file di `agent/tools/`
|
|
10
|
+
(otomatis ditemukan), atau distribusikan sebagai plugin lewat entry point
|
|
11
|
+
group "owasp_audit_agent.checkers".
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from agent.base_checker import BaseChecker
|
|
15
|
+
from agent.models import Finding, AuditResult, OWASPCategory, SeverityLevel
|
|
16
|
+
from agent.registry import CheckerRegistry, registry
|
|
17
|
+
from agent.config import AuditConfig
|
|
18
|
+
from agent.llm import build_llm, register_provider, available_providers
|
|
19
|
+
from agent.graph import build_graph, audit_code
|
|
20
|
+
|
|
21
|
+
__version__ = "0.1.0"
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"audit_code",
|
|
25
|
+
"build_graph",
|
|
26
|
+
"build_llm",
|
|
27
|
+
"register_provider",
|
|
28
|
+
"available_providers",
|
|
29
|
+
"registry",
|
|
30
|
+
"CheckerRegistry",
|
|
31
|
+
"AuditConfig",
|
|
32
|
+
"BaseChecker",
|
|
33
|
+
"Finding",
|
|
34
|
+
"AuditResult",
|
|
35
|
+
"OWASPCategory",
|
|
36
|
+
"SeverityLevel",
|
|
37
|
+
"__version__",
|
|
38
|
+
]
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import List
|
|
3
|
+
from agent.models import Finding, OWASPCategory
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BaseChecker(ABC):
|
|
7
|
+
"""
|
|
8
|
+
Abstract base class untuk semua OWASP checker.
|
|
9
|
+
Setiap checker baru WAJIB mengimplementasi method analyze().
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
@property
|
|
13
|
+
@abstractmethod
|
|
14
|
+
def category(self) -> OWASPCategory:
|
|
15
|
+
"""Kategori OWASP yang dicek oleh checker ini."""
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def name(self) -> str:
|
|
21
|
+
"""Nama checker yang mudah dibaca."""
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
@abstractmethod
|
|
25
|
+
def analyze(self, code: str, filename: str) -> List[Finding]:
|
|
26
|
+
"""
|
|
27
|
+
Analisis kode dan kembalikan list of Finding.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
code: Source code Python sebagai string
|
|
31
|
+
filename: Nama file yang dianalisis
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
List of Finding yang ditemukan
|
|
35
|
+
"""
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
def __repr__(self) -> str:
|
|
39
|
+
return f"<{self.__class__.__name__}: {self.category.value}>"
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI untuk owasp-audit-agent.
|
|
3
|
+
|
|
4
|
+
Pemakaian:
|
|
5
|
+
owasp-audit path/ke/file.py
|
|
6
|
+
owasp-audit file.py --json
|
|
7
|
+
owasp-audit --list-checkers
|
|
8
|
+
"""
|
|
9
|
+
import argparse
|
|
10
|
+
import json
|
|
11
|
+
import sys
|
|
12
|
+
|
|
13
|
+
from agent.registry import registry
|
|
14
|
+
from agent.graph import audit_code
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _cmd_list_checkers() -> int:
|
|
18
|
+
registry.discover()
|
|
19
|
+
checkers = registry.list_registered()
|
|
20
|
+
print(f"{len(checkers)} checker terdaftar:")
|
|
21
|
+
for line in sorted(checkers):
|
|
22
|
+
print(f" - {line}")
|
|
23
|
+
return 0
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _cmd_audit(path: str, as_json: bool) -> int:
|
|
27
|
+
try:
|
|
28
|
+
with open(path, "r", encoding="utf-8") as fh:
|
|
29
|
+
code = fh.read()
|
|
30
|
+
except OSError as exc:
|
|
31
|
+
print(f"Gagal membaca file: {exc}", file=sys.stderr)
|
|
32
|
+
return 2
|
|
33
|
+
|
|
34
|
+
result = audit_code(code, filename=path)
|
|
35
|
+
findings = result.get("findings", [])
|
|
36
|
+
|
|
37
|
+
if as_json:
|
|
38
|
+
payload = {
|
|
39
|
+
"filename": path,
|
|
40
|
+
"summary": result.get("summary", ""),
|
|
41
|
+
"escalated": result.get("escalated", False),
|
|
42
|
+
"findings": [f.model_dump(mode="json") for f in findings],
|
|
43
|
+
}
|
|
44
|
+
print(json.dumps(payload, indent=2, ensure_ascii=False))
|
|
45
|
+
return 1 if findings else 0
|
|
46
|
+
|
|
47
|
+
if not findings:
|
|
48
|
+
print(f"✓ Tidak ada temuan pada {path}.")
|
|
49
|
+
return 0
|
|
50
|
+
|
|
51
|
+
print(f"Ditemukan {len(findings)} isu pada {path}:\n")
|
|
52
|
+
for f in findings:
|
|
53
|
+
loc = f" (baris {f.line_number})" if f.line_number else ""
|
|
54
|
+
print(f" [{f.severity.value}] {f.owasp_category.value}{loc}")
|
|
55
|
+
print(f" {f.title}")
|
|
56
|
+
if result.get("escalated"):
|
|
57
|
+
print(f"\n⚠ {result.get('escalation_message', 'Eskalasi keamanan.')}")
|
|
58
|
+
print(f"\nRingkasan:\n{result.get('summary', '')}")
|
|
59
|
+
return 1
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def main(argv=None) -> int:
|
|
63
|
+
parser = argparse.ArgumentParser(
|
|
64
|
+
prog="owasp-audit",
|
|
65
|
+
description="Audit keamanan kode Python berbasis OWASP Top 10 (2025).",
|
|
66
|
+
)
|
|
67
|
+
parser.add_argument("path", nargs="?", help="File Python yang akan diaudit.")
|
|
68
|
+
parser.add_argument("--json", action="store_true", help="Keluarkan hasil sebagai JSON.")
|
|
69
|
+
parser.add_argument("--list-checkers", action="store_true", help="Tampilkan checker terdaftar lalu keluar.")
|
|
70
|
+
args = parser.parse_args(argv)
|
|
71
|
+
|
|
72
|
+
if args.list_checkers:
|
|
73
|
+
return _cmd_list_checkers()
|
|
74
|
+
if not args.path:
|
|
75
|
+
parser.error("berikan path file, atau gunakan --list-checkers")
|
|
76
|
+
return _cmd_audit(args.path, args.json)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
if __name__ == "__main__":
|
|
80
|
+
raise SystemExit(main())
|