agent-audit 0.1.0__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 (37) hide show
  1. agent_audit/__init__.py +3 -0
  2. agent_audit/__main__.py +13 -0
  3. agent_audit/cli/__init__.py +1 -0
  4. agent_audit/cli/commands/__init__.py +1 -0
  5. agent_audit/cli/commands/init.py +44 -0
  6. agent_audit/cli/commands/inspect.py +236 -0
  7. agent_audit/cli/commands/scan.py +329 -0
  8. agent_audit/cli/formatters/__init__.py +1 -0
  9. agent_audit/cli/formatters/json.py +138 -0
  10. agent_audit/cli/formatters/sarif.py +155 -0
  11. agent_audit/cli/formatters/terminal.py +221 -0
  12. agent_audit/cli/main.py +34 -0
  13. agent_audit/config/__init__.py +1 -0
  14. agent_audit/config/ignore.py +477 -0
  15. agent_audit/core_utils/__init__.py +1 -0
  16. agent_audit/models/__init__.py +18 -0
  17. agent_audit/models/finding.py +159 -0
  18. agent_audit/models/risk.py +77 -0
  19. agent_audit/models/tool.py +182 -0
  20. agent_audit/rules/__init__.py +6 -0
  21. agent_audit/rules/engine.py +503 -0
  22. agent_audit/rules/loader.py +160 -0
  23. agent_audit/scanners/__init__.py +5 -0
  24. agent_audit/scanners/base.py +32 -0
  25. agent_audit/scanners/config_scanner.py +390 -0
  26. agent_audit/scanners/mcp_config_scanner.py +321 -0
  27. agent_audit/scanners/mcp_inspector.py +421 -0
  28. agent_audit/scanners/python_scanner.py +544 -0
  29. agent_audit/scanners/secret_scanner.py +521 -0
  30. agent_audit/utils/__init__.py +21 -0
  31. agent_audit/utils/compat.py +98 -0
  32. agent_audit/utils/mcp_client.py +343 -0
  33. agent_audit/version.py +3 -0
  34. agent_audit-0.1.0.dist-info/METADATA +219 -0
  35. agent_audit-0.1.0.dist-info/RECORD +37 -0
  36. agent_audit-0.1.0.dist-info/WHEEL +4 -0
  37. agent_audit-0.1.0.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,343 @@
1
+ """MCP protocol client with STDIO and SSE transports."""
2
+
3
+ import asyncio
4
+ import json
5
+ import logging
6
+ import sys
7
+ from typing import Dict, Any, Optional
8
+ from abc import ABC, abstractmethod
9
+ from enum import Enum
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+ # Windows subprocess creation flags
14
+ _IS_WINDOWS = sys.platform == "win32"
15
+ _CREATE_NO_WINDOW = 0x08000000 if _IS_WINDOWS else 0
16
+
17
+
18
+ class TransportType(Enum):
19
+ """MCP transport types."""
20
+ STDIO = "stdio"
21
+ SSE = "sse"
22
+ STREAMABLE_HTTP = "streamable_http"
23
+
24
+
25
+ class BaseMCPTransport(ABC):
26
+ """Base class for MCP transport implementations."""
27
+
28
+ @abstractmethod
29
+ async def connect(self):
30
+ """Establish connection to MCP server."""
31
+ pass
32
+
33
+ @abstractmethod
34
+ async def send(self, method: str, params: Dict[str, Any]) -> Dict[str, Any]:
35
+ """Send a JSON-RPC request and wait for response."""
36
+ pass
37
+
38
+ @abstractmethod
39
+ async def notify(self, method: str, params: Dict[str, Any]):
40
+ """Send a JSON-RPC notification (no response expected)."""
41
+ pass
42
+
43
+ @abstractmethod
44
+ async def close(self):
45
+ """Close the connection."""
46
+ pass
47
+
48
+
49
+ class StdioTransport(BaseMCPTransport):
50
+ """
51
+ STDIO transport for local MCP servers.
52
+
53
+ Communicates with MCP server via stdin/stdout using JSON-RPC.
54
+ """
55
+
56
+ def __init__(self, command: str, args: Optional[list] = None, env: Optional[dict] = None):
57
+ """
58
+ Initialize STDIO transport.
59
+
60
+ Args:
61
+ command: Command to execute (e.g., "python", "node")
62
+ args: Command arguments (e.g., ["server.py"])
63
+ env: Environment variables
64
+ """
65
+ self.command = command
66
+ self.args = args or []
67
+ self.env = env
68
+ self.process: Optional[asyncio.subprocess.Process] = None
69
+ self._request_id = 0
70
+ self._pending_requests: Dict[int, asyncio.Future] = {}
71
+ self._reader_task: Optional[asyncio.Task] = None
72
+
73
+ async def connect(self):
74
+ """Start the MCP server process."""
75
+ import os
76
+
77
+ # Prepare environment
78
+ process_env = os.environ.copy()
79
+ if self.env:
80
+ process_env.update(self.env)
81
+
82
+ # Build kwargs for subprocess creation
83
+ kwargs: Dict[str, Any] = {
84
+ "stdin": asyncio.subprocess.PIPE,
85
+ "stdout": asyncio.subprocess.PIPE,
86
+ "stderr": asyncio.subprocess.PIPE,
87
+ "env": process_env,
88
+ }
89
+
90
+ # On Windows, prevent console window from appearing
91
+ if _IS_WINDOWS:
92
+ kwargs["creationflags"] = _CREATE_NO_WINDOW
93
+
94
+ self.process = await asyncio.create_subprocess_exec(
95
+ self.command, *self.args,
96
+ **kwargs
97
+ )
98
+
99
+ # Start background reader
100
+ self._reader_task = asyncio.create_task(self._read_responses())
101
+
102
+ async def _read_responses(self):
103
+ """Background task to read responses from server."""
104
+ try:
105
+ while self.process and self.process.stdout:
106
+ line = await self.process.stdout.readline()
107
+ if not line:
108
+ break
109
+
110
+ try:
111
+ response = json.loads(line.decode())
112
+ request_id = response.get('id')
113
+
114
+ if request_id is not None and request_id in self._pending_requests:
115
+ future = self._pending_requests.pop(request_id)
116
+ if not future.done():
117
+ future.set_result(response)
118
+
119
+ except json.JSONDecodeError:
120
+ logger.warning(f"Invalid JSON from server: {line}")
121
+
122
+ except asyncio.CancelledError:
123
+ pass
124
+ except Exception as e:
125
+ logger.error(f"Error reading from server: {e}")
126
+
127
+ async def send(self, method: str, params: Dict[str, Any]) -> Dict[str, Any]:
128
+ """Send a JSON-RPC request and wait for response."""
129
+ if not self.process or not self.process.stdin:
130
+ raise RuntimeError("Not connected")
131
+
132
+ self._request_id += 1
133
+ request_id = self._request_id
134
+
135
+ request = {
136
+ "jsonrpc": "2.0",
137
+ "id": request_id,
138
+ "method": method,
139
+ "params": params
140
+ }
141
+
142
+ # Create future for response
143
+ future: asyncio.Future = asyncio.get_event_loop().create_future()
144
+ self._pending_requests[request_id] = future
145
+
146
+ # Send request
147
+ request_bytes = json.dumps(request).encode() + b"\n"
148
+ self.process.stdin.write(request_bytes)
149
+ await self.process.stdin.drain()
150
+
151
+ # Wait for response with timeout
152
+ try:
153
+ response = await asyncio.wait_for(future, timeout=30)
154
+ except asyncio.TimeoutError:
155
+ self._pending_requests.pop(request_id, None)
156
+ raise TimeoutError(f"Request {method} timed out")
157
+
158
+ if "error" in response:
159
+ error = response["error"]
160
+ raise RuntimeError(f"MCP Error: {error.get('message', error)}")
161
+
162
+ return response.get("result", {})
163
+
164
+ async def notify(self, method: str, params: Dict[str, Any]):
165
+ """Send a JSON-RPC notification."""
166
+ if not self.process or not self.process.stdin:
167
+ raise RuntimeError("Not connected")
168
+
169
+ notification = {
170
+ "jsonrpc": "2.0",
171
+ "method": method,
172
+ "params": params
173
+ }
174
+
175
+ notification_bytes = json.dumps(notification).encode() + b"\n"
176
+ self.process.stdin.write(notification_bytes)
177
+ await self.process.stdin.drain()
178
+
179
+ async def close(self):
180
+ """Terminate the server process."""
181
+ if self._reader_task:
182
+ self._reader_task.cancel()
183
+ try:
184
+ await self._reader_task
185
+ except asyncio.CancelledError:
186
+ pass
187
+
188
+ if self.process:
189
+ self.process.terminate()
190
+ try:
191
+ await asyncio.wait_for(self.process.wait(), timeout=5)
192
+ except asyncio.TimeoutError:
193
+ self.process.kill()
194
+ await self.process.wait()
195
+
196
+
197
+ class SSETransport(BaseMCPTransport):
198
+ """
199
+ SSE (Server-Sent Events) transport for remote MCP servers.
200
+
201
+ Uses HTTP POST for requests and SSE for responses.
202
+ """
203
+
204
+ def __init__(self, url: str):
205
+ """
206
+ Initialize SSE transport.
207
+
208
+ Args:
209
+ url: SSE endpoint URL
210
+ """
211
+ self.url = url
212
+ self.session = None
213
+ self._request_id = 0
214
+ self._endpoint: Optional[str] = None
215
+
216
+ async def connect(self):
217
+ """Connect to the SSE endpoint and get the messages URL."""
218
+ import aiohttp
219
+
220
+ self.session = aiohttp.ClientSession()
221
+
222
+ # Connect to SSE endpoint to get messages URL
223
+ try:
224
+ async with self.session.get(self.url) as response:
225
+ if response.status != 200:
226
+ raise RuntimeError(f"SSE connection failed: {response.status}")
227
+
228
+ # Read SSE events to find endpoint
229
+ async for line in response.content:
230
+ decoded = line.decode().strip()
231
+
232
+ if decoded.startswith("event: endpoint"):
233
+ next_line = await response.content.readline()
234
+ data = next_line.decode().strip()
235
+ if data.startswith("data: "):
236
+ self._endpoint = data[6:]
237
+ break
238
+
239
+ except Exception as e:
240
+ await self.close()
241
+ raise RuntimeError(f"Failed to connect to SSE: {e}")
242
+
243
+ if not self._endpoint:
244
+ raise RuntimeError("Failed to get messages endpoint from SSE")
245
+
246
+ async def send(self, method: str, params: Dict[str, Any]) -> Dict[str, Any]:
247
+ """Send a JSON-RPC request via HTTP POST."""
248
+ if not self.session or not self._endpoint:
249
+ raise RuntimeError("Not connected")
250
+
251
+ self._request_id += 1
252
+ request = {
253
+ "jsonrpc": "2.0",
254
+ "id": self._request_id,
255
+ "method": method,
256
+ "params": params
257
+ }
258
+
259
+ async with self.session.post(self._endpoint, json=request) as response:
260
+ if response.status != 200:
261
+ raise RuntimeError(f"Request failed: {response.status}")
262
+
263
+ result = await response.json()
264
+
265
+ if "error" in result:
266
+ error = result["error"]
267
+ raise RuntimeError(f"MCP Error: {error.get('message', error)}")
268
+
269
+ return result.get("result", {})
270
+
271
+ async def notify(self, method: str, params: Dict[str, Any]):
272
+ """Send a JSON-RPC notification via HTTP POST."""
273
+ if not self.session or not self._endpoint:
274
+ raise RuntimeError("Not connected")
275
+
276
+ notification = {
277
+ "jsonrpc": "2.0",
278
+ "method": method,
279
+ "params": params
280
+ }
281
+
282
+ async with self.session.post(self._endpoint, json=notification):
283
+ pass # Notifications don't expect a response
284
+
285
+ async def close(self):
286
+ """Close the HTTP session."""
287
+ if self.session:
288
+ await self.session.close()
289
+ self.session = None
290
+
291
+
292
+ async def create_client(target: str, transport_type: TransportType) -> BaseMCPTransport:
293
+ """
294
+ Factory function to create an appropriate MCP transport.
295
+
296
+ Args:
297
+ target: Target specification
298
+ - For STDIO: "python server.py" or command with args
299
+ - For SSE: "https://example.com/sse"
300
+ transport_type: Type of transport to use
301
+
302
+ Returns:
303
+ Connected MCP transport instance
304
+ """
305
+ if transport_type == TransportType.STDIO:
306
+ # Parse command and arguments
307
+ parts = target.split()
308
+ if not parts:
309
+ raise ValueError("Empty command for STDIO transport")
310
+
311
+ command = parts[0]
312
+ args = parts[1:]
313
+
314
+ transport = StdioTransport(command, args)
315
+ await transport.connect()
316
+ return transport
317
+
318
+ elif transport_type == TransportType.SSE:
319
+ transport = SSETransport(target)
320
+ await transport.connect()
321
+ return transport
322
+
323
+ else:
324
+ raise ValueError(f"Unsupported transport type: {transport_type}")
325
+
326
+
327
+ def infer_transport_type(target: str) -> TransportType:
328
+ """
329
+ Infer transport type from target string.
330
+
331
+ Args:
332
+ target: Target specification
333
+
334
+ Returns:
335
+ Inferred TransportType
336
+ """
337
+ if target.startswith(("http://", "https://")):
338
+ return TransportType.SSE
339
+ elif target.startswith("stdio"):
340
+ return TransportType.STDIO
341
+ else:
342
+ # Assume it's a command for STDIO
343
+ return TransportType.STDIO
agent_audit/version.py ADDED
@@ -0,0 +1,3 @@
1
+ """Version information for agent-audit."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,219 @@
1
+ Metadata-Version: 2.1
2
+ Name: agent-audit
3
+ Version: 0.1.0
4
+ Summary: Security scanner for AI agents and MCP configurations - Based on OWASP Agentic Top 10
5
+ Home-page: https://github.com/HeadyZhang/agent-audit
6
+ License: MIT
7
+ Keywords: ai,agent,security,mcp,audit,owasp,vulnerability,scanner
8
+ Author: Agent Security Team
9
+ Author-email: security@example.com
10
+ Requires-Python: >=3.9,<4.0
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Information Technology
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Security
24
+ Classifier: Topic :: Software Development :: Quality Assurance
25
+ Classifier: Topic :: Software Development :: Testing
26
+ Requires-Dist: aiofiles (>=23.0,<24.0)
27
+ Requires-Dist: aiohttp (>=3.9,<4.0)
28
+ Requires-Dist: click (>=8.1.0,<9.0.0)
29
+ Requires-Dist: pydantic (>=2.0,<3.0)
30
+ Requires-Dist: pyyaml (>=6.0,<7.0)
31
+ Requires-Dist: rich (>=13.0.0,<14.0.0)
32
+ Project-URL: Bug Tracker, https://github.com/HeadyZhang/agent-audit/issues
33
+ Project-URL: Changelog, https://github.com/HeadyZhang/agent-audit/releases
34
+ Project-URL: Documentation, https://github.com/HeadyZhang/agent-audit#readme
35
+ Project-URL: Repository, https://github.com/HeadyZhang/agent-audit
36
+ Description-Content-Type: text/markdown
37
+
38
+ # Agent Audit
39
+
40
+ [![PyPI version](https://badge.fury.io/py/agent-audit.svg)](https://badge.fury.io/py/agent-audit)
41
+ [![Python](https://img.shields.io/pypi/pyversions/agent-audit.svg)](https://pypi.org/project/agent-audit/)
42
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
43
+ [![CI](https://github.com/HeadyZhang/agent-audit/actions/workflows/ci.yml/badge.svg)](https://github.com/HeadyZhang/agent-audit/actions/workflows/ci.yml)
44
+ [![codecov](https://codecov.io/gh/HeadyZhang/agent-audit/branch/master/graph/badge.svg)](https://codecov.io/gh/HeadyZhang/agent-audit)
45
+
46
+ > 🛡️ Security scanner for AI agents and MCP configurations. Detects vulnerabilities based on the **OWASP Agentic Top 10**.
47
+
48
+ <p align="center">
49
+ <img src="docs/demo.gif" alt="Agent Audit Demo" width="800">
50
+ </p>
51
+
52
+ ## ✨ Features
53
+
54
+ - **🔍 Python AST Scanning** - Detects dangerous patterns like `shell=True`, `eval()`, and tainted input flows
55
+ - **⚙️ MCP Configuration Scanning** - Validates MCP server configurations for security issues
56
+ - **🔐 Secret Detection** - Finds hardcoded credentials (AWS keys, API tokens, private keys)
57
+ - **🌐 Runtime MCP Inspection** - Probes MCP servers without executing tools ("Agent Nmap")
58
+ - **📊 Multiple Output Formats** - Terminal, JSON, SARIF (for GitHub Code Scanning), Markdown
59
+
60
+ ## 🚀 Quick Start
61
+
62
+ ### Installation
63
+
64
+ ```bash
65
+ pip install agent-audit
66
+ ```
67
+
68
+ ### Basic Usage
69
+
70
+ ```bash
71
+ # Scan current directory
72
+ agent-audit scan .
73
+
74
+ # Scan with JSON output
75
+ agent-audit scan ./my-agent --format json
76
+
77
+ # Scan with SARIF output for GitHub Code Scanning
78
+ agent-audit scan . --format sarif --output results.sarif
79
+
80
+ # Fail CI on critical findings only
81
+ agent-audit scan . --fail-on critical
82
+
83
+ # Inspect an MCP server at runtime
84
+ agent-audit inspect stdio -- npx -y @modelcontextprotocol/server-filesystem /tmp
85
+ ```
86
+
87
+ ## 🔗 GitHub Action
88
+
89
+ Add Agent Audit to your CI/CD pipeline with just a few lines:
90
+
91
+ ```yaml
92
+ name: Security Scan
93
+ on: [push, pull_request]
94
+
95
+ jobs:
96
+ agent-audit:
97
+ runs-on: ubuntu-latest
98
+ steps:
99
+ - uses: actions/checkout@v4
100
+
101
+ - name: Run Agent Audit
102
+ uses: HeadyZhang/agent-audit@v1
103
+ with:
104
+ path: '.'
105
+ fail-on: 'high'
106
+ upload-sarif: 'true'
107
+ ```
108
+
109
+ ### Action Inputs
110
+
111
+ | Input | Description | Default |
112
+ |-------|-------------|---------|
113
+ | `path` | Path to scan | `.` |
114
+ | `format` | Output format: `terminal`, `json`, `sarif`, `markdown` | `sarif` |
115
+ | `severity` | Minimum severity to report: `info`, `low`, `medium`, `high`, `critical` | `low` |
116
+ | `fail-on` | Exit with error if findings at this severity | `high` |
117
+ | `baseline` | Path to baseline file for incremental scanning | - |
118
+ | `upload-sarif` | Upload SARIF to GitHub Security tab | `true` |
119
+
120
+ ## 🎯 Detected Issues
121
+
122
+ | Rule ID | Title | Severity |
123
+ |---------|-------|----------|
124
+ | AGENT-001 | Command Injection via Unsanitized Input | 🔴 Critical |
125
+ | AGENT-002 | Excessive Agent Permissions | 🟡 Medium |
126
+ | AGENT-003 | Potential Data Exfiltration Chain | 🟠 High |
127
+ | AGENT-004 | Hardcoded Credentials | 🔴 Critical |
128
+ | AGENT-005 | Unverified MCP Server | 🟠 High |
129
+
130
+ ## ⚙️ Configuration
131
+
132
+ Create a `.agent-audit.yaml` file to customize scanning:
133
+
134
+ ```yaml
135
+ # Allowed network hosts (reduces AGENT-003 confidence)
136
+ allowed_hosts:
137
+ - "*.internal.company.com"
138
+ - "api.openai.com"
139
+
140
+ # Ignore rules
141
+ ignore:
142
+ - rule_id: AGENT-003
143
+ paths:
144
+ - "auth/**"
145
+ reason: "Auth module legitimately communicates externally"
146
+
147
+ # Scan settings
148
+ scan:
149
+ exclude:
150
+ - "tests/**"
151
+ - "venv/**"
152
+ min_severity: low
153
+ fail_on: high
154
+ ```
155
+
156
+ ## 📈 Baseline Scanning
157
+
158
+ Track new findings incrementally:
159
+
160
+ ```bash
161
+ # Save current findings as baseline
162
+ agent-audit scan . --save-baseline baseline.json
163
+
164
+ # Only report new findings
165
+ agent-audit scan . --baseline baseline.json
166
+ ```
167
+
168
+ ## 📖 CLI Reference
169
+
170
+ ```
171
+ Usage: agent-audit [OPTIONS] COMMAND [ARGS]...
172
+
173
+ Commands:
174
+ scan Scan agent code and configurations
175
+ inspect Inspect an MCP server at runtime
176
+ init Initialize configuration file
177
+
178
+ Options:
179
+ --version Show version
180
+ -v Enable verbose output
181
+ -q Only show errors
182
+ --help Show this message
183
+ ```
184
+
185
+ ## 🛠️ Development
186
+
187
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines.
188
+
189
+ ```bash
190
+ # Clone the repository
191
+ git clone https://github.com/HeadyZhang/agent-audit
192
+ cd agent-security-suite
193
+
194
+ # Install dependencies
195
+ cd packages/core && poetry install
196
+ cd ../audit && poetry install
197
+
198
+ # Run tests
199
+ poetry run pytest tests/ -v
200
+
201
+ # Run the scanner
202
+ poetry run agent-audit scan .
203
+ ```
204
+
205
+ ## 📄 License
206
+
207
+ MIT License - see [LICENSE](LICENSE) for details.
208
+
209
+ ## 🙏 Acknowledgments
210
+
211
+ - Based on the [OWASP Agentic Security Top 10](https://owasp.org/www-project-agentic-security/)
212
+ - Inspired by the need for better AI agent security tooling
213
+
214
+ ---
215
+
216
+ <p align="center">
217
+ Made with ❤️ for the AI agent security community
218
+ </p>
219
+
@@ -0,0 +1,37 @@
1
+ agent_audit/__init__.py,sha256=D8k1t9MieJMyq0in1RsJAOgZfGW1F5r-djHTspnXEG0,98
2
+ agent_audit/__main__.py,sha256=juDPvuN3eWRpjRm94fxhPUyM8VBMmg8xOS59iEYdAMM,340
3
+ agent_audit/cli/__init__.py,sha256=rsgbDj0L-wbwEfkY4bWRbr2QPUlDrtMp3z9k7qEtXAo,34
4
+ agent_audit/cli/commands/__init__.py,sha256=YKhyx4t_78Ti9_utLsgSo_iFNqXBCxCPyD0MZtGZwRo,36
5
+ agent_audit/cli/commands/init.py,sha256=agP2lvZoNwcVSrNJGatAb7boQZL5ma3Xcq5K3y0Scsw,1274
6
+ agent_audit/cli/commands/inspect.py,sha256=HFxPrLCGRP1Chtccip_9fr4l49Mvx3rpIbaOHPrwlC8,7697
7
+ agent_audit/cli/commands/scan.py,sha256=5JvH8HsGtDnNsJRwWkR5A1IH10zFg-tuGfbzHAeAd8w,11642
8
+ agent_audit/cli/formatters/__init__.py,sha256=BspmN4xcVYvmSY5fClccAIqwMUqQP7MO9auVwJJbWIM,41
9
+ agent_audit/cli/formatters/json.py,sha256=Wy-cKPmH62oXeHyM4rjQySgB7X4GwJX_7XEcWHK1Pcg,3997
10
+ agent_audit/cli/formatters/sarif.py,sha256=5j4dfuEBIy5HkusWLT0Ha_vW6sJsxcNcTfm4jq-CPH8,5361
11
+ agent_audit/cli/formatters/terminal.py,sha256=naNy-jAqWlrlO_SsL9iSZPsN-4jY1EsHcepVFIE2Fpg,6917
12
+ agent_audit/cli/main.py,sha256=JHKm0VXsNsSWwNLFOurwaUR54PuKVLod1Mat6ypqwss,971
13
+ agent_audit/config/__init__.py,sha256=BHW5R9IU5aMumvd5JLDaeuUu3ZH_kU7qODTKs3tjdak,48
14
+ agent_audit/config/ignore.py,sha256=6tLxp89zR5FOst1Ci6GvVGZhghNm_Q6UyXkFYmAZu1Q,15019
15
+ agent_audit/core_utils/__init__.py,sha256=XtUKNre_-5Ryf9u3brruaWu8kmhWklWYn1brRQg0vJg,49
16
+ agent_audit/models/__init__.py,sha256=0KBDUfUlXOfQPNkx8VDL89DxCjjbQgw2vO-v5xTf2Xs,475
17
+ agent_audit/models/finding.py,sha256=2M8H4gNlZGUMEUTj4svvNGJ3kGu-OagOQS49YH0K5ug,5512
18
+ agent_audit/models/risk.py,sha256=mDpvi5WpvcppTktPgTMw2mSgnfgusn7fU8HXIjMBvN8,2216
19
+ agent_audit/models/tool.py,sha256=hVQW4Q9ZvNDEDNtFMUFvvxwcXTiMw0ZFLb_IQLNSihE,5790
20
+ agent_audit/rules/__init__.py,sha256=L-sssDeN5jVP8_mi6zF4JMGxq4jtvJOQZAt3jKnDnhs,192
21
+ agent_audit/rules/engine.py,sha256=9S6TMfW-0v8XpzGW4vVscTJUo8OUf2K5p7V5qUyoyPE,18179
22
+ agent_audit/rules/loader.py,sha256=Fdwl_0L89s97gP-6TD27S6V-jD_A5TkQMsmr3xtC-is,5157
23
+ agent_audit/scanners/__init__.py,sha256=My758N4VyF-g2ARYPxWLIlyvZBAMm7KFQx3w6FDrZR4,136
24
+ agent_audit/scanners/base.py,sha256=pdSu0lxS5gJtvI7o7c3MFcytzOXezytID0KDUlCyxks,687
25
+ agent_audit/scanners/config_scanner.py,sha256=hkpq-5-Qbm7gCTjdUrcXrQGklK7D89gTmpPaMcMTl-Y,13136
26
+ agent_audit/scanners/mcp_config_scanner.py,sha256=LAtW9F7HFgDIb1W9U4dSFz27YOB3ls_ifF8_XG-lDbU,10666
27
+ agent_audit/scanners/mcp_inspector.py,sha256=8tfeLm_9t5c4KPkaEoRSQwB-94HN3DXbm_86Mbc88Js,15316
28
+ agent_audit/scanners/python_scanner.py,sha256=BO6sfp1lq6WARACqQzueDFbvnSCBHSP0i5SnW7tIhso,20691
29
+ agent_audit/scanners/secret_scanner.py,sha256=moNaesAqc3PFfWEvfu8V8OmO0bhZsGPj8dz_Ha_Cqvc,18686
30
+ agent_audit/utils/__init__.py,sha256=3leLd2NVV013ymtXxJjUg-THvZwUmfYiCBTwJaSsDqg,402
31
+ agent_audit/utils/compat.py,sha256=-TC2CCq1gBislYbVxdqKq7XE7c325GoPbbDF9BovOA8,3040
32
+ agent_audit/utils/mcp_client.py,sha256=TjW-aUcwnOgnSuAvk352HxiHO0sfd8Vb3Y2ySqA3-9M,10631
33
+ agent_audit/version.py,sha256=YeuRVUF33dlS0mzQu2Huk9qG-_by3kSZEAwoBB2VjCA,66
34
+ agent_audit-0.1.0.dist-info/METADATA,sha256=XjaOj5QxB2MeA-zv1DYSagyLliwmsI0dDHAcUM0mkrM,6588
35
+ agent_audit-0.1.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
36
+ agent_audit-0.1.0.dist-info/entry_points.txt,sha256=Fc0jPCn3KKoZttTJATiXY2QljohsIdTv-J29TRNU_Gc,56
37
+ agent_audit-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 1.9.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ agent-audit=agent_audit.cli.main:cli
3
+