security-advisor 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.
- pkg/__init__.py +0 -0
- pkg/sarif_report.py +180 -0
- security_advisor-0.1.0.dist-info/METADATA +279 -0
- security_advisor-0.1.0.dist-info/RECORD +7 -0
- security_advisor-0.1.0.dist-info/WHEEL +5 -0
- security_advisor-0.1.0.dist-info/licenses/LICENSE +21 -0
- security_advisor-0.1.0.dist-info/top_level.txt +1 -0
pkg/__init__.py
ADDED
|
File without changes
|
pkg/sarif_report.py
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
from datetime import datetime, timezone
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
# ---------------------------------------------------------------------------
|
|
5
|
+
# SARIF 2.1.0 builder
|
|
6
|
+
# ---------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
def _severity_to_sarif_level(severity: str) -> str:
|
|
9
|
+
"""Map a tool-specific severity string to a SARIF notification level."""
|
|
10
|
+
mapping = {
|
|
11
|
+
"critical": "error",
|
|
12
|
+
"high": "error",
|
|
13
|
+
"medium": "warning",
|
|
14
|
+
"low": "note",
|
|
15
|
+
"info": "note",
|
|
16
|
+
}
|
|
17
|
+
return mapping.get(severity.lower(), "warning")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _parse_sast_results(sast_json: dict) -> tuple[list, list]:
|
|
21
|
+
"""Convert Semgrep JSON output to SARIF rules + results."""
|
|
22
|
+
rules, results = [], []
|
|
23
|
+
seen_rule_ids: set[str] = set()
|
|
24
|
+
|
|
25
|
+
for finding in sast_json.get("results", []):
|
|
26
|
+
rule_id = finding.get("check_id", "unknown-rule")
|
|
27
|
+
message = finding.get("extra", {}).get("message", "No message.")
|
|
28
|
+
severity = finding.get("extra", {}).get("severity", "warning")
|
|
29
|
+
file_path = finding.get("path", "")
|
|
30
|
+
start = finding.get("start", {})
|
|
31
|
+
end = finding.get("end", {})
|
|
32
|
+
|
|
33
|
+
if rule_id not in seen_rule_ids:
|
|
34
|
+
seen_rule_ids.add(rule_id)
|
|
35
|
+
rules.append({
|
|
36
|
+
"id": rule_id,
|
|
37
|
+
"name": rule_id,
|
|
38
|
+
"shortDescription": {"text": message[:200]},
|
|
39
|
+
"helpUri": finding.get("extra", {}).get("metadata", {}).get("references", [None])[0],
|
|
40
|
+
"properties": {"tags": ["SAST", "semgrep"]},
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
results.append({
|
|
44
|
+
"ruleId": rule_id,
|
|
45
|
+
"level": _severity_to_sarif_level(severity),
|
|
46
|
+
"message": {"text": message},
|
|
47
|
+
"locations": [{
|
|
48
|
+
"physicalLocation": {
|
|
49
|
+
"artifactLocation": {"uri": file_path, "uriBaseId": "%SRCROOT%"},
|
|
50
|
+
"region": {
|
|
51
|
+
"startLine": start.get("line", 1),
|
|
52
|
+
"startColumn": start.get("col", 1),
|
|
53
|
+
"endLine": end.get("line", start.get("line", 1)),
|
|
54
|
+
"endColumn": end.get("col", 1),
|
|
55
|
+
},
|
|
56
|
+
}
|
|
57
|
+
}],
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
return rules, results
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _parse_trivy_results(trivy_json: dict, scan_type: str) -> tuple[list, list]:
|
|
64
|
+
"""Convert Trivy JSON output (vuln or config) to SARIF rules + results."""
|
|
65
|
+
rules, results = [], []
|
|
66
|
+
seen_rule_ids: set[str] = set()
|
|
67
|
+
tags = ["SCA", "trivy"] if scan_type == "sca" else ["IaC", "trivy"]
|
|
68
|
+
|
|
69
|
+
for target_block in trivy_json.get("Results", []):
|
|
70
|
+
target = target_block.get("Target", "")
|
|
71
|
+
findings = target_block.get("Vulnerabilities") or target_block.get("Misconfigurations") or []
|
|
72
|
+
|
|
73
|
+
for finding in findings:
|
|
74
|
+
# Vulnerabilities use VulnerabilityID; Misconfigurations use ID
|
|
75
|
+
rule_id = finding.get("VulnerabilityID") or finding.get("ID", "unknown")
|
|
76
|
+
title = finding.get("Title") or finding.get("Description", rule_id)
|
|
77
|
+
desc = finding.get("Description", title)
|
|
78
|
+
severity = finding.get("Severity", "UNKNOWN")
|
|
79
|
+
pkg_name = finding.get("PkgName", "")
|
|
80
|
+
fixed_ver = finding.get("FixedVersion", "")
|
|
81
|
+
refs = finding.get("References") or finding.get("References", [])
|
|
82
|
+
|
|
83
|
+
if rule_id not in seen_rule_ids:
|
|
84
|
+
seen_rule_ids.add(rule_id)
|
|
85
|
+
help_uri = refs[0] if refs else None
|
|
86
|
+
rules.append({
|
|
87
|
+
"id": rule_id,
|
|
88
|
+
"name": rule_id,
|
|
89
|
+
"shortDescription": {"text": title[:200]},
|
|
90
|
+
"fullDescription": {"text": desc[:1000]},
|
|
91
|
+
**({"helpUri": help_uri} if help_uri else {}),
|
|
92
|
+
"properties": {"tags": tags},
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
message_parts = [f"{title} in `{pkg_name or target}`."]
|
|
96
|
+
if fixed_ver:
|
|
97
|
+
message_parts.append(f"Fixed in version: {fixed_ver}.")
|
|
98
|
+
|
|
99
|
+
results.append({
|
|
100
|
+
"ruleId": rule_id,
|
|
101
|
+
"level": _severity_to_sarif_level(severity),
|
|
102
|
+
"message": {"text": " ".join(message_parts)},
|
|
103
|
+
"locations": [{
|
|
104
|
+
"physicalLocation": {
|
|
105
|
+
"artifactLocation": {"uri": target, "uriBaseId": "%SRCROOT%"},
|
|
106
|
+
}
|
|
107
|
+
}],
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
return rules, results
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def build_sarif_report(sast_raw: str, sca_raw: str, iac_raw: str) -> dict:
|
|
114
|
+
"""
|
|
115
|
+
Aggregate SAST, SCA, and IaC scan outputs into a single SARIF 2.1.0 document.
|
|
116
|
+
Returns the SARIF document as a Python dict.
|
|
117
|
+
"""
|
|
118
|
+
sast_json = json.loads(sast_raw) if sast_raw.strip() else {}
|
|
119
|
+
sca_json = json.loads(sca_raw) if sca_raw.strip() else {}
|
|
120
|
+
iac_json = json.loads(iac_raw) if iac_raw.strip() else {}
|
|
121
|
+
|
|
122
|
+
sast_rules, sast_results = _parse_sast_results(sast_json)
|
|
123
|
+
sca_rules, sca_results = _parse_trivy_results(sca_json, "sca")
|
|
124
|
+
iac_rules, iac_results = _parse_trivy_results(iac_json, "iac")
|
|
125
|
+
|
|
126
|
+
sarif: dict = {
|
|
127
|
+
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
|
|
128
|
+
"version": "2.1.0",
|
|
129
|
+
"runs": [
|
|
130
|
+
# ── SAST run (Semgrep) ──────────────────────────────────────────
|
|
131
|
+
{
|
|
132
|
+
"tool": {
|
|
133
|
+
"driver": {
|
|
134
|
+
"name": "Semgrep",
|
|
135
|
+
"informationUri": "https://semgrep.dev",
|
|
136
|
+
"version": "latest",
|
|
137
|
+
"rules": sast_rules,
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
"results": sast_results,
|
|
141
|
+
"invocations": [{
|
|
142
|
+
"executionSuccessful": True,
|
|
143
|
+
"endTimeUtc": datetime.now(timezone.utc).isoformat(),
|
|
144
|
+
}],
|
|
145
|
+
},
|
|
146
|
+
# ── SCA run (Trivy – vulnerabilities) ──────────────────────────
|
|
147
|
+
{
|
|
148
|
+
"tool": {
|
|
149
|
+
"driver": {
|
|
150
|
+
"name": "Trivy",
|
|
151
|
+
"informationUri": "https://trivy.dev",
|
|
152
|
+
"version": "latest",
|
|
153
|
+
"rules": sca_rules,
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
"results": sca_results,
|
|
157
|
+
"invocations": [{
|
|
158
|
+
"executionSuccessful": True,
|
|
159
|
+
"endTimeUtc": datetime.now(timezone.utc).isoformat(),
|
|
160
|
+
}],
|
|
161
|
+
},
|
|
162
|
+
# ── IaC run (Trivy – misconfigurations) ────────────────────────
|
|
163
|
+
{
|
|
164
|
+
"tool": {
|
|
165
|
+
"driver": {
|
|
166
|
+
"name": "Trivy",
|
|
167
|
+
"informationUri": "https://trivy.dev",
|
|
168
|
+
"version": "latest",
|
|
169
|
+
"rules": iac_rules,
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
"results": iac_results,
|
|
173
|
+
"invocations": [{
|
|
174
|
+
"executionSuccessful": True,
|
|
175
|
+
"endTimeUtc": datetime.now(timezone.utc).isoformat(),
|
|
176
|
+
}],
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
}
|
|
180
|
+
return sarif
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: security-advisor
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Add your description here
|
|
5
|
+
Requires-Python: >=3.14
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Dist: fastmcp>=3.2.4
|
|
9
|
+
Requires-Dist: mcp>=1.27.1
|
|
10
|
+
Dynamic: license-file
|
|
11
|
+
|
|
12
|
+
# 🛡️ Security Advisor
|
|
13
|
+
|
|
14
|
+
An **MCP (Model Context Protocol) server** that orchestrates comprehensive security scans — SAST, SCA, and IaC — across any project and produces a unified **SARIF 2.1.0** report consumable by GitHub Advanced Security, VS Code, and other industry-standard tooling.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Overview
|
|
19
|
+
|
|
20
|
+
Security Advisor exposes four MCP tools that an AI assistant (e.g., Claude, Gemini) can invoke to analyse a codebase:
|
|
21
|
+
|
|
22
|
+
| Tool | Description |
|
|
23
|
+
|---|---|
|
|
24
|
+
| `security_sast_skill` | Static Application Security Testing via **Semgrep** |
|
|
25
|
+
| `security_sca_skill` | Software Composition Analysis via **Trivy** (dependency vulnerabilities) |
|
|
26
|
+
| `security_iac_scan_skill` | Infrastructure-as-Code misconfiguration scan via **Trivy** (Terraform, K8s, Docker) |
|
|
27
|
+
| `security_advisor_skill` | **Master skill** — runs all three scans in parallel and exports a unified SARIF report |
|
|
28
|
+
|
|
29
|
+
### How It Works
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
AI Assistant
|
|
33
|
+
│
|
|
34
|
+
└─► security_advisor_skill(project_path)
|
|
35
|
+
│
|
|
36
|
+
├─► security_sast_skill → Semgrep JSON
|
|
37
|
+
├─► security_sca_skill → Trivy vuln JSON
|
|
38
|
+
└─► security_iac_scan_skill → Trivy config JSON
|
|
39
|
+
│
|
|
40
|
+
▼
|
|
41
|
+
build_sarif_report() ← pkg/sarif_report.py
|
|
42
|
+
│
|
|
43
|
+
▼
|
|
44
|
+
<project_path>/Security-Advisor-Report.sarif
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Prerequisites
|
|
50
|
+
|
|
51
|
+
Ensure the following are installed and available on your `PATH` before running Security Advisor.
|
|
52
|
+
|
|
53
|
+
### System Tools
|
|
54
|
+
|
|
55
|
+
| Tool | Version | Install |
|
|
56
|
+
|---|---|---|
|
|
57
|
+
| **Python** | ≥ 3.14 | [python.org](https://www.python.org/downloads/) |
|
|
58
|
+
| **uv** | latest | `curl -LsSf https://astral.sh/uv/install.sh \| sh` |
|
|
59
|
+
| **Semgrep** | latest | `pip install semgrep` or `brew install semgrep` |
|
|
60
|
+
| **Trivy** | latest | `brew install trivy` or see [trivy.dev](https://trivy.dev/latest/getting-started/installation/) |
|
|
61
|
+
|
|
62
|
+
### Verify Prerequisites
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
python3 --version # Should be 3.14+
|
|
66
|
+
uv --version
|
|
67
|
+
semgrep --version
|
|
68
|
+
trivy --version
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Project Structure
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
security-advisor/
|
|
77
|
+
├── main.py # MCP server entry point — exposes all scan tools
|
|
78
|
+
├── pkg/
|
|
79
|
+
│ ├── __init__.py
|
|
80
|
+
│ └── sarif_report.py # SARIF 2.1.0 builder (parses Semgrep + Trivy JSON)
|
|
81
|
+
├── pyproject.toml # Project metadata and dependencies
|
|
82
|
+
├── uv.lock # Locked dependency manifest
|
|
83
|
+
├── .python-version # Pinned Python version (3.14)
|
|
84
|
+
└── README.md
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Installation
|
|
90
|
+
|
|
91
|
+
### 1. Clone the repository
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
git clone <repository-url>
|
|
95
|
+
cd security-advisor
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 2. Create and activate a virtual environment with `uv`
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
uv venv
|
|
102
|
+
source .venv/bin/activate # macOS / Linux
|
|
103
|
+
# .venv\Scripts\activate # Windows
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 3. Install dependencies
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
uv pip install -e .
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
This installs:
|
|
113
|
+
- [`fastmcp`](https://github.com/jlowin/fastmcp) ≥ 3.2.4 — high-level MCP server framework
|
|
114
|
+
- [`mcp`](https://github.com/modelcontextprotocol/python-sdk) ≥ 1.27.1 — Model Context Protocol Python SDK
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Development
|
|
119
|
+
|
|
120
|
+
### Running the MCP Server Locally
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
uv run main.py
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Or via the standard Python entrypoint:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
python main.py
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The server starts and listens for MCP tool calls over **stdio** (default FastMCP transport).
|
|
133
|
+
|
|
134
|
+
### Running with `fastmcp` dev mode
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
fastmcp dev main.py
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
This launches an interactive MCP inspector at `http://localhost:6274` so you can test tools manually.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## MCP Client Configuration
|
|
145
|
+
|
|
146
|
+
To connect Security Advisor to an AI assistant, add it to your MCP client config.
|
|
147
|
+
|
|
148
|
+
### Claude Desktop (`claude_desktop_config.json`)
|
|
149
|
+
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"mcpServers": {
|
|
153
|
+
"security-advisor": {
|
|
154
|
+
"command": "uv",
|
|
155
|
+
"args": [
|
|
156
|
+
"--directory",
|
|
157
|
+
"/absolute/path/to/security-advisor",
|
|
158
|
+
"run",
|
|
159
|
+
"main.py"
|
|
160
|
+
]
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Gemini / Antigravity (`.gemini/settings.json`)
|
|
167
|
+
|
|
168
|
+
```json
|
|
169
|
+
{
|
|
170
|
+
"mcpServers": {
|
|
171
|
+
"security-advisor": {
|
|
172
|
+
"command": "uv",
|
|
173
|
+
"args": [
|
|
174
|
+
"--directory",
|
|
175
|
+
"/absolute/path/to/security-advisor",
|
|
176
|
+
"run",
|
|
177
|
+
"main.py"
|
|
178
|
+
]
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
> **Tip:** Replace `/absolute/path/to/security-advisor` with the actual path on your machine.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Usage
|
|
189
|
+
|
|
190
|
+
### Via an AI Assistant
|
|
191
|
+
|
|
192
|
+
Once the MCP server is connected, instruct your assistant:
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
Run a full security analysis on /path/to/my-project
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
The assistant will invoke `security_advisor_skill`, which:
|
|
199
|
+
1. Runs Semgrep SAST, Trivy SCA, and Trivy IaC scans **in parallel**
|
|
200
|
+
2. Aggregates all findings into a SARIF 2.1.0 document
|
|
201
|
+
3. Writes the report to `<project_path>/Security-Advisor-Report.sarif`
|
|
202
|
+
4. Returns a human-readable summary
|
|
203
|
+
|
|
204
|
+
### Individual Tools
|
|
205
|
+
|
|
206
|
+
You can also invoke individual scan tools:
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
Run a SAST scan on /path/to/my-project
|
|
210
|
+
Run an SCA scan on /path/to/my-project
|
|
211
|
+
Run an IaC scan on /path/to/my-project
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## SARIF Report
|
|
217
|
+
|
|
218
|
+
The exported **`Security-Advisor-Report.sarif`** is a valid [SARIF 2.1.0](https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html) document containing three `runs`:
|
|
219
|
+
|
|
220
|
+
| Run | Tool | Findings |
|
|
221
|
+
|---|---|---|
|
|
222
|
+
| `runs[0]` | Semgrep | SAST code-level issues |
|
|
223
|
+
| `runs[1]` | Trivy | SCA dependency vulnerabilities |
|
|
224
|
+
| `runs[2]` | Trivy | IaC misconfigurations |
|
|
225
|
+
|
|
226
|
+
### Severity Mapping
|
|
227
|
+
|
|
228
|
+
| Tool Severity | SARIF Level |
|
|
229
|
+
|---|---|
|
|
230
|
+
| `CRITICAL`, `HIGH` | `error` |
|
|
231
|
+
| `MEDIUM` | `warning` |
|
|
232
|
+
| `LOW`, `INFO` | `note` |
|
|
233
|
+
|
|
234
|
+
### Viewing the Report
|
|
235
|
+
|
|
236
|
+
- **GitHub**: Upload to [Code Scanning](https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/uploading-a-sarif-file-to-github) via `gh` CLI or Actions
|
|
237
|
+
- **VS Code**: Install the [SARIF Viewer extension](https://marketplace.visualstudio.com/items?itemName=MS-SarifVSCode.sarif-viewer)
|
|
238
|
+
- **Any SARIF-compatible tool**: The file adheres to the official OASIS schema
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
# Upload to GitHub Code Scanning
|
|
242
|
+
gh api \
|
|
243
|
+
--method POST \
|
|
244
|
+
/repos/{owner}/{repo}/code-scanning/sarifs \
|
|
245
|
+
--field commit_sha=$(git rev-parse HEAD) \
|
|
246
|
+
--field ref=$(git symbolic-ref HEAD) \
|
|
247
|
+
--field sarif=@Security-Advisor-Report.sarif
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Dependencies
|
|
253
|
+
|
|
254
|
+
| Package | Version | Purpose |
|
|
255
|
+
|---|---|---|
|
|
256
|
+
| `fastmcp` | ≥ 3.2.4 | MCP server framework |
|
|
257
|
+
| `mcp` | ≥ 1.27.1 | Model Context Protocol Python SDK |
|
|
258
|
+
|
|
259
|
+
External CLI tools (not Python packages):
|
|
260
|
+
|
|
261
|
+
| Tool | Purpose |
|
|
262
|
+
|---|---|
|
|
263
|
+
| `semgrep` | SAST scanning |
|
|
264
|
+
| `trivy` | SCA + IaC scanning |
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Contributing
|
|
269
|
+
|
|
270
|
+
1. Fork the repository and create a feature branch
|
|
271
|
+
2. Make your changes and ensure the server starts cleanly (`uv run main.py`)
|
|
272
|
+
3. Test manually using `fastmcp dev main.py`
|
|
273
|
+
4. Open a pull request with a clear description of the changes
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## License
|
|
278
|
+
|
|
279
|
+
This project is licensed under the **MIT License**.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
pkg/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
pkg/sarif_report.py,sha256=jeg4aonATV_alU4ACvi4QWBdmlrYsWv_2h2Q41nXHtI,7444
|
|
3
|
+
security_advisor-0.1.0.dist-info/licenses/LICENSE,sha256=BqSdBAFLSGpS17yvP58nw1oG--7fKcwjPWxy-gyPl-4,1071
|
|
4
|
+
security_advisor-0.1.0.dist-info/METADATA,sha256=XZ-H3kLAnpZP9u4to-aEIYQqODlErihm3F0ndafk9xE,7071
|
|
5
|
+
security_advisor-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
6
|
+
security_advisor-0.1.0.dist-info/top_level.txt,sha256=8jjfKuFvlaNGG7JiuNtS31gIuwOm8thUcUQoNbsxxls,4
|
|
7
|
+
security_advisor-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Aditya Byreddy
|
|
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 @@
|
|
|
1
|
+
pkg
|