agentscan-py 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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AgentScan contributors
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,6 @@
1
+ include README.md
2
+ include LICENSE
3
+ include requirements.txt
4
+ include targets.example.txt
5
+ recursive-include src/agentscan *.py
6
+ global-exclude __pycache__ *.py[cod] *.egg-info
@@ -0,0 +1,160 @@
1
+ Metadata-Version: 2.4
2
+ Name: agentscan-py
3
+ Version: 1.0.0
4
+ Summary: Read-only scanner for exposed AI/agent services: detects unauthenticated endpoints on standard ports and enumerates their API surface.
5
+ Author: JohnDoeAnon
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/JohnDoeAnonITA/agentscan-py
8
+ Project-URL: Repository, https://github.com/JohnDoeAnonITA/agentscan-py
9
+ Project-URL: Issues, https://github.com/JohnDoeAnonITA/agentscan-py/issues
10
+ Keywords: security,pentest,reconnaissance,scanner,ai,llm,agent,ollama,vllm,mcp,langserve
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Information Technology
13
+ Classifier: Topic :: Security
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: License :: OSI Approved :: MIT License
18
+ Requires-Python: >=3.8
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Provides-Extra: dev
22
+ Requires-Dist: build>=1.0; extra == "dev"
23
+ Requires-Dist: twine>=4.0; extra == "dev"
24
+ Dynamic: license-file
25
+
26
+ ```
27
+ █████╗ ██████╗ ███████╗███╗ ██╗████████╗███████╗ ██████╗ █████╗ ███╗ ██╗
28
+ ██╔══██╗██╔════╝██╔════╝████╗ ██║╚══██╔══╝██╔════╝██╔════╝██╔══██╗████╗ ██║
29
+ ███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ ███████╗██║ ███████║██╔██╗ ██║
30
+ ██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ╚════██║██║ ██╔══██║██║╚██╗██║
31
+ ██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ███████║╚██████╗██║ ██║██║ ╚████║
32
+ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝
33
+ made by JohnDoeAnon in collaboration with AnonymousITALIA
34
+ ```
35
+
36
+ # AgentScan
37
+
38
+ **Read-only scanner for exposed AI / LLM / agent services.**
39
+
40
+ AgentScan finds AI services listening on standard ports that answer **without
41
+ authentication**, identifies what they are, and enumerates their **API
42
+ endpoints** — so you can see exactly what is exposed. It never writes, never
43
+ sends prompts, and never executes anything on the target: **only HTTP GET**
44
+ requests are issued.
45
+
46
+ Use it **only against assets you own or are explicitly authorised to test.**
47
+
48
+ ## Features
49
+
50
+ - **31 service signatures** — Ollama, vLLM, LocalAI, LiteLLM, llama.cpp, TGI,
51
+ KoboldCpp, LM Studio, TabbyAPI, Aphrodite, Xinference, Text-Generation-WebUI,
52
+ Flowise, Langflow, n8n, Dify, AnythingLLM, Open WebUI, Gradio, Streamlit,
53
+ ComfyUI, MCP servers, Jupyter, LangServe, Haystack/hayhooks, OpenLLM,
54
+ SuperAGI, Chainlit, Letta/MemGPT, AutoGen Studio.
55
+ - **Endpoint enumeration** from five sources: OpenAPI (`/openapi.json`),
56
+ per-service catalog, the shared OpenAI-compatible surface, an aggressive
57
+ path sweep, and fingerprinting evidence.
58
+ - **Aggressive path sweep** — 68 API prefixes × 152 segments (+ 27 well-known
59
+ paths) to discover endpoints that are not in any catalog.
60
+ - **Catch-all / SPA guard** — detects servers that answer 200 to any path, so
61
+ endpoint lists are never inflated and services are not misidentified.
62
+ - **Response snippets** — each live endpoint shows a one-line body preview.
63
+ - **Reports** — console, Markdown, JSON, and a CyberStrike-ready payload.
64
+ - **Optional response dump** — save the body of every 2xx response for manual
65
+ inspection.
66
+ - **Zero dependencies** — standard library only, Python 3.8+.
67
+
68
+ ## Install
69
+
70
+ ```bash
71
+ pip install agentscan-py
72
+ ```
73
+ (run with the `agentscan` command)
74
+
75
+ > Note: the distribution name is `agentscan-py` because `agentscan` is already
76
+ > taken on PyPI by an unrelated project.
77
+
78
+ Or from source:
79
+
80
+ ```bash
81
+ git clone https://github.com/JohnDoeAnonITA/agentscan-py.git
82
+ cd agentscan-py
83
+ pip install .
84
+ ```
85
+
86
+ ## Usage
87
+
88
+ ```bash
89
+ # scan a single host on the built-in AI/agent ports
90
+ agentscan -t 10.0.0.5 --authorized
91
+
92
+ # a subnet
93
+ agentscan -t 10.0.0.0/24 --authorized --rate 100 --out-dir ./reports
94
+
95
+ # specific ports
96
+ agentscan -t 10.0.0.5 --authorized --ports 11434,3000,5678,8000
97
+
98
+ # targets from a file
99
+ agentscan --targets hosts.txt --authorized
100
+ ```
101
+
102
+ `--authorized` is **mandatory** — it is your confirmation that you are allowed
103
+ to test the supplied targets.
104
+
105
+ ### Output
106
+
107
+ `--out-dir DIR` writes `agentscan-<timestamp>.json`, `.md`, and
108
+ `.cyberstrike.json`. You can also write a single format with `--json`,
109
+ `--md`, or `--cyberstrike`.
110
+
111
+ By default only endpoints returning **2xx** are displayed; pass
112
+ `--all-status` to also show 401/403/405 (auth / method-not-allowed).
113
+
114
+ ### Key options
115
+
116
+ | Option | Description |
117
+ |---|---|
118
+ | `-t, --target` | host / IP / CIDR / range (repeatable, comma-separated) |
119
+ | `--targets FILE` | one target per line (`#` comments allowed) |
120
+ | `--ports` | `auto`, a list (`11434,3000`), or a range (`8000-8100`) |
121
+ | `--sweep {off,normal,aggressive}` | path-sweep depth (default `aggressive`) |
122
+ | `--sweep-budget N` | max sweep requests per service |
123
+ | `--all-status` | show non-2xx endpoints too |
124
+ | `--dump-response --dump-dir DIR` | save body of every 2xx response |
125
+ | `--rate N` | global requests/second (default 50) |
126
+ | `--cyberstrike FILE` | write CyberStrike ingestion payload |
127
+ | `--authorized` | **required** scope confirmation |
128
+
129
+ Run `agentscan --help` for the full list.
130
+
131
+ ## Target formats
132
+
133
+ ```
134
+ 10.0.0.5 single IP (IPv4/IPv6)
135
+ box.lab.internal hostname (DNS)
136
+ 10.0.0.0/24 CIDR subnet (capped by --max-hosts)
137
+ 10.0.0.1-10.0.0.50 IP range (explicit end)
138
+ 10.0.0.1-50 IP range (last-octet shorthand)
139
+ ```
140
+
141
+ ## Safety
142
+
143
+ - **Read-only**: only GET requests. POST-only routes are reported as HTTP 405
144
+ (proof the function exists) but never called.
145
+ - **Rate-limited** globally (`--rate`).
146
+ - **Host cap** on CIDR expansion (`--max-hosts`).
147
+ - **Authorization gate** (`--authorized`).
148
+
149
+ ## Output example
150
+
151
+ ```
152
+ NO-AUTH! 127.0.0.1:11434 Ollama [high] 6/23 endpoints (2xx)
153
+ GET /api/tags 200 [{"name":"llama3:latest", ...}]
154
+ GET /api/version 200 "0.32.5"
155
+ GET /v1/models 200 {"object":"list","data":[ ... ]}
156
+ ```
157
+
158
+ ## License
159
+
160
+ MIT
@@ -0,0 +1,135 @@
1
+ ```
2
+ █████╗ ██████╗ ███████╗███╗ ██╗████████╗███████╗ ██████╗ █████╗ ███╗ ██╗
3
+ ██╔══██╗██╔════╝██╔════╝████╗ ██║╚══██╔══╝██╔════╝██╔════╝██╔══██╗████╗ ██║
4
+ ███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ ███████╗██║ ███████║██╔██╗ ██║
5
+ ██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ╚════██║██║ ██╔══██║██║╚██╗██║
6
+ ██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ███████║╚██████╗██║ ██║██║ ╚████║
7
+ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝
8
+ made by JohnDoeAnon in collaboration with AnonymousITALIA
9
+ ```
10
+
11
+ # AgentScan
12
+
13
+ **Read-only scanner for exposed AI / LLM / agent services.**
14
+
15
+ AgentScan finds AI services listening on standard ports that answer **without
16
+ authentication**, identifies what they are, and enumerates their **API
17
+ endpoints** — so you can see exactly what is exposed. It never writes, never
18
+ sends prompts, and never executes anything on the target: **only HTTP GET**
19
+ requests are issued.
20
+
21
+ Use it **only against assets you own or are explicitly authorised to test.**
22
+
23
+ ## Features
24
+
25
+ - **31 service signatures** — Ollama, vLLM, LocalAI, LiteLLM, llama.cpp, TGI,
26
+ KoboldCpp, LM Studio, TabbyAPI, Aphrodite, Xinference, Text-Generation-WebUI,
27
+ Flowise, Langflow, n8n, Dify, AnythingLLM, Open WebUI, Gradio, Streamlit,
28
+ ComfyUI, MCP servers, Jupyter, LangServe, Haystack/hayhooks, OpenLLM,
29
+ SuperAGI, Chainlit, Letta/MemGPT, AutoGen Studio.
30
+ - **Endpoint enumeration** from five sources: OpenAPI (`/openapi.json`),
31
+ per-service catalog, the shared OpenAI-compatible surface, an aggressive
32
+ path sweep, and fingerprinting evidence.
33
+ - **Aggressive path sweep** — 68 API prefixes × 152 segments (+ 27 well-known
34
+ paths) to discover endpoints that are not in any catalog.
35
+ - **Catch-all / SPA guard** — detects servers that answer 200 to any path, so
36
+ endpoint lists are never inflated and services are not misidentified.
37
+ - **Response snippets** — each live endpoint shows a one-line body preview.
38
+ - **Reports** — console, Markdown, JSON, and a CyberStrike-ready payload.
39
+ - **Optional response dump** — save the body of every 2xx response for manual
40
+ inspection.
41
+ - **Zero dependencies** — standard library only, Python 3.8+.
42
+
43
+ ## Install
44
+
45
+ ```bash
46
+ pip install agentscan-py
47
+ ```
48
+ (run with the `agentscan` command)
49
+
50
+ > Note: the distribution name is `agentscan-py` because `agentscan` is already
51
+ > taken on PyPI by an unrelated project.
52
+
53
+ Or from source:
54
+
55
+ ```bash
56
+ git clone https://github.com/JohnDoeAnonITA/agentscan-py.git
57
+ cd agentscan-py
58
+ pip install .
59
+ ```
60
+
61
+ ## Usage
62
+
63
+ ```bash
64
+ # scan a single host on the built-in AI/agent ports
65
+ agentscan -t 10.0.0.5 --authorized
66
+
67
+ # a subnet
68
+ agentscan -t 10.0.0.0/24 --authorized --rate 100 --out-dir ./reports
69
+
70
+ # specific ports
71
+ agentscan -t 10.0.0.5 --authorized --ports 11434,3000,5678,8000
72
+
73
+ # targets from a file
74
+ agentscan --targets hosts.txt --authorized
75
+ ```
76
+
77
+ `--authorized` is **mandatory** — it is your confirmation that you are allowed
78
+ to test the supplied targets.
79
+
80
+ ### Output
81
+
82
+ `--out-dir DIR` writes `agentscan-<timestamp>.json`, `.md`, and
83
+ `.cyberstrike.json`. You can also write a single format with `--json`,
84
+ `--md`, or `--cyberstrike`.
85
+
86
+ By default only endpoints returning **2xx** are displayed; pass
87
+ `--all-status` to also show 401/403/405 (auth / method-not-allowed).
88
+
89
+ ### Key options
90
+
91
+ | Option | Description |
92
+ |---|---|
93
+ | `-t, --target` | host / IP / CIDR / range (repeatable, comma-separated) |
94
+ | `--targets FILE` | one target per line (`#` comments allowed) |
95
+ | `--ports` | `auto`, a list (`11434,3000`), or a range (`8000-8100`) |
96
+ | `--sweep {off,normal,aggressive}` | path-sweep depth (default `aggressive`) |
97
+ | `--sweep-budget N` | max sweep requests per service |
98
+ | `--all-status` | show non-2xx endpoints too |
99
+ | `--dump-response --dump-dir DIR` | save body of every 2xx response |
100
+ | `--rate N` | global requests/second (default 50) |
101
+ | `--cyberstrike FILE` | write CyberStrike ingestion payload |
102
+ | `--authorized` | **required** scope confirmation |
103
+
104
+ Run `agentscan --help` for the full list.
105
+
106
+ ## Target formats
107
+
108
+ ```
109
+ 10.0.0.5 single IP (IPv4/IPv6)
110
+ box.lab.internal hostname (DNS)
111
+ 10.0.0.0/24 CIDR subnet (capped by --max-hosts)
112
+ 10.0.0.1-10.0.0.50 IP range (explicit end)
113
+ 10.0.0.1-50 IP range (last-octet shorthand)
114
+ ```
115
+
116
+ ## Safety
117
+
118
+ - **Read-only**: only GET requests. POST-only routes are reported as HTTP 405
119
+ (proof the function exists) but never called.
120
+ - **Rate-limited** globally (`--rate`).
121
+ - **Host cap** on CIDR expansion (`--max-hosts`).
122
+ - **Authorization gate** (`--authorized`).
123
+
124
+ ## Output example
125
+
126
+ ```
127
+ NO-AUTH! 127.0.0.1:11434 Ollama [high] 6/23 endpoints (2xx)
128
+ GET /api/tags 200 [{"name":"llama3:latest", ...}]
129
+ GET /api/version 200 "0.32.5"
130
+ GET /v1/models 200 {"object":"list","data":[ ... ]}
131
+ ```
132
+
133
+ ## License
134
+
135
+ MIT
@@ -0,0 +1,45 @@
1
+ [build-system]
2
+ requires = ["setuptools>=64", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "agentscan-py"
7
+ version = "1.0.0"
8
+ description = "Read-only scanner for exposed AI/agent services: detects unauthenticated endpoints on standard ports and enumerates their API surface."
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = { text = "MIT" }
12
+ keywords = [
13
+ "security", "pentest", "reconnaissance", "scanner",
14
+ "ai", "llm", "agent", "ollama", "vllm", "mcp", "langserve",
15
+ ]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Information Technology",
19
+ "Topic :: Security",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3 :: Only",
22
+ "Operating System :: OS Independent",
23
+ "License :: OSI Approved :: MIT License",
24
+ ]
25
+ # No runtime dependencies — standard library only.
26
+ dependencies = []
27
+
28
+ authors = [{ name = "JohnDoeAnon" }]
29
+
30
+ [project.urls]
31
+ Homepage = "https://github.com/JohnDoeAnonITA/agentscan-py"
32
+ Repository = "https://github.com/JohnDoeAnonITA/agentscan-py"
33
+ Issues = "https://github.com/JohnDoeAnonITA/agentscan-py/issues"
34
+
35
+ [project.scripts]
36
+ agentscan = "agentscan.cli:main"
37
+
38
+ [project.optional-dependencies]
39
+ dev = ["build>=1.0", "twine>=4.0"]
40
+
41
+ [tool.setuptools]
42
+ package-dir = { "" = "src" }
43
+
44
+ [tool.setuptools.packages.find]
45
+ where = ["src"]
@@ -0,0 +1,18 @@
1
+ # AgentScan — requirements
2
+ #
3
+ # Runtime: NONE. AgentScan is pure standard library (Python >= 3.8).
4
+ # `pip install -r requirements.txt` is safe and installs nothing required.
5
+ #
6
+ # Standard-library modules used:
7
+ # argparse, concurrent.futures, http.client, ipaddress, json, os, socket,
8
+ # ssl, sys, threading, time, datetime
9
+ #
10
+ # To install the package itself:
11
+ # pip install .
12
+ #
13
+ # To build distributable artifacts:
14
+ # pip install -r requirements-dev.txt # then: python -m build
15
+
16
+ # --- optional build tooling (not needed to run) ---
17
+ # build>=1.0
18
+ # twine>=4.0
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,8 @@
1
+ """AgentScan — find exposed AI/agent services and enumerate their API surface.
2
+
3
+ A read-only reconnaissance scanner for AI/LLM/agent services that answer on
4
+ standard ports without authentication. Standard library only.
5
+ """
6
+
7
+ __version__ = "1.0.0"
8
+ __all__ = ["__version__"]
@@ -0,0 +1,7 @@
1
+ """Enable `python -m agentscan`."""
2
+ import sys
3
+
4
+ from .cli import main
5
+
6
+ if __name__ == "__main__":
7
+ sys.exit(main())