aiptx 2.0.7__py3-none-any.whl

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 (187) hide show
  1. aipt_v2/__init__.py +110 -0
  2. aipt_v2/__main__.py +24 -0
  3. aipt_v2/agents/AIPTxAgent/__init__.py +10 -0
  4. aipt_v2/agents/AIPTxAgent/aiptx_agent.py +211 -0
  5. aipt_v2/agents/__init__.py +46 -0
  6. aipt_v2/agents/base.py +520 -0
  7. aipt_v2/agents/exploit_agent.py +688 -0
  8. aipt_v2/agents/ptt.py +406 -0
  9. aipt_v2/agents/state.py +168 -0
  10. aipt_v2/app.py +957 -0
  11. aipt_v2/browser/__init__.py +31 -0
  12. aipt_v2/browser/automation.py +458 -0
  13. aipt_v2/browser/crawler.py +453 -0
  14. aipt_v2/cli.py +2933 -0
  15. aipt_v2/compliance/__init__.py +71 -0
  16. aipt_v2/compliance/compliance_report.py +449 -0
  17. aipt_v2/compliance/framework_mapper.py +424 -0
  18. aipt_v2/compliance/nist_mapping.py +345 -0
  19. aipt_v2/compliance/owasp_mapping.py +330 -0
  20. aipt_v2/compliance/pci_mapping.py +297 -0
  21. aipt_v2/config.py +341 -0
  22. aipt_v2/core/__init__.py +43 -0
  23. aipt_v2/core/agent.py +630 -0
  24. aipt_v2/core/llm.py +395 -0
  25. aipt_v2/core/memory.py +305 -0
  26. aipt_v2/core/ptt.py +329 -0
  27. aipt_v2/database/__init__.py +14 -0
  28. aipt_v2/database/models.py +232 -0
  29. aipt_v2/database/repository.py +384 -0
  30. aipt_v2/docker/__init__.py +23 -0
  31. aipt_v2/docker/builder.py +260 -0
  32. aipt_v2/docker/manager.py +222 -0
  33. aipt_v2/docker/sandbox.py +371 -0
  34. aipt_v2/evasion/__init__.py +58 -0
  35. aipt_v2/evasion/request_obfuscator.py +272 -0
  36. aipt_v2/evasion/tls_fingerprint.py +285 -0
  37. aipt_v2/evasion/ua_rotator.py +301 -0
  38. aipt_v2/evasion/waf_bypass.py +439 -0
  39. aipt_v2/execution/__init__.py +23 -0
  40. aipt_v2/execution/executor.py +302 -0
  41. aipt_v2/execution/parser.py +544 -0
  42. aipt_v2/execution/terminal.py +337 -0
  43. aipt_v2/health.py +437 -0
  44. aipt_v2/intelligence/__init__.py +194 -0
  45. aipt_v2/intelligence/adaptation.py +474 -0
  46. aipt_v2/intelligence/auth.py +520 -0
  47. aipt_v2/intelligence/chaining.py +775 -0
  48. aipt_v2/intelligence/correlation.py +536 -0
  49. aipt_v2/intelligence/cve_aipt.py +334 -0
  50. aipt_v2/intelligence/cve_info.py +1111 -0
  51. aipt_v2/intelligence/knowledge_graph.py +590 -0
  52. aipt_v2/intelligence/learning.py +626 -0
  53. aipt_v2/intelligence/llm_analyzer.py +502 -0
  54. aipt_v2/intelligence/llm_tool_selector.py +518 -0
  55. aipt_v2/intelligence/payload_generator.py +562 -0
  56. aipt_v2/intelligence/rag.py +239 -0
  57. aipt_v2/intelligence/scope.py +442 -0
  58. aipt_v2/intelligence/searchers/__init__.py +5 -0
  59. aipt_v2/intelligence/searchers/exploitdb_searcher.py +523 -0
  60. aipt_v2/intelligence/searchers/github_searcher.py +467 -0
  61. aipt_v2/intelligence/searchers/google_searcher.py +281 -0
  62. aipt_v2/intelligence/tools.json +443 -0
  63. aipt_v2/intelligence/triage.py +670 -0
  64. aipt_v2/interactive_shell.py +559 -0
  65. aipt_v2/interface/__init__.py +5 -0
  66. aipt_v2/interface/cli.py +230 -0
  67. aipt_v2/interface/main.py +501 -0
  68. aipt_v2/interface/tui.py +1276 -0
  69. aipt_v2/interface/utils.py +583 -0
  70. aipt_v2/llm/__init__.py +39 -0
  71. aipt_v2/llm/config.py +26 -0
  72. aipt_v2/llm/llm.py +514 -0
  73. aipt_v2/llm/memory.py +214 -0
  74. aipt_v2/llm/request_queue.py +89 -0
  75. aipt_v2/llm/utils.py +89 -0
  76. aipt_v2/local_tool_installer.py +1467 -0
  77. aipt_v2/models/__init__.py +15 -0
  78. aipt_v2/models/findings.py +295 -0
  79. aipt_v2/models/phase_result.py +224 -0
  80. aipt_v2/models/scan_config.py +207 -0
  81. aipt_v2/monitoring/grafana/dashboards/aipt-dashboard.json +355 -0
  82. aipt_v2/monitoring/grafana/dashboards/default.yml +17 -0
  83. aipt_v2/monitoring/grafana/datasources/prometheus.yml +17 -0
  84. aipt_v2/monitoring/prometheus.yml +60 -0
  85. aipt_v2/orchestration/__init__.py +52 -0
  86. aipt_v2/orchestration/pipeline.py +398 -0
  87. aipt_v2/orchestration/progress.py +300 -0
  88. aipt_v2/orchestration/scheduler.py +296 -0
  89. aipt_v2/orchestrator.py +2427 -0
  90. aipt_v2/payloads/__init__.py +27 -0
  91. aipt_v2/payloads/cmdi.py +150 -0
  92. aipt_v2/payloads/sqli.py +263 -0
  93. aipt_v2/payloads/ssrf.py +204 -0
  94. aipt_v2/payloads/templates.py +222 -0
  95. aipt_v2/payloads/traversal.py +166 -0
  96. aipt_v2/payloads/xss.py +204 -0
  97. aipt_v2/prompts/__init__.py +60 -0
  98. aipt_v2/proxy/__init__.py +29 -0
  99. aipt_v2/proxy/history.py +352 -0
  100. aipt_v2/proxy/interceptor.py +452 -0
  101. aipt_v2/recon/__init__.py +44 -0
  102. aipt_v2/recon/dns.py +241 -0
  103. aipt_v2/recon/osint.py +367 -0
  104. aipt_v2/recon/subdomain.py +372 -0
  105. aipt_v2/recon/tech_detect.py +311 -0
  106. aipt_v2/reports/__init__.py +17 -0
  107. aipt_v2/reports/generator.py +313 -0
  108. aipt_v2/reports/html_report.py +378 -0
  109. aipt_v2/runtime/__init__.py +53 -0
  110. aipt_v2/runtime/base.py +30 -0
  111. aipt_v2/runtime/docker.py +401 -0
  112. aipt_v2/runtime/local.py +346 -0
  113. aipt_v2/runtime/tool_server.py +205 -0
  114. aipt_v2/runtime/vps.py +830 -0
  115. aipt_v2/scanners/__init__.py +28 -0
  116. aipt_v2/scanners/base.py +273 -0
  117. aipt_v2/scanners/nikto.py +244 -0
  118. aipt_v2/scanners/nmap.py +402 -0
  119. aipt_v2/scanners/nuclei.py +273 -0
  120. aipt_v2/scanners/web.py +454 -0
  121. aipt_v2/scripts/security_audit.py +366 -0
  122. aipt_v2/setup_wizard.py +941 -0
  123. aipt_v2/skills/__init__.py +80 -0
  124. aipt_v2/skills/agents/__init__.py +14 -0
  125. aipt_v2/skills/agents/api_tester.py +706 -0
  126. aipt_v2/skills/agents/base.py +477 -0
  127. aipt_v2/skills/agents/code_review.py +459 -0
  128. aipt_v2/skills/agents/security_agent.py +336 -0
  129. aipt_v2/skills/agents/web_pentest.py +818 -0
  130. aipt_v2/skills/prompts/__init__.py +647 -0
  131. aipt_v2/system_detector.py +539 -0
  132. aipt_v2/telemetry/__init__.py +7 -0
  133. aipt_v2/telemetry/tracer.py +347 -0
  134. aipt_v2/terminal/__init__.py +28 -0
  135. aipt_v2/terminal/executor.py +400 -0
  136. aipt_v2/terminal/sandbox.py +350 -0
  137. aipt_v2/tools/__init__.py +44 -0
  138. aipt_v2/tools/active_directory/__init__.py +78 -0
  139. aipt_v2/tools/active_directory/ad_config.py +238 -0
  140. aipt_v2/tools/active_directory/bloodhound_wrapper.py +447 -0
  141. aipt_v2/tools/active_directory/kerberos_attacks.py +430 -0
  142. aipt_v2/tools/active_directory/ldap_enum.py +533 -0
  143. aipt_v2/tools/active_directory/smb_attacks.py +505 -0
  144. aipt_v2/tools/agents_graph/__init__.py +19 -0
  145. aipt_v2/tools/agents_graph/agents_graph_actions.py +69 -0
  146. aipt_v2/tools/api_security/__init__.py +76 -0
  147. aipt_v2/tools/api_security/api_discovery.py +608 -0
  148. aipt_v2/tools/api_security/graphql_scanner.py +622 -0
  149. aipt_v2/tools/api_security/jwt_analyzer.py +577 -0
  150. aipt_v2/tools/api_security/openapi_fuzzer.py +761 -0
  151. aipt_v2/tools/browser/__init__.py +5 -0
  152. aipt_v2/tools/browser/browser_actions.py +238 -0
  153. aipt_v2/tools/browser/browser_instance.py +535 -0
  154. aipt_v2/tools/browser/tab_manager.py +344 -0
  155. aipt_v2/tools/cloud/__init__.py +70 -0
  156. aipt_v2/tools/cloud/cloud_config.py +273 -0
  157. aipt_v2/tools/cloud/cloud_scanner.py +639 -0
  158. aipt_v2/tools/cloud/prowler_tool.py +571 -0
  159. aipt_v2/tools/cloud/scoutsuite_tool.py +359 -0
  160. aipt_v2/tools/executor.py +307 -0
  161. aipt_v2/tools/parser.py +408 -0
  162. aipt_v2/tools/proxy/__init__.py +5 -0
  163. aipt_v2/tools/proxy/proxy_actions.py +103 -0
  164. aipt_v2/tools/proxy/proxy_manager.py +789 -0
  165. aipt_v2/tools/registry.py +196 -0
  166. aipt_v2/tools/scanners/__init__.py +343 -0
  167. aipt_v2/tools/scanners/acunetix_tool.py +712 -0
  168. aipt_v2/tools/scanners/burp_tool.py +631 -0
  169. aipt_v2/tools/scanners/config.py +156 -0
  170. aipt_v2/tools/scanners/nessus_tool.py +588 -0
  171. aipt_v2/tools/scanners/zap_tool.py +612 -0
  172. aipt_v2/tools/terminal/__init__.py +5 -0
  173. aipt_v2/tools/terminal/terminal_actions.py +37 -0
  174. aipt_v2/tools/terminal/terminal_manager.py +153 -0
  175. aipt_v2/tools/terminal/terminal_session.py +449 -0
  176. aipt_v2/tools/tool_processing.py +108 -0
  177. aipt_v2/utils/__init__.py +17 -0
  178. aipt_v2/utils/logging.py +202 -0
  179. aipt_v2/utils/model_manager.py +187 -0
  180. aipt_v2/utils/searchers/__init__.py +269 -0
  181. aipt_v2/verify_install.py +793 -0
  182. aiptx-2.0.7.dist-info/METADATA +345 -0
  183. aiptx-2.0.7.dist-info/RECORD +187 -0
  184. aiptx-2.0.7.dist-info/WHEEL +5 -0
  185. aiptx-2.0.7.dist-info/entry_points.txt +7 -0
  186. aiptx-2.0.7.dist-info/licenses/LICENSE +21 -0
  187. aiptx-2.0.7.dist-info/top_level.txt +1 -0
@@ -0,0 +1,297 @@
1
+ """
2
+ PCI-DSS 4.0 Mapping
3
+
4
+ Payment Card Industry Data Security Standard mapping.
5
+ Maps CWEs to PCI-DSS 4.0 requirements.
6
+
7
+ Usage:
8
+ from aipt_v2.compliance import PCIMapper, get_pci_requirement
9
+
10
+ req = get_pci_requirement("CWE-89") # Returns "6.2"
11
+ """
12
+
13
+ from dataclasses import dataclass, field
14
+ from typing import List, Dict, Optional
15
+
16
+
17
+ @dataclass
18
+ class PCIRequirement:
19
+ """PCI-DSS requirement definition."""
20
+ id: str
21
+ name: str
22
+ description: str
23
+ sub_requirements: List[str]
24
+ cwes: List[str]
25
+ testing_procedures: List[str]
26
+
27
+
28
+ # PCI-DSS 4.0 Requirements (security-relevant subset)
29
+ PCI_DSS_REQUIREMENTS = {
30
+ "2.2": PCIRequirement(
31
+ id="2.2",
32
+ name="System Components are Configured and Managed Securely",
33
+ description="Configuration standards are developed, implemented, and maintained "
34
+ "for system components that are consistent with industry-accepted "
35
+ "system hardening standards.",
36
+ sub_requirements=[
37
+ "2.2.1 - Configuration standards are implemented",
38
+ "2.2.2 - Vendor default accounts are managed",
39
+ "2.2.3 - Primary functions are separated on different servers",
40
+ "2.2.4 - Only necessary services and protocols are enabled",
41
+ "2.2.5 - Insecure services and protocols are addressed",
42
+ "2.2.6 - System security parameters are configured",
43
+ "2.2.7 - Non-console administrative access is encrypted"
44
+ ],
45
+ cwes=["CWE-16", "CWE-260", "CWE-611", "CWE-756", "CWE-942"],
46
+ testing_procedures=[
47
+ "Examine configuration standards",
48
+ "Examine system configurations",
49
+ "Interview system administrators"
50
+ ]
51
+ ),
52
+
53
+ "3.4": PCIRequirement(
54
+ id="3.4",
55
+ name="PAN is Rendered Unreadable Anywhere it is Stored",
56
+ description="Primary Account Numbers (PAN) is rendered unreadable anywhere "
57
+ "it is stored using strong cryptography.",
58
+ sub_requirements=[
59
+ "3.4.1 - PAN rendered unreadable via cryptography or truncation",
60
+ "3.4.2 - Technical controls prevent PAN copy/relocation"
61
+ ],
62
+ cwes=["CWE-311", "CWE-312", "CWE-313", "CWE-316"],
63
+ testing_procedures=[
64
+ "Examine data repositories to verify PAN is unreadable",
65
+ "Examine cryptographic key management procedures"
66
+ ]
67
+ ),
68
+
69
+ "3.5": PCIRequirement(
70
+ id="3.5",
71
+ name="Cryptographic Keys are Protected",
72
+ description="Cryptographic keys used to protect stored account data "
73
+ "are secured.",
74
+ sub_requirements=[
75
+ "3.5.1 - Key access restricted to fewest custodians",
76
+ "3.5.1.1 - Service providers: key per customer",
77
+ "3.5.1.2 - Key storage in secure cryptographic device",
78
+ "3.5.1.3 - Key stored in fewest locations"
79
+ ],
80
+ cwes=["CWE-320", "CWE-321", "CWE-326", "CWE-327"],
81
+ testing_procedures=[
82
+ "Examine documented procedures",
83
+ "Interview personnel",
84
+ "Observe key management processes"
85
+ ]
86
+ ),
87
+
88
+ "4.1": PCIRequirement(
89
+ id="4.1",
90
+ name="Strong Cryptography Protects Data During Transmission",
91
+ description="Processes and mechanisms are defined to protect account data "
92
+ "with strong cryptography during transmission over open networks.",
93
+ sub_requirements=[
94
+ "4.1.1 - Security policies and procedures documented",
95
+ "4.1.2 - Roles and responsibilities assigned"
96
+ ],
97
+ cwes=["CWE-319", "CWE-326", "CWE-327", "CWE-523"],
98
+ testing_procedures=[
99
+ "Examine policies and configuration standards",
100
+ "Interview responsible personnel"
101
+ ]
102
+ ),
103
+
104
+ "6.2": PCIRequirement(
105
+ id="6.2",
106
+ name="Bespoke and Custom Software is Developed Securely",
107
+ description="Bespoke and custom software is developed securely, and "
108
+ "software development follows secure software development guidance.",
109
+ sub_requirements=[
110
+ "6.2.1 - Software developed based on industry standards",
111
+ "6.2.2 - Personnel trained in secure development",
112
+ "6.2.3 - Code reviewed for vulnerabilities",
113
+ "6.2.4 - Common software attacks addressed"
114
+ ],
115
+ cwes=["CWE-79", "CWE-89", "CWE-78", "CWE-94", "CWE-502", "CWE-918", "CWE-22",
116
+ "CWE-434", "CWE-352", "CWE-601", "CWE-20"],
117
+ testing_procedures=[
118
+ "Examine secure development procedures",
119
+ "Interview developers",
120
+ "Review code review processes"
121
+ ]
122
+ ),
123
+
124
+ "6.3": PCIRequirement(
125
+ id="6.3",
126
+ name="Security Vulnerabilities are Identified and Addressed",
127
+ description="Security vulnerabilities are identified and addressed.",
128
+ sub_requirements=[
129
+ "6.3.1 - Vulnerabilities identified via reputable sources",
130
+ "6.3.2 - Inventory of bespoke software maintained",
131
+ "6.3.3 - Vulnerabilities addressed via patching"
132
+ ],
133
+ cwes=["CWE-937", "CWE-1035", "CWE-1104"],
134
+ testing_procedures=[
135
+ "Examine processes for identifying vulnerabilities",
136
+ "Interview responsible personnel"
137
+ ]
138
+ ),
139
+
140
+ "7.1": PCIRequirement(
141
+ id="7.1",
142
+ name="Access to System Components is Defined and Assigned",
143
+ description="Processes and mechanisms for restricting access to system "
144
+ "components and cardholder data are defined and understood.",
145
+ sub_requirements=[
146
+ "7.1.1 - Security policies defined and known",
147
+ "7.1.2 - Access control model defined"
148
+ ],
149
+ cwes=["CWE-284", "CWE-285", "CWE-862", "CWE-863", "CWE-639"],
150
+ testing_procedures=[
151
+ "Examine documented policies",
152
+ "Interview personnel"
153
+ ]
154
+ ),
155
+
156
+ "8.3": PCIRequirement(
157
+ id="8.3",
158
+ name="Strong Authentication for Users and Administrators",
159
+ description="Strong authentication for users and administrators is established "
160
+ "and managed.",
161
+ sub_requirements=[
162
+ "8.3.1 - All access authenticated",
163
+ "8.3.2 - Strong cryptography for authentication",
164
+ "8.3.4 - MFA for remote network access",
165
+ "8.3.5 - MFA for all access to CDE",
166
+ "8.3.6 - MFA systems cannot be bypassed",
167
+ "8.3.9 - Passwords have minimum complexity",
168
+ "8.3.10 - Failed login attempts limited"
169
+ ],
170
+ cwes=["CWE-287", "CWE-521", "CWE-798", "CWE-307", "CWE-384", "CWE-306"],
171
+ testing_procedures=[
172
+ "Examine system configuration standards",
173
+ "Observe authentication processes"
174
+ ]
175
+ ),
176
+
177
+ "10.2": PCIRequirement(
178
+ id="10.2",
179
+ name="Audit Logs are Implemented",
180
+ description="Audit logs are implemented to support the detection of "
181
+ "anomalies and suspicious activity.",
182
+ sub_requirements=[
183
+ "10.2.1 - Audit logs enabled and active",
184
+ "10.2.1.1 - User access to CHD logged",
185
+ "10.2.1.2 - Admin actions logged",
186
+ "10.2.1.3 - Access to audit logs logged",
187
+ "10.2.1.4 - Invalid access attempts logged",
188
+ "10.2.1.5 - Changes to auth credentials logged",
189
+ "10.2.1.6 - System/log events logged",
190
+ "10.2.1.7 - Security events logged"
191
+ ],
192
+ cwes=["CWE-778", "CWE-223", "CWE-117", "CWE-532"],
193
+ testing_procedures=[
194
+ "Examine audit log configurations",
195
+ "Interview personnel",
196
+ "Review log samples"
197
+ ]
198
+ ),
199
+
200
+ "11.3": PCIRequirement(
201
+ id="11.3",
202
+ name="External and Internal Vulnerabilities Regularly Identified",
203
+ description="External and internal vulnerabilities are regularly identified, "
204
+ "prioritized, and addressed.",
205
+ sub_requirements=[
206
+ "11.3.1 - Internal vulnerability scans quarterly",
207
+ "11.3.2 - External vulnerability scans quarterly",
208
+ "11.3.3 - Vulnerability scans after significant changes",
209
+ "11.3.4 - Internal penetration testing"
210
+ ],
211
+ cwes=["CWE-937", "CWE-1104"],
212
+ testing_procedures=[
213
+ "Examine scan reports",
214
+ "Interview responsible personnel",
215
+ "Examine remediation processes"
216
+ ]
217
+ )
218
+ }
219
+
220
+
221
+ class PCIMapper:
222
+ """PCI-DSS specific mapper."""
223
+
224
+ def __init__(self):
225
+ self.requirements = PCI_DSS_REQUIREMENTS
226
+
227
+ def get_requirement(self, cwe_id: str) -> Optional[PCIRequirement]:
228
+ """Get PCI requirement for a CWE."""
229
+ cwe_id = cwe_id.upper()
230
+ if not cwe_id.startswith("CWE-"):
231
+ cwe_id = f"CWE-{cwe_id}"
232
+
233
+ for req_id, requirement in self.requirements.items():
234
+ if cwe_id in requirement.cwes:
235
+ return requirement
236
+
237
+ return None
238
+
239
+ def get_requirement_by_id(self, req_id: str) -> Optional[PCIRequirement]:
240
+ """Get PCI requirement by ID."""
241
+ return self.requirements.get(req_id)
242
+
243
+ def get_all_requirements_for_cwe(self, cwe_id: str) -> List[PCIRequirement]:
244
+ """Get all PCI requirements mapped to a CWE."""
245
+ cwe_id = cwe_id.upper()
246
+ if not cwe_id.startswith("CWE-"):
247
+ cwe_id = f"CWE-{cwe_id}"
248
+
249
+ requirements = []
250
+ for requirement in self.requirements.values():
251
+ if cwe_id in requirement.cwes:
252
+ requirements.append(requirement)
253
+
254
+ return requirements
255
+
256
+ def get_compliance_status(self, findings: List[Dict]) -> Dict[str, Dict]:
257
+ """
258
+ Calculate PCI-DSS compliance status based on findings.
259
+
260
+ Args:
261
+ findings: List of findings with CWE IDs
262
+
263
+ Returns:
264
+ Dict with compliance status per requirement
265
+ """
266
+ status = {}
267
+
268
+ for req_id, requirement in self.requirements.items():
269
+ affected_cwes = []
270
+ for finding in findings:
271
+ cwe = finding.get("cwe", finding.get("cwe_id", ""))
272
+ if cwe.upper() in requirement.cwes or f"CWE-{cwe}" in requirement.cwes:
273
+ affected_cwes.append(cwe)
274
+
275
+ status[req_id] = {
276
+ "requirement_name": requirement.name,
277
+ "compliant": len(affected_cwes) == 0,
278
+ "findings_count": len(affected_cwes),
279
+ "affected_cwes": affected_cwes
280
+ }
281
+
282
+ return status
283
+
284
+
285
+ def get_pci_requirement(cwe_id: str) -> Optional[str]:
286
+ """
287
+ Get PCI-DSS requirement ID for a CWE.
288
+
289
+ Args:
290
+ cwe_id: CWE identifier
291
+
292
+ Returns:
293
+ PCI requirement ID or None
294
+ """
295
+ mapper = PCIMapper()
296
+ requirement = mapper.get_requirement(cwe_id)
297
+ return requirement.id if requirement else None
aipt_v2/config.py ADDED
@@ -0,0 +1,341 @@
1
+ """
2
+ AIPT v2 Configuration Management
3
+ ================================
4
+
5
+ Centralized configuration with validation using Pydantic.
6
+ Loads from environment variables with sensible defaults.
7
+ Also loads from ~/.aiptx/.env file created by the setup wizard.
8
+ """
9
+
10
+ import os
11
+ from typing import List, Optional
12
+ from functools import lru_cache
13
+ from pathlib import Path
14
+
15
+ from dotenv import load_dotenv
16
+ from pydantic import BaseModel, Field, field_validator, model_validator
17
+ from pydantic_settings import BaseSettings
18
+
19
+ from .utils.logging import logger
20
+
21
+
22
+ def _load_config_files():
23
+ """
24
+ Load configuration from .env files.
25
+
26
+ Priority (highest to lowest):
27
+ 1. Environment variables (already set in shell)
28
+ 2. Local .env file in current directory
29
+ 3. Global ~/.aiptx/.env file from setup wizard
30
+ """
31
+ # Load global config first (lowest priority)
32
+ global_env = Path.home() / ".aiptx" / ".env"
33
+ if global_env.exists():
34
+ load_dotenv(global_env, override=False)
35
+
36
+ # Load local .env file (higher priority, but doesn't override existing env vars)
37
+ local_env = Path(".env")
38
+ if local_env.exists():
39
+ load_dotenv(local_env, override=False)
40
+
41
+
42
+ # Load config files on module import
43
+ _load_config_files()
44
+
45
+
46
+ class LLMSettings(BaseModel):
47
+ """LLM provider configuration."""
48
+
49
+ provider: str = Field(default="anthropic", description="LLM provider name")
50
+ model: str = Field(default="claude-sonnet-4-20250514", description="Model identifier")
51
+ api_key: Optional[str] = Field(default=None, description="API key")
52
+ api_base: Optional[str] = Field(default=None, description="Custom API base URL")
53
+ timeout: int = Field(default=120, ge=10, le=600, description="Request timeout in seconds")
54
+ max_tokens: int = Field(default=4096, ge=100, le=128000, description="Max response tokens")
55
+ temperature: float = Field(default=0.7, ge=0.0, le=2.0, description="Sampling temperature")
56
+ enable_caching: bool = Field(default=True, description="Enable prompt caching")
57
+
58
+ @field_validator("api_key", mode="before")
59
+ @classmethod
60
+ def get_api_key_from_env(cls, v):
61
+ if v:
62
+ return v
63
+ # Try common environment variables
64
+ for key in ["ANTHROPIC_API_KEY", "OPENAI_API_KEY", "DEEPSEEK_API_KEY", "LLM_API_KEY"]:
65
+ if os.getenv(key):
66
+ return os.getenv(key)
67
+ return None
68
+
69
+
70
+ class ScannerSettings(BaseModel):
71
+ """Enterprise scanner configuration."""
72
+
73
+ # Acunetix
74
+ acunetix_url: Optional[str] = Field(default=None, description="Acunetix API URL")
75
+ acunetix_api_key: Optional[str] = Field(default=None, description="Acunetix API key")
76
+
77
+ # Burp Suite
78
+ burp_url: Optional[str] = Field(default=None, description="Burp Suite API URL")
79
+ burp_api_key: Optional[str] = Field(default=None, description="Burp Suite API key")
80
+
81
+ # Nessus
82
+ nessus_url: Optional[str] = Field(default=None, description="Nessus API URL")
83
+ nessus_access_key: Optional[str] = Field(default=None, description="Nessus access key")
84
+ nessus_secret_key: Optional[str] = Field(default=None, description="Nessus secret key")
85
+
86
+ # OWASP ZAP
87
+ zap_url: Optional[str] = Field(default=None, description="ZAP API URL")
88
+ zap_api_key: Optional[str] = Field(default=None, description="ZAP API key")
89
+
90
+ @field_validator("acunetix_url", "burp_url", "nessus_url", "zap_url", mode="before")
91
+ @classmethod
92
+ def validate_url(cls, v):
93
+ if v and not v.startswith(("http://", "https://")):
94
+ # Auto-prepend http:// if no scheme provided (user-friendly)
95
+ v = f"http://{v}"
96
+ return v
97
+
98
+
99
+ class VPSSettings(BaseModel):
100
+ """VPS execution configuration."""
101
+
102
+ host: Optional[str] = Field(default=None, description="VPS hostname or IP")
103
+ user: str = Field(default="ubuntu", description="SSH username")
104
+ key_path: Optional[str] = Field(default=None, description="Path to SSH private key")
105
+ port: int = Field(default=22, ge=1, le=65535, description="SSH port")
106
+ # Security: Use /var/tmp for longer-lived temp files (survives reboots)
107
+ # The directory should be created with restricted permissions (700) on the VPS
108
+ results_dir: str = Field(
109
+ default="/var/tmp/aipt_results",
110
+ description="Remote results directory (should be created with mode 700)"
111
+ )
112
+ timeout: int = Field(default=300, ge=30, le=3600, description="Command timeout in seconds")
113
+
114
+ @field_validator("key_path", mode="before")
115
+ @classmethod
116
+ def expand_key_path(cls, v):
117
+ if v:
118
+ return str(Path(v).expanduser().resolve())
119
+ return v
120
+
121
+
122
+ class APISettings(BaseModel):
123
+ """REST API configuration."""
124
+
125
+ # Security: Default to localhost to avoid accidental exposure (CWE-605)
126
+ # Use AIPT_API__HOST=0.0.0.0 for production deployments behind a reverse proxy
127
+ host: str = Field(default="127.0.0.1", description="API host (use 0.0.0.0 for network access)")
128
+ port: int = Field(default=8000, ge=1, le=65535, description="API port")
129
+ cors_origins: List[str] = Field(
130
+ default=["http://localhost:3000"],
131
+ description="Allowed CORS origins"
132
+ )
133
+ rate_limit: str = Field(default="100/minute", description="Rate limit per client")
134
+ enable_docs: bool = Field(default=True, description="Enable Swagger/OpenAPI docs")
135
+
136
+
137
+ class DatabaseSettings(BaseModel):
138
+ """Database configuration."""
139
+
140
+ url: str = Field(default="sqlite:///./aipt.db", description="Database connection URL")
141
+ echo: bool = Field(default=False, description="Echo SQL queries")
142
+ pool_size: int = Field(default=5, ge=1, le=100, description="Connection pool size")
143
+
144
+
145
+ class LoggingSettings(BaseModel):
146
+ """Logging configuration."""
147
+
148
+ level: str = Field(default="INFO", description="Log level")
149
+ format: str = Field(default="console", description="Log format (console or json)")
150
+ redact_secrets: bool = Field(default=True, description="Redact sensitive values in logs")
151
+
152
+
153
+ class AIPTConfig(BaseSettings):
154
+ """
155
+ Main AIPT v2 configuration.
156
+
157
+ Loads from environment variables with AIPT_ prefix.
158
+ """
159
+
160
+ # Sub-configurations
161
+ llm: LLMSettings = Field(default_factory=LLMSettings)
162
+ scanners: ScannerSettings = Field(default_factory=ScannerSettings)
163
+ vps: VPSSettings = Field(default_factory=VPSSettings)
164
+ api: APISettings = Field(default_factory=APISettings)
165
+ database: DatabaseSettings = Field(default_factory=DatabaseSettings)
166
+ logging: LoggingSettings = Field(default_factory=LoggingSettings)
167
+
168
+ # General settings
169
+ sandbox_mode: bool = Field(default=False, description="Run tools in sandbox")
170
+ output_dir: Path = Field(default=Path("./results"), description="Output directory")
171
+ reports_dir: Path = Field(default=Path("./reports"), description="Reports directory")
172
+
173
+ model_config = {
174
+ "env_prefix": "AIPT_",
175
+ "env_nested_delimiter": "__",
176
+ "case_sensitive": False,
177
+ }
178
+
179
+ @model_validator(mode="after")
180
+ def create_directories(self):
181
+ """Ensure output directories exist."""
182
+ self.output_dir.mkdir(parents=True, exist_ok=True)
183
+ self.reports_dir.mkdir(parents=True, exist_ok=True)
184
+ return self
185
+
186
+
187
+ @lru_cache(maxsize=1)
188
+ def get_config() -> AIPTConfig:
189
+ """
190
+ Get the global configuration instance.
191
+
192
+ Returns:
193
+ AIPTConfig instance loaded from environment
194
+ """
195
+ # Load from environment
196
+ # Note: Setup wizard saves with AIPT_ prefix and __ delimiter (e.g., AIPT_LLM__PROVIDER)
197
+ # We check both formats for backwards compatibility
198
+ config = AIPTConfig(
199
+ llm=LLMSettings(
200
+ provider=os.getenv("AIPT_LLM__PROVIDER") or os.getenv("AIPT_LLM_PROVIDER", "anthropic"),
201
+ model=os.getenv("AIPT_LLM__MODEL") or os.getenv("AIPT_LLM_MODEL", "claude-sonnet-4-20250514"),
202
+ api_key=os.getenv("ANTHROPIC_API_KEY") or os.getenv("OPENAI_API_KEY") or os.getenv("DEEPSEEK_API_KEY") or os.getenv("LLM_API_KEY"),
203
+ timeout=int(os.getenv("AIPT_LLM__TIMEOUT") or os.getenv("AIPT_LLM_TIMEOUT", "120")),
204
+ ),
205
+ scanners=ScannerSettings(
206
+ acunetix_url=os.getenv("AIPT_SCANNERS__ACUNETIX_URL") or os.getenv("ACUNETIX_URL"),
207
+ acunetix_api_key=os.getenv("AIPT_SCANNERS__ACUNETIX_API_KEY") or os.getenv("ACUNETIX_API_KEY"),
208
+ burp_url=os.getenv("AIPT_SCANNERS__BURP_URL") or os.getenv("BURP_URL"),
209
+ burp_api_key=os.getenv("AIPT_SCANNERS__BURP_API_KEY") or os.getenv("BURP_API_KEY"),
210
+ nessus_url=os.getenv("AIPT_SCANNERS__NESSUS_URL") or os.getenv("NESSUS_URL"),
211
+ nessus_access_key=os.getenv("AIPT_SCANNERS__NESSUS_ACCESS_KEY") or os.getenv("NESSUS_ACCESS_KEY"),
212
+ nessus_secret_key=os.getenv("AIPT_SCANNERS__NESSUS_SECRET_KEY") or os.getenv("NESSUS_SECRET_KEY"),
213
+ zap_url=os.getenv("AIPT_SCANNERS__ZAP_URL") or os.getenv("ZAP_URL"),
214
+ zap_api_key=os.getenv("AIPT_SCANNERS__ZAP_API_KEY") or os.getenv("ZAP_API_KEY"),
215
+ ),
216
+ vps=VPSSettings(
217
+ host=os.getenv("AIPT_VPS__HOST") or os.getenv("VPS_HOST"),
218
+ user=os.getenv("AIPT_VPS__USER") or os.getenv("VPS_USER", "ubuntu"),
219
+ key_path=os.getenv("AIPT_VPS__KEY_PATH") or os.getenv("VPS_KEY"),
220
+ ),
221
+ api=APISettings(
222
+ cors_origins=os.getenv("AIPT_CORS_ORIGINS", "http://localhost:3000").split(","),
223
+ rate_limit=os.getenv("AIPT_RATE_LIMIT", "100/minute"),
224
+ ),
225
+ database=DatabaseSettings(
226
+ url=os.getenv("DATABASE_URL", "sqlite:///./aipt.db"),
227
+ ),
228
+ logging=LoggingSettings(
229
+ level=os.getenv("AIPT_LOG_LEVEL", "WARNING"), # Default to WARNING for cleaner output
230
+ format=os.getenv("AIPT_LOG_FORMAT", "console"),
231
+ ),
232
+ sandbox_mode=os.getenv("AIPT_SANDBOX_MODE", "false").lower() == "true",
233
+ )
234
+
235
+ # Only log configuration details at DEBUG level for cleaner default output
236
+ logger.debug(
237
+ "Configuration loaded",
238
+ llm_provider=config.llm.provider,
239
+ llm_model=config.llm.model,
240
+ has_llm_key=bool(config.llm.api_key),
241
+ has_acunetix=bool(config.scanners.acunetix_url),
242
+ has_burp=bool(config.scanners.burp_url),
243
+ has_nessus=bool(config.scanners.nessus_url),
244
+ has_vps=bool(config.vps.host),
245
+ sandbox_mode=config.sandbox_mode,
246
+ )
247
+
248
+ return config
249
+
250
+
251
+ def reload_config() -> AIPTConfig:
252
+ """
253
+ Reload configuration from files and environment.
254
+
255
+ This clears the cached config and reloads from:
256
+ - ~/.aiptx/.env (setup wizard config)
257
+ - ./.env (local project config)
258
+ - Environment variables
259
+
260
+ Useful after running the setup wizard.
261
+
262
+ Returns:
263
+ Fresh AIPTConfig instance
264
+ """
265
+ # Clear the cached config
266
+ get_config.cache_clear()
267
+
268
+ # Reload .env files
269
+ _load_config_files()
270
+
271
+ # Return fresh config
272
+ return get_config()
273
+
274
+
275
+ def validate_config_for_features(features: List[str]) -> List[str]:
276
+ """
277
+ Validate that required configuration is present for requested features.
278
+
279
+ Args:
280
+ features: List of feature names to validate
281
+
282
+ Returns:
283
+ List of error messages (empty if all valid)
284
+ """
285
+ config = get_config()
286
+ errors = []
287
+
288
+ if "llm" in features and not config.llm.api_key:
289
+ errors.append(
290
+ "LLM API key required. Set ANTHROPIC_API_KEY or OPENAI_API_KEY environment variable."
291
+ )
292
+
293
+ if "acunetix" in features:
294
+ if not config.scanners.acunetix_url:
295
+ errors.append("Acunetix URL required. Set ACUNETIX_URL environment variable.")
296
+ if not config.scanners.acunetix_api_key:
297
+ errors.append("Acunetix API key required. Set ACUNETIX_API_KEY environment variable.")
298
+
299
+ if "burp" in features:
300
+ if not config.scanners.burp_url:
301
+ errors.append("Burp Suite URL required. Set BURP_URL environment variable.")
302
+ if not config.scanners.burp_api_key:
303
+ errors.append("Burp Suite API key required. Set BURP_API_KEY environment variable.")
304
+
305
+ if "nessus" in features:
306
+ if not config.scanners.nessus_url:
307
+ errors.append("Nessus URL required. Set NESSUS_URL environment variable.")
308
+ if not config.scanners.nessus_access_key:
309
+ errors.append("Nessus access key required. Set NESSUS_ACCESS_KEY environment variable.")
310
+ if not config.scanners.nessus_secret_key:
311
+ errors.append("Nessus secret key required. Set NESSUS_SECRET_KEY environment variable.")
312
+
313
+ if "vps" in features:
314
+ if not config.vps.host:
315
+ errors.append("VPS host required. Set VPS_HOST environment variable.")
316
+ if not config.vps.key_path:
317
+ errors.append("VPS SSH key path required. Set VPS_KEY environment variable.")
318
+ elif not Path(config.vps.key_path).exists():
319
+ errors.append(f"VPS SSH key not found: {config.vps.key_path}")
320
+
321
+ return errors
322
+
323
+
324
+ # Convenience function
325
+ def require_config(*features: str) -> AIPTConfig:
326
+ """
327
+ Get config and raise if required features are not configured.
328
+
329
+ Args:
330
+ *features: Feature names to validate
331
+
332
+ Returns:
333
+ AIPTConfig instance
334
+
335
+ Raises:
336
+ ValueError: If required configuration is missing
337
+ """
338
+ errors = validate_config_for_features(list(features))
339
+ if errors:
340
+ raise ValueError("Configuration errors:\n" + "\n".join(f" - {e}" for e in errors))
341
+ return get_config()
@@ -0,0 +1,43 @@
1
+ """
2
+ AIPT Core Module
3
+
4
+ LangGraph-based autonomous pentesting agent with:
5
+ - Multi-provider LLM abstraction (OpenAI, Anthropic, Ollama)
6
+ - Memory management with automatic compression
7
+ - State machine for pentest workflow
8
+
9
+ Inspired by: Strix (LangGraph state machine, 300 iterations)
10
+ """
11
+ from __future__ import annotations
12
+
13
+ from .llm import (
14
+ LLMProvider,
15
+ LLMResponse,
16
+ OpenAIProvider,
17
+ AnthropicProvider,
18
+ OllamaProvider,
19
+ get_llm,
20
+ )
21
+ from .memory import MemoryManager, MemoryConfig
22
+ from .agent import AIPTAgent, PentestState, Phase
23
+ from .ptt import PTTTracker, PTTNode
24
+
25
+ __all__ = [
26
+ # LLM
27
+ "LLMProvider",
28
+ "LLMResponse",
29
+ "OpenAIProvider",
30
+ "AnthropicProvider",
31
+ "OllamaProvider",
32
+ "get_llm",
33
+ # Memory
34
+ "MemoryManager",
35
+ "MemoryConfig",
36
+ # Agent
37
+ "AIPTAgent",
38
+ "PentestState",
39
+ "Phase",
40
+ # PTT
41
+ "PTTTracker",
42
+ "PTTNode",
43
+ ]