vexa-core 1.0.35__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 (83) hide show
  1. vexa_core-1.0.35/LICENSE +21 -0
  2. vexa_core-1.0.35/PKG-INFO +81 -0
  3. vexa_core-1.0.35/README.md +32 -0
  4. vexa_core-1.0.35/pyproject.toml +62 -0
  5. vexa_core-1.0.35/setup.cfg +4 -0
  6. vexa_core-1.0.35/setup.py +5 -0
  7. vexa_core-1.0.35/src/vexa/__init__.py +19 -0
  8. vexa_core-1.0.35/src/vexa/ai_providers/__init__.py +0 -0
  9. vexa_core-1.0.35/src/vexa/ai_providers/anthropic_provider.py +144 -0
  10. vexa_core-1.0.35/src/vexa/ai_providers/azure_cli.py +424 -0
  11. vexa_core-1.0.35/src/vexa/ai_providers/base.py +91 -0
  12. vexa_core-1.0.35/src/vexa/ai_providers/google_cli.py +184 -0
  13. vexa_core-1.0.35/src/vexa/ai_providers/google_sdk.py +244 -0
  14. vexa_core-1.0.35/src/vexa/ai_providers/guides.py +50 -0
  15. vexa_core-1.0.35/src/vexa/ai_providers/kiro_cli.py +417 -0
  16. vexa_core-1.0.35/src/vexa/ai_providers/manager.py +701 -0
  17. vexa_core-1.0.35/src/vexa/ai_providers/ollama_provider.py +409 -0
  18. vexa_core-1.0.35/src/vexa/ai_providers/openai_provider.py +143 -0
  19. vexa_core-1.0.35/src/vexa/ai_providers/prompts.py +313 -0
  20. vexa_core-1.0.35/src/vexa/ai_providers/triage.py +472 -0
  21. vexa_core-1.0.35/src/vexa/attestation/__init__.py +9 -0
  22. vexa_core-1.0.35/src/vexa/attestation/attestation_builder.py +158 -0
  23. vexa_core-1.0.35/src/vexa/attestation/verifier.py +119 -0
  24. vexa_core-1.0.35/src/vexa/common/__init__.py +64 -0
  25. vexa_core-1.0.35/src/vexa/common/cloud_provider.py +253 -0
  26. vexa_core-1.0.35/src/vexa/common/config.py +105 -0
  27. vexa_core-1.0.35/src/vexa/common/config_manager.py +90 -0
  28. vexa_core-1.0.35/src/vexa/common/logging.py +216 -0
  29. vexa_core-1.0.35/src/vexa/common/models.py +261 -0
  30. vexa_core-1.0.35/src/vexa/common/path_filter.py +66 -0
  31. vexa_core-1.0.35/src/vexa/common/performance.py +111 -0
  32. vexa_core-1.0.35/src/vexa/jobs/__init__.py +18 -0
  33. vexa_core-1.0.35/src/vexa/jobs/manager.py +421 -0
  34. vexa_core-1.0.35/src/vexa/rag/__init__.py +6 -0
  35. vexa_core-1.0.35/src/vexa/rag/context_builder.py +133 -0
  36. vexa_core-1.0.35/src/vexa/rag/indexer.py +229 -0
  37. vexa_core-1.0.35/src/vexa/rag/vector_store.py +127 -0
  38. vexa_core-1.0.35/src/vexa/reports/__init__.py +34 -0
  39. vexa_core-1.0.35/src/vexa/reports/generator.py +217 -0
  40. vexa_core-1.0.35/src/vexa/reports/html.py +761 -0
  41. vexa_core-1.0.35/src/vexa/reports/json.py +147 -0
  42. vexa_core-1.0.35/src/vexa/reports/markdown.py +294 -0
  43. vexa_core-1.0.35/src/vexa/reports/sarif.py +286 -0
  44. vexa_core-1.0.35/src/vexa/reports/sbom.py +94 -0
  45. vexa_core-1.0.35/src/vexa/scanners/__init__.py +63 -0
  46. vexa_core-1.0.35/src/vexa/scanners/bandit.py +193 -0
  47. vexa_core-1.0.35/src/vexa/scanners/base.py +372 -0
  48. vexa_core-1.0.35/src/vexa/scanners/checkov.py +202 -0
  49. vexa_core-1.0.35/src/vexa/scanners/data_merger.py +270 -0
  50. vexa_core-1.0.35/src/vexa/scanners/deduplication_engine.py +282 -0
  51. vexa_core-1.0.35/src/vexa/scanners/detect_secrets.py +144 -0
  52. vexa_core-1.0.35/src/vexa/scanners/engine.py +492 -0
  53. vexa_core-1.0.35/src/vexa/scanners/framework_mapper.py +158 -0
  54. vexa_core-1.0.35/src/vexa/scanners/grype.py +128 -0
  55. vexa_core-1.0.35/src/vexa/scanners/npm_audit.py +134 -0
  56. vexa_core-1.0.35/src/vexa/scanners/pip_audit.py +149 -0
  57. vexa_core-1.0.35/src/vexa/scanners/pip_licenses.py +129 -0
  58. vexa_core-1.0.35/src/vexa/scanners/semgrep.py +130 -0
  59. vexa_core-1.0.35/src/vexa/scanners/syft.py +115 -0
  60. vexa_core-1.0.35/src/vexa/security/__init__.py +45 -0
  61. vexa_core-1.0.35/src/vexa/security/output_sanitizer.py +202 -0
  62. vexa_core-1.0.35/src/vexa/security/security_validator.py +300 -0
  63. vexa_core-1.0.35/src/vexa/security/subprocess_runner.py +369 -0
  64. vexa_core-1.0.35/src/vexa/security/validators.py +300 -0
  65. vexa_core-1.0.35/src/vexa/security_matrix/__init__.py +0 -0
  66. vexa_core-1.0.35/src/vexa/security_matrix/file_filter.py +0 -0
  67. vexa_core-1.0.35/src/vexa/security_matrix/neolifter.py +0 -0
  68. vexa_core-1.0.35/src/vexa/security_validate/__init__.py +0 -0
  69. vexa_core-1.0.35/src/vexa/security_validate/cdk.py +0 -0
  70. vexa_core-1.0.35/src/vexa/security_validate/cloudformation.py +0 -0
  71. vexa_core-1.0.35/src/vexa/security_validate/severity.py +0 -0
  72. vexa_core-1.0.35/src/vexa/security_validate/terraform.py +0 -0
  73. vexa_core-1.0.35/src/vexa/telemetry/__init__.py +3 -0
  74. vexa_core-1.0.35/src/vexa/telemetry/client.py +90 -0
  75. vexa_core-1.0.35/src/vexa/threat_model/__init__.py +0 -0
  76. vexa_core-1.0.35/src/vexa/threat_model/action_plan.py +0 -0
  77. vexa_core-1.0.35/src/vexa/threat_model/stride_engine.py +0 -0
  78. vexa_core-1.0.35/src/vexa_core.egg-info/PKG-INFO +81 -0
  79. vexa_core-1.0.35/src/vexa_core.egg-info/SOURCES.txt +81 -0
  80. vexa_core-1.0.35/src/vexa_core.egg-info/dependency_links.txt +1 -0
  81. vexa_core-1.0.35/src/vexa_core.egg-info/requires.txt +31 -0
  82. vexa_core-1.0.35/src/vexa_core.egg-info/top_level.txt +1 -0
  83. vexa_core-1.0.35/tests/test_openai_provider.py +82 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 noviqtechnologies
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,81 @@
1
+ Metadata-Version: 2.4
2
+ Name: vexa-core
3
+ Version: 1.0.35
4
+ Summary: Enterprise-grade security analysis core engine — air-gapped scanning with AI-powered fixes
5
+ Author-email: Noviq Technologies <support@noviqtechnologies.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://codesecure.dev
8
+ Project-URL: Repository, https://github.com/noviqtechnologies/vexa
9
+ Project-URL: Documentation, https://github.com/noviqtechnologies/vexa/blob/main/docs/QUICKSTART.md
10
+ Project-URL: Issues, https://github.com/noviqtechnologies/vexa/issues
11
+ Keywords: security,sast,vulnerability,scanner,privacy,ai,bandit,semgrep,checkov
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.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Security
20
+ Classifier: Topic :: Software Development :: Quality Assurance
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: pydantic>=2.0.0
25
+ Requires-Dist: jinja2>=3.1.0
26
+ Requires-Dist: asyncio>=3.4.3
27
+ Requires-Dist: rich>=13.0.0
28
+ Requires-Dist: mermaid-py>=0.1.0
29
+ Requires-Dist: markdown>=3.5.2
30
+ Requires-Dist: pygments>=2.17.2
31
+ Requires-Dist: packaging>=24.0
32
+ Requires-Dist: bandit>=1.7.0
33
+ Requires-Dist: semgrep>=1.0.0; sys_platform != "win32"
34
+ Requires-Dist: checkov>=3.0.0
35
+ Requires-Dist: detect-secrets>=1.4.0
36
+ Requires-Dist: pip-audit>=2.0.0
37
+ Requires-Dist: pip-licenses>=4.0.0
38
+ Requires-Dist: pyyaml>=6.0
39
+ Provides-Extra: google
40
+ Requires-Dist: google-genai>=1.0.0; extra == "google"
41
+ Provides-Extra: openai
42
+ Requires-Dist: openai>=1.0.0; extra == "openai"
43
+ Provides-Extra: anthropicai
44
+ Requires-Dist: anthropic>=0.40.0; extra == "anthropicai"
45
+ Provides-Extra: aws
46
+ Provides-Extra: all
47
+ Requires-Dist: vexa-core[anthropicai,google,openai]; extra == "all"
48
+ Dynamic: license-file
49
+
50
+ # Vexa Core SDK
51
+ ![Vexa Logo](logo.png)
52
+ The fundamental engine powering AI-native security analysis.
53
+
54
+ Vexa Core provides the underlying logic for multi-scanner orchestration, AI-powered remediation, and security audit logging.
55
+
56
+ ### Installation
57
+ ```bash
58
+ pip install vexa-core
59
+ ```
60
+
61
+ ### Getting Started
62
+ ```python
63
+ from vexa.core.engine import ScanEngine
64
+ from vexa.ai_providers import AIManager
65
+
66
+ # Initialize engine with default scanners
67
+ engine = ScanEngine(scanners=['bandit', 'semgrep'])
68
+
69
+ # Run analysis
70
+ findings = engine.scan_file("insecure.py")
71
+
72
+ for finding in findings:
73
+ print(f"[{finding.severity}] {finding.title}: {finding.description}")
74
+ ```
75
+
76
+ ### Requirements
77
+ - Python 3.9+
78
+ - Security Scanners (Bandit, Semgrep, etc.) installed on PATH.
79
+
80
+ ### License
81
+ MIT License.
@@ -0,0 +1,32 @@
1
+ # Vexa Core SDK
2
+ ![Vexa Logo](logo.png)
3
+ The fundamental engine powering AI-native security analysis.
4
+
5
+ Vexa Core provides the underlying logic for multi-scanner orchestration, AI-powered remediation, and security audit logging.
6
+
7
+ ### Installation
8
+ ```bash
9
+ pip install vexa-core
10
+ ```
11
+
12
+ ### Getting Started
13
+ ```python
14
+ from vexa.core.engine import ScanEngine
15
+ from vexa.ai_providers import AIManager
16
+
17
+ # Initialize engine with default scanners
18
+ engine = ScanEngine(scanners=['bandit', 'semgrep'])
19
+
20
+ # Run analysis
21
+ findings = engine.scan_file("insecure.py")
22
+
23
+ for finding in findings:
24
+ print(f"[{finding.severity}] {finding.title}: {finding.description}")
25
+ ```
26
+
27
+ ### Requirements
28
+ - Python 3.9+
29
+ - Security Scanners (Bandit, Semgrep, etc.) installed on PATH.
30
+
31
+ ### License
32
+ MIT License.
@@ -0,0 +1,62 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "vexa-core"
7
+ version = "1.0.35"
8
+ description = "Enterprise-grade security analysis core engine — air-gapped scanning with AI-powered fixes"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = {text = "MIT"}
12
+ authors = [{name = "Noviq Technologies", email = "support@noviqtechnologies.com"}]
13
+ keywords = ["security", "sast", "vulnerability", "scanner", "privacy", "ai", "bandit", "semgrep", "checkov"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.10",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Topic :: Security",
23
+ "Topic :: Software Development :: Quality Assurance",
24
+ ]
25
+
26
+
27
+ dependencies = [
28
+ "pydantic>=2.0.0",
29
+ "jinja2>=3.1.0",
30
+ "asyncio>=3.4.3",
31
+ "rich>=13.0.0",
32
+ "mermaid-py>=0.1.0",
33
+ "markdown>=3.5.2",
34
+ "pygments>=2.17.2",
35
+ "packaging>=24.0",
36
+ # Scanners
37
+ "bandit>=1.7.0",
38
+ "semgrep>=1.0.0; sys_platform != 'win32'",
39
+ "checkov>=3.0.0",
40
+ "detect-secrets>=1.4.0",
41
+ "pip-audit>=2.0.0",
42
+ "pip-licenses>=4.0.0",
43
+ "pyyaml>=6.0",
44
+ ]
45
+
46
+ [project.optional-dependencies]
47
+ google = ["google-genai>=1.0.0"]
48
+ openai = ["openai>=1.0.0"]
49
+ anthropicai = ["anthropic>=0.40.0"]
50
+ # aws = ["kiro-cli>=1.0.0"] # Disabled: not on PyPI, CLI provider disabled
51
+ aws = []
52
+ all = ["vexa-core[google,openai,anthropicai]"]
53
+
54
+ [tool.setuptools.packages.find]
55
+ where = ["src"]
56
+ include = ["vexa*"]
57
+
58
+ [project.urls]
59
+ Homepage = "https://codesecure.dev"
60
+ Repository = "https://github.com/noviqtechnologies/vexa"
61
+ Documentation = "https://github.com/noviqtechnologies/vexa/blob/main/docs/QUICKSTART.md"
62
+ Issues = "https://github.com/noviqtechnologies/vexa/issues"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,5 @@
1
+ from setuptools import setup
2
+
3
+ # Delegate to pyproject.toml
4
+ if __name__ == "__main__":
5
+ setup()
@@ -0,0 +1,19 @@
1
+ """
2
+ Vexa - Enterprise Security Analysis Platform.
3
+ """
4
+
5
+ try:
6
+ from importlib.metadata import version, PackageNotFoundError
7
+ except ImportError:
8
+ # Fallback for Python < 3.8
9
+ try:
10
+ from importlib_metadata import version, PackageNotFoundError
11
+ except ImportError:
12
+ version = lambda _: "unknown"
13
+ PackageNotFoundError = Exception
14
+
15
+ try:
16
+ __version__ = version("vexa-core")
17
+ except (PackageNotFoundError, NameError, ImportError):
18
+ # Fallback for development where the package is not installed
19
+ __version__ = "1.0.35"
File without changes
@@ -0,0 +1,144 @@
1
+ import asyncio
2
+ from typing import List, Dict, Any, Optional
3
+
4
+ from vexa.common.models import Finding, EnhancedFinding
5
+ from vexa.common.logging import get_logger
6
+ from vexa.ai_providers.base import (
7
+ BaseAIProvider,
8
+ AIProviderType,
9
+ AIProviderStatus,
10
+ )
11
+ from vexa.ai_providers.prompts import GenericPromptBuilder, GenericMarkdownParser
12
+ from vexa.common.config import get_env
13
+
14
+ logger = get_logger(__name__)
15
+
16
+
17
+ class AnthropicWrapper(BaseAIProvider):
18
+ """Anthropic Provider Implementation"""
19
+
20
+ PROVIDER_TYPE = AIProviderType.ANTHROPIC
21
+
22
+ def __init__(self):
23
+ self.prompt_builder = GenericPromptBuilder()
24
+ self.parser = GenericMarkdownParser()
25
+ self._api_key = get_env("VEXA_ANTHROPIC_API_KEY", "")
26
+ self._model = get_env("VEXA_ANTHROPIC_MODEL", "claude-sonnet-4-20250514")
27
+
28
+ def _get_client(self):
29
+ try:
30
+ import anthropic
31
+ return anthropic.AsyncAnthropic(api_key=self._api_key)
32
+ except ImportError:
33
+ raise RuntimeError("anthropic SDK not installed")
34
+
35
+ def set_api_key(self, api_key: str):
36
+ self._api_key = api_key
37
+
38
+ def set_model(self, model: str):
39
+ self._model = model
40
+
41
+ @property
42
+ def is_available(self) -> bool:
43
+ try:
44
+ import anthropic
45
+ return bool(self._api_key)
46
+ except ImportError:
47
+ return False
48
+
49
+ async def check_availability(self) -> tuple[AIProviderStatus, str]:
50
+ try:
51
+ import anthropic
52
+ except ImportError:
53
+ return AIProviderStatus.UNAVAILABLE, "Anthropic SDK not found (install with 'pip install anthropic')"
54
+
55
+ if not self._api_key:
56
+ return AIProviderStatus.UNAVAILABLE, "VEXA_ANTHROPIC_API_KEY is not set"
57
+
58
+ return AIProviderStatus.AVAILABLE, "Ready"
59
+
60
+ def _classify_error(self, err_msg: str, status_code: Optional[int] = None) -> str:
61
+ err_lower = err_msg.lower()
62
+ if status_code in (401, 403) or any(w in err_lower for w in ["invalid x-api-key", "authentication"]):
63
+ return "auth"
64
+ if status_code == 429 or any(w in err_lower for w in ["rate_limit", "too many requests"]):
65
+ return "rate_limit"
66
+ return "other"
67
+
68
+ async def test_connection(self) -> tuple[AIProviderStatus, str]:
69
+ status, msg = await self.check_availability()
70
+ if status != AIProviderStatus.AVAILABLE:
71
+ return status, msg
72
+
73
+ try:
74
+ client = self._get_client()
75
+ logger.info("Validating Anthropic API key with model %s...", self._model)
76
+ await client.messages.create(
77
+ model=self._model,
78
+ messages=[{"role": "user", "content": "Reply with 'ok'"}],
79
+ max_tokens=5,
80
+ )
81
+ return AIProviderStatus.AVAILABLE, "Ready"
82
+ except Exception as e:
83
+ err_type = self._classify_error(str(e), getattr(e, "status_code", None))
84
+ if err_type == "auth":
85
+ return AIProviderStatus.ERROR, f"Anthropic Auth Error: {e}"
86
+ if err_type == "rate_limit":
87
+ return AIProviderStatus.ERROR, f"Anthropic Rate Limit Error: {e}"
88
+ return AIProviderStatus.ERROR, f"Anthropic Connection Failed: {str(e)}"
89
+
90
+ async def analyze_findings_batch(
91
+ self,
92
+ findings: List[Finding],
93
+ code_contexts: Dict[str, str],
94
+ batch_size: int = 10,
95
+ app_context: Optional[Dict[str, Any]] = None,
96
+ is_workspace_scan: bool = False
97
+ ) -> List[EnhancedFinding]:
98
+
99
+ if not findings:
100
+ return []
101
+
102
+ client = self._get_client()
103
+ prompt = self.prompt_builder.build_batch_prompt(findings, app_context=app_context, is_workspace_scan=is_workspace_scan)
104
+
105
+ system_prompt = (
106
+ "You are Vexa, an expert AI security assistant. "
107
+ "Analyze security findings and provide remediation in Markdown format. "
108
+ "Follow the ZERO-CHATTER RULE: remediation code blocks must contain "
109
+ "ONLY pure source code, no explanations."
110
+ )
111
+
112
+ try:
113
+ logger.info("Sending batch of %d findings to Anthropic (%s)...", len(findings), self._model)
114
+
115
+ response = await client.messages.create(
116
+ model=self._model,
117
+ system=system_prompt,
118
+ messages=[
119
+ {"role": "user", "content": prompt}
120
+ ],
121
+ temperature=0.2,
122
+ max_tokens=4096,
123
+ )
124
+
125
+ text = response.content[0].text if response.content else ""
126
+ logger.debug("Received AI response length: %d characters", len(text))
127
+
128
+ return self.parser.parse(text, findings)
129
+
130
+ except Exception as e:
131
+ err_type = self._classify_error(str(e), getattr(e, "status_code", None))
132
+ if err_type == "rate_limit":
133
+ raise RuntimeError(f"Anthropic Rate Limit Exceeded: {e}")
134
+ logger.exception("Anthropic Analysis failed: %s", e)
135
+ raise e
136
+
137
+ def enhance_finding(self, finding: Finding, analysis: Any) -> EnhancedFinding:
138
+ pass
139
+
140
+ async def generate_stride_analysis(self, repo_path: Any, category: str) -> Dict[str, Any]:
141
+ return {"error": "Not implemented"}
142
+
143
+ def get_anthropic_wrapper() -> AnthropicWrapper:
144
+ return AnthropicWrapper()