agent-security 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agent_security-1.0.0/LICENSE +21 -0
- agent_security-1.0.0/PKG-INFO +150 -0
- agent_security-1.0.0/README.md +116 -0
- agent_security-1.0.0/agent_security/__init__.py +3 -0
- agent_security-1.0.0/agent_security/cli.py +114 -0
- agent_security-1.0.0/agent_security/reporter.py +135 -0
- agent_security-1.0.0/agent_security/scanner.py +109 -0
- agent_security-1.0.0/agent_security.egg-info/PKG-INFO +150 -0
- agent_security-1.0.0/agent_security.egg-info/SOURCES.txt +12 -0
- agent_security-1.0.0/agent_security.egg-info/dependency_links.txt +1 -0
- agent_security-1.0.0/agent_security.egg-info/entry_points.txt +2 -0
- agent_security-1.0.0/agent_security.egg-info/top_level.txt +1 -0
- agent_security-1.0.0/setup.cfg +4 -0
- agent_security-1.0.0/setup.py +34 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nerq
|
|
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,150 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-security
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Security scanner for AI agent dependencies. One command to know if your AI stack is safe.
|
|
5
|
+
Home-page: https://nerq.ai
|
|
6
|
+
Author: Nerq
|
|
7
|
+
Author-email: hello@nerq.ai
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://nerq.ai
|
|
10
|
+
Project-URL: Documentation, https://nerq.ai/start
|
|
11
|
+
Project-URL: Repository, https://github.com/agentic-index/agent-security
|
|
12
|
+
Keywords: ai,agents,security,trust,cve,scanner,mcp
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Topic :: Security
|
|
18
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
19
|
+
Requires-Python: >=3.8
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Dynamic: author
|
|
23
|
+
Dynamic: author-email
|
|
24
|
+
Dynamic: classifier
|
|
25
|
+
Dynamic: description
|
|
26
|
+
Dynamic: description-content-type
|
|
27
|
+
Dynamic: home-page
|
|
28
|
+
Dynamic: keywords
|
|
29
|
+
Dynamic: license
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
Dynamic: project-url
|
|
32
|
+
Dynamic: requires-python
|
|
33
|
+
Dynamic: summary
|
|
34
|
+
|
|
35
|
+
# agent-security
|
|
36
|
+
|
|
37
|
+
**Know if your AI dependencies are safe. One command.**
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install agent-security
|
|
41
|
+
agent-security scan requirements.txt
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Scans all your AI agent dependencies against Nerq's trust database of 204,000+ agents.
|
|
45
|
+
Checks for CVEs, license issues, maintenance status, and overall trust score.
|
|
46
|
+
|
|
47
|
+
## Output
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
agent-security scan: requirements.txt
|
|
51
|
+
Scanned 12 dependencies
|
|
52
|
+
|
|
53
|
+
OK langchain: Trust 88 (A), MIT
|
|
54
|
+
OK openai: Trust 91 (A+), MIT
|
|
55
|
+
!! some-agent: Trust 48 (C), 1 CVE(s), no license
|
|
56
|
+
!! risky-tool: Trust 29 (D), 2 CVE(s), AGPL
|
|
57
|
+
|
|
58
|
+
Summary: 10 trusted, 1 warning(s), 1 critical
|
|
59
|
+
|
|
60
|
+
Run 'agent-security fix requirements.txt' for improvement recommendations.
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Commands
|
|
64
|
+
|
|
65
|
+
### scan
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
agent-security scan requirements.txt
|
|
69
|
+
agent-security scan package.json
|
|
70
|
+
agent-security scan pyproject.toml
|
|
71
|
+
agent-security scan requirements.txt --ci # exits 1 if critical issues
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### fix
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
agent-security fix requirements.txt
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Shows specific recommendations for each problematic dependency:
|
|
81
|
+
- Alternative packages with higher trust scores
|
|
82
|
+
- CVE details and update suggestions
|
|
83
|
+
|
|
84
|
+
### check
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
agent-security check langchain
|
|
88
|
+
agent-security check auto-gpt
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Check trust for a single package.
|
|
92
|
+
|
|
93
|
+
### badge
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
agent-security badge my-project
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Generates markdown for a Nerq trust badge to add to your README.
|
|
100
|
+
|
|
101
|
+
### ci
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
agent-security ci
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Outputs a ready-to-use GitHub Action YAML for automated trust checking on every PR.
|
|
108
|
+
|
|
109
|
+
## Supported files
|
|
110
|
+
|
|
111
|
+
- `requirements.txt` — Python dependencies
|
|
112
|
+
- `package.json` — Node.js dependencies
|
|
113
|
+
- `pyproject.toml` — Python project dependencies
|
|
114
|
+
|
|
115
|
+
## How it works
|
|
116
|
+
|
|
117
|
+
agent-security calls the [Nerq API](https://nerq.ai/v1/preflight) for each dependency.
|
|
118
|
+
Every package is scored on:
|
|
119
|
+
|
|
120
|
+
- **Security** — Known CVEs and vulnerability history
|
|
121
|
+
- **Maintenance** — Update frequency, issue response time
|
|
122
|
+
- **Popularity** — Stars, downloads, community size
|
|
123
|
+
- **License** — SPDX compliance, commercial friendliness
|
|
124
|
+
- **Ecosystem** — Framework compatibility, integration quality
|
|
125
|
+
|
|
126
|
+
No API key required. Free to use.
|
|
127
|
+
|
|
128
|
+
## CI Integration
|
|
129
|
+
|
|
130
|
+
Add to `.github/workflows/trust-check.yml`:
|
|
131
|
+
|
|
132
|
+
```yaml
|
|
133
|
+
name: Agent Security Check
|
|
134
|
+
on: [push, pull_request]
|
|
135
|
+
|
|
136
|
+
jobs:
|
|
137
|
+
trust-check:
|
|
138
|
+
runs-on: ubuntu-latest
|
|
139
|
+
steps:
|
|
140
|
+
- uses: actions/checkout@v4
|
|
141
|
+
- uses: actions/setup-python@v5
|
|
142
|
+
with:
|
|
143
|
+
python-version: '3.11'
|
|
144
|
+
- run: pip install agent-security
|
|
145
|
+
- run: agent-security scan requirements.txt --ci
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## License
|
|
149
|
+
|
|
150
|
+
MIT
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# agent-security
|
|
2
|
+
|
|
3
|
+
**Know if your AI dependencies are safe. One command.**
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pip install agent-security
|
|
7
|
+
agent-security scan requirements.txt
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Scans all your AI agent dependencies against Nerq's trust database of 204,000+ agents.
|
|
11
|
+
Checks for CVEs, license issues, maintenance status, and overall trust score.
|
|
12
|
+
|
|
13
|
+
## Output
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
agent-security scan: requirements.txt
|
|
17
|
+
Scanned 12 dependencies
|
|
18
|
+
|
|
19
|
+
OK langchain: Trust 88 (A), MIT
|
|
20
|
+
OK openai: Trust 91 (A+), MIT
|
|
21
|
+
!! some-agent: Trust 48 (C), 1 CVE(s), no license
|
|
22
|
+
!! risky-tool: Trust 29 (D), 2 CVE(s), AGPL
|
|
23
|
+
|
|
24
|
+
Summary: 10 trusted, 1 warning(s), 1 critical
|
|
25
|
+
|
|
26
|
+
Run 'agent-security fix requirements.txt' for improvement recommendations.
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Commands
|
|
30
|
+
|
|
31
|
+
### scan
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
agent-security scan requirements.txt
|
|
35
|
+
agent-security scan package.json
|
|
36
|
+
agent-security scan pyproject.toml
|
|
37
|
+
agent-security scan requirements.txt --ci # exits 1 if critical issues
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### fix
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
agent-security fix requirements.txt
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Shows specific recommendations for each problematic dependency:
|
|
47
|
+
- Alternative packages with higher trust scores
|
|
48
|
+
- CVE details and update suggestions
|
|
49
|
+
|
|
50
|
+
### check
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
agent-security check langchain
|
|
54
|
+
agent-security check auto-gpt
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Check trust for a single package.
|
|
58
|
+
|
|
59
|
+
### badge
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
agent-security badge my-project
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Generates markdown for a Nerq trust badge to add to your README.
|
|
66
|
+
|
|
67
|
+
### ci
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
agent-security ci
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Outputs a ready-to-use GitHub Action YAML for automated trust checking on every PR.
|
|
74
|
+
|
|
75
|
+
## Supported files
|
|
76
|
+
|
|
77
|
+
- `requirements.txt` — Python dependencies
|
|
78
|
+
- `package.json` — Node.js dependencies
|
|
79
|
+
- `pyproject.toml` — Python project dependencies
|
|
80
|
+
|
|
81
|
+
## How it works
|
|
82
|
+
|
|
83
|
+
agent-security calls the [Nerq API](https://nerq.ai/v1/preflight) for each dependency.
|
|
84
|
+
Every package is scored on:
|
|
85
|
+
|
|
86
|
+
- **Security** — Known CVEs and vulnerability history
|
|
87
|
+
- **Maintenance** — Update frequency, issue response time
|
|
88
|
+
- **Popularity** — Stars, downloads, community size
|
|
89
|
+
- **License** — SPDX compliance, commercial friendliness
|
|
90
|
+
- **Ecosystem** — Framework compatibility, integration quality
|
|
91
|
+
|
|
92
|
+
No API key required. Free to use.
|
|
93
|
+
|
|
94
|
+
## CI Integration
|
|
95
|
+
|
|
96
|
+
Add to `.github/workflows/trust-check.yml`:
|
|
97
|
+
|
|
98
|
+
```yaml
|
|
99
|
+
name: Agent Security Check
|
|
100
|
+
on: [push, pull_request]
|
|
101
|
+
|
|
102
|
+
jobs:
|
|
103
|
+
trust-check:
|
|
104
|
+
runs-on: ubuntu-latest
|
|
105
|
+
steps:
|
|
106
|
+
- uses: actions/checkout@v4
|
|
107
|
+
- uses: actions/setup-python@v5
|
|
108
|
+
with:
|
|
109
|
+
python-version: '3.11'
|
|
110
|
+
- run: pip install agent-security
|
|
111
|
+
- run: agent-security scan requirements.txt --ci
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
MIT
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""CLI entry point for agent-security."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from agent_security.scanner import scan_file, detect_and_parse, check_trust
|
|
5
|
+
from agent_security.reporter import (
|
|
6
|
+
format_scan_report, format_fix_report, generate_badge_markdown,
|
|
7
|
+
generate_github_action, bold
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def main():
|
|
12
|
+
args = sys.argv[1:]
|
|
13
|
+
|
|
14
|
+
if not args or args[0] in ("--help", "-h", "help"):
|
|
15
|
+
print_help()
|
|
16
|
+
return
|
|
17
|
+
|
|
18
|
+
command = args[0]
|
|
19
|
+
api_url = None
|
|
20
|
+
|
|
21
|
+
# Extract --api-url flag if present
|
|
22
|
+
for i, arg in enumerate(args):
|
|
23
|
+
if arg == "--api-url" and i + 1 < len(args):
|
|
24
|
+
api_url = args[i + 1]
|
|
25
|
+
args = args[:i] + args[i + 2:]
|
|
26
|
+
break
|
|
27
|
+
|
|
28
|
+
if command == "scan":
|
|
29
|
+
if len(args) < 2:
|
|
30
|
+
print("Usage: agent-security scan <requirements.txt|package.json|pyproject.toml>")
|
|
31
|
+
sys.exit(1)
|
|
32
|
+
filepath = args[1]
|
|
33
|
+
ci_mode = "--ci" in args
|
|
34
|
+
|
|
35
|
+
print(f"Scanning {filepath}...")
|
|
36
|
+
results = scan_file(filepath, api_url)
|
|
37
|
+
print(format_scan_report(results, filepath))
|
|
38
|
+
|
|
39
|
+
if ci_mode:
|
|
40
|
+
critical = sum(1 for r in results if r["trust_score"] is not None and r["trust_score"] < 40)
|
|
41
|
+
if critical > 0:
|
|
42
|
+
sys.exit(1)
|
|
43
|
+
|
|
44
|
+
elif command == "fix":
|
|
45
|
+
if len(args) < 2:
|
|
46
|
+
print("Usage: agent-security fix <requirements.txt|package.json|pyproject.toml>")
|
|
47
|
+
sys.exit(1)
|
|
48
|
+
filepath = args[1]
|
|
49
|
+
results = scan_file(filepath, api_url)
|
|
50
|
+
print(format_fix_report(results))
|
|
51
|
+
|
|
52
|
+
elif command == "badge":
|
|
53
|
+
name = args[1] if len(args) > 1 else "my-project"
|
|
54
|
+
print(f"\nAdd this to your README:\n")
|
|
55
|
+
print(f" {generate_badge_markdown(name)}\n")
|
|
56
|
+
|
|
57
|
+
elif command == "ci":
|
|
58
|
+
print(f"\nAdd this to .github/workflows/trust-check.yml:\n")
|
|
59
|
+
print(generate_github_action())
|
|
60
|
+
|
|
61
|
+
elif command == "check":
|
|
62
|
+
if len(args) < 2:
|
|
63
|
+
print("Usage: agent-security check <package-name>")
|
|
64
|
+
sys.exit(1)
|
|
65
|
+
name = args[1]
|
|
66
|
+
result = check_trust(name, api_url)
|
|
67
|
+
if result["error"]:
|
|
68
|
+
print(f" {name}: not found ({result['error']})")
|
|
69
|
+
else:
|
|
70
|
+
trust = int(result["trust_score"]) if result["trust_score"] else "?"
|
|
71
|
+
grade = result["grade"] or "?"
|
|
72
|
+
print(f" {name}: Trust {trust} ({grade}) — {result['recommendation']}")
|
|
73
|
+
if result["cve_count"]:
|
|
74
|
+
print(f" CVEs: {result['cve_count']}")
|
|
75
|
+
if result["license"]:
|
|
76
|
+
print(f" License: {result['license']}")
|
|
77
|
+
|
|
78
|
+
else:
|
|
79
|
+
print(f"Unknown command: {command}")
|
|
80
|
+
print_help()
|
|
81
|
+
sys.exit(1)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def print_help():
|
|
85
|
+
print("""
|
|
86
|
+
agent-security — Know if your AI dependencies are safe. One command.
|
|
87
|
+
|
|
88
|
+
Commands:
|
|
89
|
+
scan <file> Scan dependencies for trust scores and CVEs
|
|
90
|
+
fix <file> Show fix recommendations for problematic dependencies
|
|
91
|
+
check <name> Check trust for a single package
|
|
92
|
+
badge [name] Generate Nerq trust badge markdown
|
|
93
|
+
ci Generate GitHub Action YAML for CI integration
|
|
94
|
+
|
|
95
|
+
Supported files:
|
|
96
|
+
requirements.txt, package.json, pyproject.toml
|
|
97
|
+
|
|
98
|
+
Options:
|
|
99
|
+
--ci Exit with code 1 if critical issues found (for CI)
|
|
100
|
+
--api-url URL Override Nerq API URL
|
|
101
|
+
|
|
102
|
+
Examples:
|
|
103
|
+
agent-security scan requirements.txt
|
|
104
|
+
agent-security fix package.json
|
|
105
|
+
agent-security check langchain
|
|
106
|
+
agent-security badge my-project
|
|
107
|
+
agent-security ci
|
|
108
|
+
|
|
109
|
+
Powered by nerq.ai — the trust layer for AI agents.
|
|
110
|
+
""")
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
if __name__ == "__main__":
|
|
114
|
+
main()
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""Format scan results for terminal output."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _color(text, code):
|
|
7
|
+
"""Apply ANSI color if stdout is a terminal."""
|
|
8
|
+
if not sys.stdout.isatty():
|
|
9
|
+
return text
|
|
10
|
+
return f"\033[{code}m{text}\033[0m"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def green(text): return _color(text, "32")
|
|
14
|
+
def yellow(text): return _color(text, "33")
|
|
15
|
+
def red(text): return _color(text, "31")
|
|
16
|
+
def bold(text): return _color(text, "1")
|
|
17
|
+
def dim(text): return _color(text, "2")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def format_scan_report(results, filepath):
|
|
21
|
+
"""Format scan results as a terminal report."""
|
|
22
|
+
lines = []
|
|
23
|
+
lines.append(f"\n{bold('agent-security')} scan: {filepath}")
|
|
24
|
+
lines.append(f"Scanned {len(results)} dependencies\n")
|
|
25
|
+
|
|
26
|
+
trusted = 0
|
|
27
|
+
warnings = 0
|
|
28
|
+
critical = 0
|
|
29
|
+
not_found = 0
|
|
30
|
+
|
|
31
|
+
for r in results:
|
|
32
|
+
name = r["name"]
|
|
33
|
+
trust = r["trust_score"]
|
|
34
|
+
grade = r["grade"] or "?"
|
|
35
|
+
rec = r["recommendation"] or "UNKNOWN"
|
|
36
|
+
cves = r["cve_count"]
|
|
37
|
+
lic = r["license"] or "unknown"
|
|
38
|
+
error = r["error"]
|
|
39
|
+
|
|
40
|
+
if error:
|
|
41
|
+
not_found += 1
|
|
42
|
+
lines.append(f" {dim('?')} {name}: {dim('not found in index')}")
|
|
43
|
+
continue
|
|
44
|
+
|
|
45
|
+
trust_str = f"{int(trust)}" if trust is not None else "?"
|
|
46
|
+
cve_str = f", {cves} CVE(s)" if cves else ""
|
|
47
|
+
lic_str = f", {lic}" if lic and lic != "unknown" else ""
|
|
48
|
+
|
|
49
|
+
if rec == "ALLOW" or (trust is not None and trust >= 70):
|
|
50
|
+
trusted += 1
|
|
51
|
+
icon = green("OK")
|
|
52
|
+
detail = f"Trust {trust_str} ({grade}){cve_str}{lic_str}"
|
|
53
|
+
lines.append(f" {icon} {name}: {detail}")
|
|
54
|
+
elif rec == "DENY" or (trust is not None and trust < 40):
|
|
55
|
+
critical += 1
|
|
56
|
+
icon = red("!!")
|
|
57
|
+
detail = f"Trust {trust_str} ({grade}){cve_str}{lic_str}"
|
|
58
|
+
lines.append(f" {icon} {red(name)}: {detail}")
|
|
59
|
+
else:
|
|
60
|
+
warnings += 1
|
|
61
|
+
icon = yellow("!!")
|
|
62
|
+
detail = f"Trust {trust_str} ({grade}){cve_str}{lic_str}"
|
|
63
|
+
lines.append(f" {icon} {yellow(name)}: {detail}")
|
|
64
|
+
|
|
65
|
+
lines.append("")
|
|
66
|
+
summary_parts = []
|
|
67
|
+
if trusted:
|
|
68
|
+
summary_parts.append(green(f"{trusted} trusted"))
|
|
69
|
+
if warnings:
|
|
70
|
+
summary_parts.append(yellow(f"{warnings} warning(s)"))
|
|
71
|
+
if critical:
|
|
72
|
+
summary_parts.append(red(f"{critical} critical"))
|
|
73
|
+
if not_found:
|
|
74
|
+
summary_parts.append(dim(f"{not_found} not found"))
|
|
75
|
+
lines.append(f"Summary: {', '.join(summary_parts)}")
|
|
76
|
+
|
|
77
|
+
if critical > 0:
|
|
78
|
+
lines.append(f"\nRun '{bold('agent-security fix ' + filepath)}' for improvement recommendations.")
|
|
79
|
+
|
|
80
|
+
return "\n".join(lines)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def format_fix_report(results):
|
|
84
|
+
"""Format fix recommendations."""
|
|
85
|
+
lines = []
|
|
86
|
+
lines.append(f"\n{bold('agent-security')} fix recommendations:\n")
|
|
87
|
+
|
|
88
|
+
problematic = [r for r in results if r["trust_score"] is not None and r["trust_score"] < 60]
|
|
89
|
+
|
|
90
|
+
if not problematic:
|
|
91
|
+
lines.append(" All dependencies look good. No fixes needed.")
|
|
92
|
+
return "\n".join(lines)
|
|
93
|
+
|
|
94
|
+
for r in problematic:
|
|
95
|
+
trust = int(r["trust_score"]) if r["trust_score"] else "?"
|
|
96
|
+
lines.append(f" {bold(r['name'])} (Trust: {trust}):")
|
|
97
|
+
|
|
98
|
+
if r["cve_count"]:
|
|
99
|
+
lines.append(f" -> {r['cve_count']} known CVE(s) — check for updates")
|
|
100
|
+
|
|
101
|
+
alts = r.get("alternatives", [])
|
|
102
|
+
if alts:
|
|
103
|
+
alt = alts[0]
|
|
104
|
+
alt_name = alt.get("name", "?")
|
|
105
|
+
alt_trust = int(alt.get("trust_score", 0))
|
|
106
|
+
lines.append(f" -> Alternative: {green(alt_name)} (Trust: {alt_trust})")
|
|
107
|
+
else:
|
|
108
|
+
lines.append(f" -> No direct alternative found. Review manually.")
|
|
109
|
+
|
|
110
|
+
lines.append("")
|
|
111
|
+
|
|
112
|
+
return "\n".join(lines)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def generate_badge_markdown(project_name="my-project"):
|
|
116
|
+
"""Generate Nerq trust badge markdown."""
|
|
117
|
+
return f"[](https://nerq.ai/safe/{project_name})"
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def generate_github_action():
|
|
121
|
+
"""Generate GitHub Action YAML for trust checking."""
|
|
122
|
+
return """name: Agent Security Check
|
|
123
|
+
on: [push, pull_request]
|
|
124
|
+
|
|
125
|
+
jobs:
|
|
126
|
+
trust-check:
|
|
127
|
+
runs-on: ubuntu-latest
|
|
128
|
+
steps:
|
|
129
|
+
- uses: actions/checkout@v4
|
|
130
|
+
- uses: actions/setup-python@v5
|
|
131
|
+
with:
|
|
132
|
+
python-version: '3.11'
|
|
133
|
+
- run: pip install agent-security
|
|
134
|
+
- run: agent-security scan requirements.txt --ci
|
|
135
|
+
"""
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""Scan dependency files for AI agent trust scores."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import re
|
|
5
|
+
import urllib.request
|
|
6
|
+
import urllib.parse
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
API_URL = "https://nerq.ai"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def parse_requirements(filepath):
|
|
13
|
+
"""Parse requirements.txt and return list of package names."""
|
|
14
|
+
packages = []
|
|
15
|
+
with open(filepath) as f:
|
|
16
|
+
for line in f:
|
|
17
|
+
line = line.strip()
|
|
18
|
+
if not line or line.startswith("#") or line.startswith("-"):
|
|
19
|
+
continue
|
|
20
|
+
# Strip version specifiers
|
|
21
|
+
name = re.split(r"[>=<!\[;]", line)[0].strip()
|
|
22
|
+
if name:
|
|
23
|
+
packages.append(name)
|
|
24
|
+
return packages
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def parse_package_json(filepath):
|
|
28
|
+
"""Parse package.json and return list of dependency names."""
|
|
29
|
+
with open(filepath) as f:
|
|
30
|
+
data = json.load(f)
|
|
31
|
+
deps = list(data.get("dependencies", {}).keys())
|
|
32
|
+
deps += list(data.get("devDependencies", {}).keys())
|
|
33
|
+
return deps
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def parse_pyproject(filepath):
|
|
37
|
+
"""Parse pyproject.toml for dependencies (basic parser)."""
|
|
38
|
+
packages = []
|
|
39
|
+
in_deps = False
|
|
40
|
+
with open(filepath) as f:
|
|
41
|
+
for line in f:
|
|
42
|
+
line = line.strip()
|
|
43
|
+
if line.startswith("dependencies") and "=" in line:
|
|
44
|
+
in_deps = True
|
|
45
|
+
continue
|
|
46
|
+
if in_deps:
|
|
47
|
+
if line == "]":
|
|
48
|
+
in_deps = False
|
|
49
|
+
continue
|
|
50
|
+
# Extract package name from "package>=1.0"
|
|
51
|
+
match = re.match(r'"([a-zA-Z0-9_-]+)', line)
|
|
52
|
+
if match:
|
|
53
|
+
packages.append(match.group(1))
|
|
54
|
+
return packages
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def detect_and_parse(filepath):
|
|
58
|
+
"""Auto-detect file type and parse dependencies."""
|
|
59
|
+
p = Path(filepath)
|
|
60
|
+
name = p.name.lower()
|
|
61
|
+
|
|
62
|
+
if name == "requirements.txt" or name.endswith(".txt"):
|
|
63
|
+
return parse_requirements(filepath)
|
|
64
|
+
elif name == "package.json":
|
|
65
|
+
return parse_package_json(filepath)
|
|
66
|
+
elif name == "pyproject.toml":
|
|
67
|
+
return parse_pyproject(filepath)
|
|
68
|
+
else:
|
|
69
|
+
# Try requirements.txt format as fallback
|
|
70
|
+
return parse_requirements(filepath)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def check_trust(package_name, api_url=None):
|
|
74
|
+
"""Check trust score for a single package."""
|
|
75
|
+
base = api_url or API_URL
|
|
76
|
+
url = f"{base}/v1/preflight?target={urllib.parse.quote(package_name)}"
|
|
77
|
+
try:
|
|
78
|
+
data = json.loads(urllib.request.urlopen(url, timeout=15).read())
|
|
79
|
+
return {
|
|
80
|
+
"name": package_name,
|
|
81
|
+
"trust_score": data.get("target_trust"),
|
|
82
|
+
"grade": data.get("target_grade"),
|
|
83
|
+
"recommendation": data.get("recommendation"),
|
|
84
|
+
"cve_count": data.get("security", {}).get("cve_count", 0),
|
|
85
|
+
"license": data.get("security", {}).get("license"),
|
|
86
|
+
"alternatives": data.get("alternatives", []),
|
|
87
|
+
"error": None,
|
|
88
|
+
}
|
|
89
|
+
except Exception as e:
|
|
90
|
+
return {
|
|
91
|
+
"name": package_name,
|
|
92
|
+
"trust_score": None,
|
|
93
|
+
"grade": None,
|
|
94
|
+
"recommendation": None,
|
|
95
|
+
"cve_count": 0,
|
|
96
|
+
"license": None,
|
|
97
|
+
"alternatives": [],
|
|
98
|
+
"error": str(e),
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def scan_file(filepath, api_url=None):
|
|
103
|
+
"""Scan a dependency file and return trust results for all packages."""
|
|
104
|
+
packages = detect_and_parse(filepath)
|
|
105
|
+
results = []
|
|
106
|
+
for pkg in packages:
|
|
107
|
+
result = check_trust(pkg, api_url)
|
|
108
|
+
results.append(result)
|
|
109
|
+
return results
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-security
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Security scanner for AI agent dependencies. One command to know if your AI stack is safe.
|
|
5
|
+
Home-page: https://nerq.ai
|
|
6
|
+
Author: Nerq
|
|
7
|
+
Author-email: hello@nerq.ai
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://nerq.ai
|
|
10
|
+
Project-URL: Documentation, https://nerq.ai/start
|
|
11
|
+
Project-URL: Repository, https://github.com/agentic-index/agent-security
|
|
12
|
+
Keywords: ai,agents,security,trust,cve,scanner,mcp
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Topic :: Security
|
|
18
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
19
|
+
Requires-Python: >=3.8
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Dynamic: author
|
|
23
|
+
Dynamic: author-email
|
|
24
|
+
Dynamic: classifier
|
|
25
|
+
Dynamic: description
|
|
26
|
+
Dynamic: description-content-type
|
|
27
|
+
Dynamic: home-page
|
|
28
|
+
Dynamic: keywords
|
|
29
|
+
Dynamic: license
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
Dynamic: project-url
|
|
32
|
+
Dynamic: requires-python
|
|
33
|
+
Dynamic: summary
|
|
34
|
+
|
|
35
|
+
# agent-security
|
|
36
|
+
|
|
37
|
+
**Know if your AI dependencies are safe. One command.**
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install agent-security
|
|
41
|
+
agent-security scan requirements.txt
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Scans all your AI agent dependencies against Nerq's trust database of 204,000+ agents.
|
|
45
|
+
Checks for CVEs, license issues, maintenance status, and overall trust score.
|
|
46
|
+
|
|
47
|
+
## Output
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
agent-security scan: requirements.txt
|
|
51
|
+
Scanned 12 dependencies
|
|
52
|
+
|
|
53
|
+
OK langchain: Trust 88 (A), MIT
|
|
54
|
+
OK openai: Trust 91 (A+), MIT
|
|
55
|
+
!! some-agent: Trust 48 (C), 1 CVE(s), no license
|
|
56
|
+
!! risky-tool: Trust 29 (D), 2 CVE(s), AGPL
|
|
57
|
+
|
|
58
|
+
Summary: 10 trusted, 1 warning(s), 1 critical
|
|
59
|
+
|
|
60
|
+
Run 'agent-security fix requirements.txt' for improvement recommendations.
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Commands
|
|
64
|
+
|
|
65
|
+
### scan
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
agent-security scan requirements.txt
|
|
69
|
+
agent-security scan package.json
|
|
70
|
+
agent-security scan pyproject.toml
|
|
71
|
+
agent-security scan requirements.txt --ci # exits 1 if critical issues
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### fix
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
agent-security fix requirements.txt
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Shows specific recommendations for each problematic dependency:
|
|
81
|
+
- Alternative packages with higher trust scores
|
|
82
|
+
- CVE details and update suggestions
|
|
83
|
+
|
|
84
|
+
### check
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
agent-security check langchain
|
|
88
|
+
agent-security check auto-gpt
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Check trust for a single package.
|
|
92
|
+
|
|
93
|
+
### badge
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
agent-security badge my-project
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Generates markdown for a Nerq trust badge to add to your README.
|
|
100
|
+
|
|
101
|
+
### ci
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
agent-security ci
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Outputs a ready-to-use GitHub Action YAML for automated trust checking on every PR.
|
|
108
|
+
|
|
109
|
+
## Supported files
|
|
110
|
+
|
|
111
|
+
- `requirements.txt` — Python dependencies
|
|
112
|
+
- `package.json` — Node.js dependencies
|
|
113
|
+
- `pyproject.toml` — Python project dependencies
|
|
114
|
+
|
|
115
|
+
## How it works
|
|
116
|
+
|
|
117
|
+
agent-security calls the [Nerq API](https://nerq.ai/v1/preflight) for each dependency.
|
|
118
|
+
Every package is scored on:
|
|
119
|
+
|
|
120
|
+
- **Security** — Known CVEs and vulnerability history
|
|
121
|
+
- **Maintenance** — Update frequency, issue response time
|
|
122
|
+
- **Popularity** — Stars, downloads, community size
|
|
123
|
+
- **License** — SPDX compliance, commercial friendliness
|
|
124
|
+
- **Ecosystem** — Framework compatibility, integration quality
|
|
125
|
+
|
|
126
|
+
No API key required. Free to use.
|
|
127
|
+
|
|
128
|
+
## CI Integration
|
|
129
|
+
|
|
130
|
+
Add to `.github/workflows/trust-check.yml`:
|
|
131
|
+
|
|
132
|
+
```yaml
|
|
133
|
+
name: Agent Security Check
|
|
134
|
+
on: [push, pull_request]
|
|
135
|
+
|
|
136
|
+
jobs:
|
|
137
|
+
trust-check:
|
|
138
|
+
runs-on: ubuntu-latest
|
|
139
|
+
steps:
|
|
140
|
+
- uses: actions/checkout@v4
|
|
141
|
+
- uses: actions/setup-python@v5
|
|
142
|
+
with:
|
|
143
|
+
python-version: '3.11'
|
|
144
|
+
- run: pip install agent-security
|
|
145
|
+
- run: agent-security scan requirements.txt --ci
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## License
|
|
149
|
+
|
|
150
|
+
MIT
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
setup.py
|
|
4
|
+
agent_security/__init__.py
|
|
5
|
+
agent_security/cli.py
|
|
6
|
+
agent_security/reporter.py
|
|
7
|
+
agent_security/scanner.py
|
|
8
|
+
agent_security.egg-info/PKG-INFO
|
|
9
|
+
agent_security.egg-info/SOURCES.txt
|
|
10
|
+
agent_security.egg-info/dependency_links.txt
|
|
11
|
+
agent_security.egg-info/entry_points.txt
|
|
12
|
+
agent_security.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
agent_security
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name="agent-security",
|
|
5
|
+
version="1.0.0",
|
|
6
|
+
description="Security scanner for AI agent dependencies. One command to know if your AI stack is safe.",
|
|
7
|
+
long_description=open("README.md").read(),
|
|
8
|
+
long_description_content_type="text/markdown",
|
|
9
|
+
author="Nerq",
|
|
10
|
+
author_email="hello@nerq.ai",
|
|
11
|
+
url="https://nerq.ai",
|
|
12
|
+
project_urls={
|
|
13
|
+
"Homepage": "https://nerq.ai",
|
|
14
|
+
"Documentation": "https://nerq.ai/start",
|
|
15
|
+
"Repository": "https://github.com/agentic-index/agent-security",
|
|
16
|
+
},
|
|
17
|
+
packages=find_packages(),
|
|
18
|
+
python_requires=">=3.8",
|
|
19
|
+
entry_points={
|
|
20
|
+
"console_scripts": [
|
|
21
|
+
"agent-security=agent_security.cli:main",
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
classifiers=[
|
|
25
|
+
"Development Status :: 4 - Beta",
|
|
26
|
+
"Intended Audience :: Developers",
|
|
27
|
+
"License :: OSI Approved :: MIT License",
|
|
28
|
+
"Programming Language :: Python :: 3",
|
|
29
|
+
"Topic :: Security",
|
|
30
|
+
"Topic :: Software Development :: Quality Assurance",
|
|
31
|
+
],
|
|
32
|
+
keywords=["ai", "agents", "security", "trust", "cve", "scanner", "mcp"],
|
|
33
|
+
license="MIT",
|
|
34
|
+
)
|