stoa-agent-risk 0.1.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.
- stoa_agent_risk-0.1.0/LICENSE +21 -0
- stoa_agent_risk-0.1.0/PKG-INFO +253 -0
- stoa_agent_risk-0.1.0/README.md +202 -0
- stoa_agent_risk-0.1.0/pyproject.toml +50 -0
- stoa_agent_risk-0.1.0/setup.cfg +4 -0
- stoa_agent_risk-0.1.0/src/stoa/__init__.py +5 -0
- stoa_agent_risk-0.1.0/src/stoa/agent_detection.py +248 -0
- stoa_agent_risk-0.1.0/src/stoa/cli.py +246 -0
- stoa_agent_risk-0.1.0/src/stoa/config.py +145 -0
- stoa_agent_risk-0.1.0/src/stoa/diff.py +84 -0
- stoa_agent_risk-0.1.0/src/stoa/git_metadata.py +145 -0
- stoa_agent_risk-0.1.0/src/stoa/github.py +89 -0
- stoa_agent_risk-0.1.0/src/stoa/integration_detection.py +61 -0
- stoa_agent_risk-0.1.0/src/stoa/models.py +153 -0
- stoa_agent_risk-0.1.0/src/stoa/redaction.py +35 -0
- stoa_agent_risk-0.1.0/src/stoa/report_html.py +403 -0
- stoa_agent_risk-0.1.0/src/stoa/report_json.py +156 -0
- stoa_agent_risk-0.1.0/src/stoa/risk_detection.py +260 -0
- stoa_agent_risk-0.1.0/src/stoa/rules.py +580 -0
- stoa_agent_risk-0.1.0/src/stoa/scanner.py +208 -0
- stoa_agent_risk-0.1.0/src/stoa/suppressions.py +83 -0
- stoa_agent_risk-0.1.0/src/stoa/templates/stoa.toml +41 -0
- stoa_agent_risk-0.1.0/src/stoa/templates/stoa.yml +78 -0
- stoa_agent_risk-0.1.0/src/stoa/templates/stoaignore +8 -0
- stoa_agent_risk-0.1.0/src/stoa/traversal.py +148 -0
- stoa_agent_risk-0.1.0/src/stoa_agent_risk.egg-info/PKG-INFO +253 -0
- stoa_agent_risk-0.1.0/src/stoa_agent_risk.egg-info/SOURCES.txt +36 -0
- stoa_agent_risk-0.1.0/src/stoa_agent_risk.egg-info/dependency_links.txt +1 -0
- stoa_agent_risk-0.1.0/src/stoa_agent_risk.egg-info/entry_points.txt +2 -0
- stoa_agent_risk-0.1.0/src/stoa_agent_risk.egg-info/requires.txt +7 -0
- stoa_agent_risk-0.1.0/src/stoa_agent_risk.egg-info/top_level.txt +1 -0
- stoa_agent_risk-0.1.0/tests/test_agent_detection.py +230 -0
- stoa_agent_risk-0.1.0/tests/test_cli.py +143 -0
- stoa_agent_risk-0.1.0/tests/test_diff.py +139 -0
- stoa_agent_risk-0.1.0/tests/test_html_escape.py +100 -0
- stoa_agent_risk-0.1.0/tests/test_redaction.py +71 -0
- stoa_agent_risk-0.1.0/tests/test_risk_detection.py +239 -0
- stoa_agent_risk-0.1.0/tests/test_suppressions.py +121 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Stoa 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,253 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: stoa-agent-risk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Local-first AI agent inventory and risk scanner: finds agent candidates with evidence, maps capabilities and integrations, and gates newly introduced high-confidence critical risks.
|
|
5
|
+
Author-email: Ved Upadhyay <iamved05@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Stoa contributors
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://stoa-features.vercel.app
|
|
29
|
+
Project-URL: Repository, https://github.com/iamved/stoa-agent-risk
|
|
30
|
+
Project-URL: Issues, https://github.com/iamved/stoa-agent-risk/issues
|
|
31
|
+
Project-URL: Documentation, https://github.com/iamved/stoa-agent-risk#readme
|
|
32
|
+
Keywords: ai-agents,security,static-analysis,llm,sast
|
|
33
|
+
Classifier: Development Status :: 4 - Beta
|
|
34
|
+
Classifier: Environment :: Console
|
|
35
|
+
Classifier: Intended Audience :: Developers
|
|
36
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
37
|
+
Classifier: Programming Language :: Python :: 3
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
41
|
+
Classifier: Topic :: Security
|
|
42
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
43
|
+
Requires-Python: >=3.10
|
|
44
|
+
Description-Content-Type: text/markdown
|
|
45
|
+
License-File: LICENSE
|
|
46
|
+
Requires-Dist: pathspec>=0.11
|
|
47
|
+
Requires-Dist: tomli>=2.0; python_version < "3.11"
|
|
48
|
+
Provides-Extra: dev
|
|
49
|
+
Requires-Dist: pytest>=7.4; extra == "dev"
|
|
50
|
+
Dynamic: license-file
|
|
51
|
+
|
|
52
|
+
# Stoa
|
|
53
|
+
|
|
54
|
+
**A local-first AI agent inventory and risk scanner** that identifies agent
|
|
55
|
+
candidates with supporting evidence, maps their capabilities and integrations,
|
|
56
|
+
and prevents newly introduced high-confidence critical risks from entering
|
|
57
|
+
the codebase.
|
|
58
|
+
|
|
59
|
+
Stoa scans Python, JavaScript, and TypeScript repositories statically — no
|
|
60
|
+
runtime hooks, no uploads, no accounts.
|
|
61
|
+
|
|
62
|
+
## What Stoa does
|
|
63
|
+
|
|
64
|
+
- **Discovers likely AI agents** (LangChain, LangGraph, CrewAI, AutoGen,
|
|
65
|
+
LlamaIndex, OpenAI Agents SDK, PydanticAI, Bedrock Agents, Semantic Kernel,
|
|
66
|
+
LiteLLM, and raw provider calls) using weighted evidence, and shows exactly
|
|
67
|
+
*why* each candidate was detected.
|
|
68
|
+
- **Maps providers, frameworks, integrations, and capabilities** — e.g. an
|
|
69
|
+
agent candidate with payment access, database reads, and Slack messaging.
|
|
70
|
+
- **Detects high-confidence risks**: hardcoded credentials, hardcoded
|
|
71
|
+
passwords, interpolated SQL, swallowed exceptions, insecure HTTP, missing
|
|
72
|
+
request timeouts, and control-review prompts.
|
|
73
|
+
- **Produces local reports**: a manager-friendly self-contained HTML report
|
|
74
|
+
and a deterministic, versioned JSON registry.
|
|
75
|
+
- **Gates only newly introduced critical findings by default** — existing
|
|
76
|
+
debt never blocks an unrelated pull request.
|
|
77
|
+
|
|
78
|
+
Stoa reports *candidates* and *evidence*, not certainties. A "control not
|
|
79
|
+
observed" prompt is a review nudge, not a proven vulnerability.
|
|
80
|
+
|
|
81
|
+
## Quick start
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pipx install stoa-agent-risk
|
|
85
|
+
cd my-repository
|
|
86
|
+
stoa scan .
|
|
87
|
+
open stoa-report.html
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`stoa scan .` writes `stoa-report.html` and `stoa-registry.json` and exits 0
|
|
91
|
+
(report-only) unless a gate is configured. The JSON is designed to be read by
|
|
92
|
+
coding assistants too:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
stoa scan . --json stoa-registry.json
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## GitHub Actions
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
stoa init github
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
This creates (without overwriting existing files — use `--force` to
|
|
105
|
+
overwrite):
|
|
106
|
+
|
|
107
|
+
- `.github/workflows/stoa.yml` — full-history checkout, pinned Stoa install,
|
|
108
|
+
full-repository scan, diff against the PR base branch, GitHub annotations,
|
|
109
|
+
a job summary, uploaded HTML/JSON artifacts, and a gate that fails **only**
|
|
110
|
+
when the PR introduces a new high-confidence critical finding.
|
|
111
|
+
- `.stoaignore` — gitignore-style path exclusions.
|
|
112
|
+
- `stoa.toml` — configuration with documented defaults.
|
|
113
|
+
|
|
114
|
+
## CLI
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
stoa scan [PATH]
|
|
118
|
+
--html PATH HTML report (default stoa-report.html)
|
|
119
|
+
--json PATH JSON registry (default stoa-registry.json)
|
|
120
|
+
--base GIT_REF enable diff-aware behavior (e.g. origin/main)
|
|
121
|
+
--strict fail on all unsuppressed high-confidence criticals
|
|
122
|
+
--fail-on {none,high,critical}
|
|
123
|
+
--fail-on-new {none,high,critical} applies with --base
|
|
124
|
+
--github-annotations emit ::error/::warning workflow commands
|
|
125
|
+
--summary-file PATH write a GitHub job-summary Markdown file
|
|
126
|
+
--config PATH explicit stoa.toml
|
|
127
|
+
--no-git skip git metadata
|
|
128
|
+
--include / --exclude extra path patterns (repeatable)
|
|
129
|
+
--verbose / --quiet
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Exit codes: `0` gate passed · `1` gate failed · `2` invalid arguments or
|
|
133
|
+
configuration · `3` scanner execution error.
|
|
134
|
+
|
|
135
|
+
Only high-confidence findings from gate-eligible rules (SEC001, SEC002) can
|
|
136
|
+
fail a scan; SQL-interpolation, network, and review-prompt rules report but
|
|
137
|
+
never gate, because static regex analysis cannot prove exploitability.
|
|
138
|
+
|
|
139
|
+
## Suppression
|
|
140
|
+
|
|
141
|
+
Inline, on the same or preceding line, always with explicit rule IDs:
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
# stoa: ignore[SEC003] trusted identifier from internal enum
|
|
145
|
+
query = f"SELECT * FROM {table_name}"
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
```javascript
|
|
149
|
+
const endpoint = "http://staging.internal.corp"; // stoa: ignore[NET001]
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
File-wide:
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
# stoa: ignore-file[CTRL001,CTRL002]
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Suppressed findings are counted and shown in reports — never silently
|
|
159
|
+
discarded. There is no blanket `ignore-all`.
|
|
160
|
+
|
|
161
|
+
## Configuration
|
|
162
|
+
|
|
163
|
+
`stoa.toml` in the repository root (all values shown are defaults):
|
|
164
|
+
|
|
165
|
+
```toml
|
|
166
|
+
fail_on = "none" # gate on all findings at/above this severity
|
|
167
|
+
fail_on_new = "critical" # gate on newly introduced findings (with --base)
|
|
168
|
+
max_file_bytes = 1000000
|
|
169
|
+
follow_symlinks = false
|
|
170
|
+
respect_gitignore = true
|
|
171
|
+
|
|
172
|
+
ignore_paths = [ # merged with built-in defaults (node_modules, dist, …)
|
|
173
|
+
"tests/snapshots/**",
|
|
174
|
+
]
|
|
175
|
+
|
|
176
|
+
[severity] # per-rule severity overrides
|
|
177
|
+
NET001 = "info"
|
|
178
|
+
|
|
179
|
+
[rules] # per-rule enable/disable
|
|
180
|
+
CTRL003 = false
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
`.stoaignore` uses gitignore syntax for path exclusions. Tests and fixtures
|
|
184
|
+
are *not* ignored by default — secret scanning is still useful there — but
|
|
185
|
+
they are downweighted for agent detection and placeholder-secret heuristics
|
|
186
|
+
apply.
|
|
187
|
+
|
|
188
|
+
## Rules
|
|
189
|
+
|
|
190
|
+
| Rule | Title | Default severity | Gates? |
|
|
191
|
+
|---|---|---|---|
|
|
192
|
+
| SEC001 | Possible hardcoded API credential | critical | yes (high confidence only) |
|
|
193
|
+
| SEC002 | Possible hardcoded password | high (critical at high confidence) | yes (high confidence only) |
|
|
194
|
+
| SEC003 | Interpolated SQL statement | high | no |
|
|
195
|
+
| REL001 | Swallowed exception | medium | no |
|
|
196
|
+
| NET001 | Insecure non-local HTTP endpoint | medium | no |
|
|
197
|
+
| NET002 | Request timeout not observed | medium | no |
|
|
198
|
+
| CTRL001–003 | Auth / validation / rate-limit control not observed | info | never |
|
|
199
|
+
|
|
200
|
+
## Security model
|
|
201
|
+
|
|
202
|
+
- **Local-first.** No source code is uploaded anywhere; Stoa makes no network
|
|
203
|
+
calls and collects no telemetry.
|
|
204
|
+
- **Secrets are redacted before serialization.** A detected credential is
|
|
205
|
+
replaced with `prefix…[REDACTED:sha256-fingerprint]` the moment it is
|
|
206
|
+
matched; the raw value never reaches terminal output, JSON, HTML,
|
|
207
|
+
annotations, summaries, or logs.
|
|
208
|
+
- Static analysis has **false positives and false negatives**. Findings are
|
|
209
|
+
evidence for review, not verdicts.
|
|
210
|
+
|
|
211
|
+
## Schema stability
|
|
212
|
+
|
|
213
|
+
The JSON output is versioned and additive-first — see [SCHEMA.md](SCHEMA.md).
|
|
214
|
+
Consumers must ignore unknown fields. The field names `autonomy_level`,
|
|
215
|
+
`loss_scenarios`, `liveness_state`, `policy_lines`, and `exposure_class` are
|
|
216
|
+
reserved for future versions. Treat `stoa-registry.json` as a CI artifact;
|
|
217
|
+
committing it to the repository is not recommended.
|
|
218
|
+
|
|
219
|
+
## Limitations
|
|
220
|
+
|
|
221
|
+
- Regex and pattern-based; no AST or semantic analysis.
|
|
222
|
+
- No runtime behavior: capability evidence does not prove a code path
|
|
223
|
+
executes, and call sites are not API call counts.
|
|
224
|
+
- No cross-repository or organization-wide infrastructure visibility: a
|
|
225
|
+
control "not observed in this file" may exist elsewhere.
|
|
226
|
+
- No definitive ownership inference — "last touched by" is commit history,
|
|
227
|
+
not ownership; CODEOWNERS support covers the common gitignore-style subset
|
|
228
|
+
of GitHub's pattern syntax (order-sensitive last-match-wins; bracket
|
|
229
|
+
character classes and per-file section syntax are not supported).
|
|
230
|
+
- Python, JavaScript, and TypeScript only.
|
|
231
|
+
- Only the repository-root `.gitignore` and `.stoaignore` are consulted.
|
|
232
|
+
|
|
233
|
+
## CI bypass considerations
|
|
234
|
+
|
|
235
|
+
- The workflow installs a **pinned** Stoa release from PyPI rather than
|
|
236
|
+
executing scanner code from the pull request, so a PR cannot modify the
|
|
237
|
+
scanner to bypass enforcement.
|
|
238
|
+
- Protect `.github/workflows/stoa.yml`, `stoa.toml`, and `.stoaignore` with
|
|
239
|
+
CODEOWNERS and branch protection — a PR that edits them can weaken the
|
|
240
|
+
gate, so those edits deserve review.
|
|
241
|
+
- Inline suppressions (`# stoa: ignore[...]`) change what the gate sees;
|
|
242
|
+
review them like any other security-relevant change.
|
|
243
|
+
|
|
244
|
+
## Development
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
python -m venv .venv && .venv/bin/pip install -e ".[dev]"
|
|
248
|
+
.venv/bin/pytest
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## License
|
|
252
|
+
|
|
253
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# Stoa
|
|
2
|
+
|
|
3
|
+
**A local-first AI agent inventory and risk scanner** that identifies agent
|
|
4
|
+
candidates with supporting evidence, maps their capabilities and integrations,
|
|
5
|
+
and prevents newly introduced high-confidence critical risks from entering
|
|
6
|
+
the codebase.
|
|
7
|
+
|
|
8
|
+
Stoa scans Python, JavaScript, and TypeScript repositories statically — no
|
|
9
|
+
runtime hooks, no uploads, no accounts.
|
|
10
|
+
|
|
11
|
+
## What Stoa does
|
|
12
|
+
|
|
13
|
+
- **Discovers likely AI agents** (LangChain, LangGraph, CrewAI, AutoGen,
|
|
14
|
+
LlamaIndex, OpenAI Agents SDK, PydanticAI, Bedrock Agents, Semantic Kernel,
|
|
15
|
+
LiteLLM, and raw provider calls) using weighted evidence, and shows exactly
|
|
16
|
+
*why* each candidate was detected.
|
|
17
|
+
- **Maps providers, frameworks, integrations, and capabilities** — e.g. an
|
|
18
|
+
agent candidate with payment access, database reads, and Slack messaging.
|
|
19
|
+
- **Detects high-confidence risks**: hardcoded credentials, hardcoded
|
|
20
|
+
passwords, interpolated SQL, swallowed exceptions, insecure HTTP, missing
|
|
21
|
+
request timeouts, and control-review prompts.
|
|
22
|
+
- **Produces local reports**: a manager-friendly self-contained HTML report
|
|
23
|
+
and a deterministic, versioned JSON registry.
|
|
24
|
+
- **Gates only newly introduced critical findings by default** — existing
|
|
25
|
+
debt never blocks an unrelated pull request.
|
|
26
|
+
|
|
27
|
+
Stoa reports *candidates* and *evidence*, not certainties. A "control not
|
|
28
|
+
observed" prompt is a review nudge, not a proven vulnerability.
|
|
29
|
+
|
|
30
|
+
## Quick start
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pipx install stoa-agent-risk
|
|
34
|
+
cd my-repository
|
|
35
|
+
stoa scan .
|
|
36
|
+
open stoa-report.html
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`stoa scan .` writes `stoa-report.html` and `stoa-registry.json` and exits 0
|
|
40
|
+
(report-only) unless a gate is configured. The JSON is designed to be read by
|
|
41
|
+
coding assistants too:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
stoa scan . --json stoa-registry.json
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## GitHub Actions
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
stoa init github
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
This creates (without overwriting existing files — use `--force` to
|
|
54
|
+
overwrite):
|
|
55
|
+
|
|
56
|
+
- `.github/workflows/stoa.yml` — full-history checkout, pinned Stoa install,
|
|
57
|
+
full-repository scan, diff against the PR base branch, GitHub annotations,
|
|
58
|
+
a job summary, uploaded HTML/JSON artifacts, and a gate that fails **only**
|
|
59
|
+
when the PR introduces a new high-confidence critical finding.
|
|
60
|
+
- `.stoaignore` — gitignore-style path exclusions.
|
|
61
|
+
- `stoa.toml` — configuration with documented defaults.
|
|
62
|
+
|
|
63
|
+
## CLI
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
stoa scan [PATH]
|
|
67
|
+
--html PATH HTML report (default stoa-report.html)
|
|
68
|
+
--json PATH JSON registry (default stoa-registry.json)
|
|
69
|
+
--base GIT_REF enable diff-aware behavior (e.g. origin/main)
|
|
70
|
+
--strict fail on all unsuppressed high-confidence criticals
|
|
71
|
+
--fail-on {none,high,critical}
|
|
72
|
+
--fail-on-new {none,high,critical} applies with --base
|
|
73
|
+
--github-annotations emit ::error/::warning workflow commands
|
|
74
|
+
--summary-file PATH write a GitHub job-summary Markdown file
|
|
75
|
+
--config PATH explicit stoa.toml
|
|
76
|
+
--no-git skip git metadata
|
|
77
|
+
--include / --exclude extra path patterns (repeatable)
|
|
78
|
+
--verbose / --quiet
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Exit codes: `0` gate passed · `1` gate failed · `2` invalid arguments or
|
|
82
|
+
configuration · `3` scanner execution error.
|
|
83
|
+
|
|
84
|
+
Only high-confidence findings from gate-eligible rules (SEC001, SEC002) can
|
|
85
|
+
fail a scan; SQL-interpolation, network, and review-prompt rules report but
|
|
86
|
+
never gate, because static regex analysis cannot prove exploitability.
|
|
87
|
+
|
|
88
|
+
## Suppression
|
|
89
|
+
|
|
90
|
+
Inline, on the same or preceding line, always with explicit rule IDs:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
# stoa: ignore[SEC003] trusted identifier from internal enum
|
|
94
|
+
query = f"SELECT * FROM {table_name}"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
const endpoint = "http://staging.internal.corp"; // stoa: ignore[NET001]
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
File-wide:
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
# stoa: ignore-file[CTRL001,CTRL002]
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Suppressed findings are counted and shown in reports — never silently
|
|
108
|
+
discarded. There is no blanket `ignore-all`.
|
|
109
|
+
|
|
110
|
+
## Configuration
|
|
111
|
+
|
|
112
|
+
`stoa.toml` in the repository root (all values shown are defaults):
|
|
113
|
+
|
|
114
|
+
```toml
|
|
115
|
+
fail_on = "none" # gate on all findings at/above this severity
|
|
116
|
+
fail_on_new = "critical" # gate on newly introduced findings (with --base)
|
|
117
|
+
max_file_bytes = 1000000
|
|
118
|
+
follow_symlinks = false
|
|
119
|
+
respect_gitignore = true
|
|
120
|
+
|
|
121
|
+
ignore_paths = [ # merged with built-in defaults (node_modules, dist, …)
|
|
122
|
+
"tests/snapshots/**",
|
|
123
|
+
]
|
|
124
|
+
|
|
125
|
+
[severity] # per-rule severity overrides
|
|
126
|
+
NET001 = "info"
|
|
127
|
+
|
|
128
|
+
[rules] # per-rule enable/disable
|
|
129
|
+
CTRL003 = false
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`.stoaignore` uses gitignore syntax for path exclusions. Tests and fixtures
|
|
133
|
+
are *not* ignored by default — secret scanning is still useful there — but
|
|
134
|
+
they are downweighted for agent detection and placeholder-secret heuristics
|
|
135
|
+
apply.
|
|
136
|
+
|
|
137
|
+
## Rules
|
|
138
|
+
|
|
139
|
+
| Rule | Title | Default severity | Gates? |
|
|
140
|
+
|---|---|---|---|
|
|
141
|
+
| SEC001 | Possible hardcoded API credential | critical | yes (high confidence only) |
|
|
142
|
+
| SEC002 | Possible hardcoded password | high (critical at high confidence) | yes (high confidence only) |
|
|
143
|
+
| SEC003 | Interpolated SQL statement | high | no |
|
|
144
|
+
| REL001 | Swallowed exception | medium | no |
|
|
145
|
+
| NET001 | Insecure non-local HTTP endpoint | medium | no |
|
|
146
|
+
| NET002 | Request timeout not observed | medium | no |
|
|
147
|
+
| CTRL001–003 | Auth / validation / rate-limit control not observed | info | never |
|
|
148
|
+
|
|
149
|
+
## Security model
|
|
150
|
+
|
|
151
|
+
- **Local-first.** No source code is uploaded anywhere; Stoa makes no network
|
|
152
|
+
calls and collects no telemetry.
|
|
153
|
+
- **Secrets are redacted before serialization.** A detected credential is
|
|
154
|
+
replaced with `prefix…[REDACTED:sha256-fingerprint]` the moment it is
|
|
155
|
+
matched; the raw value never reaches terminal output, JSON, HTML,
|
|
156
|
+
annotations, summaries, or logs.
|
|
157
|
+
- Static analysis has **false positives and false negatives**. Findings are
|
|
158
|
+
evidence for review, not verdicts.
|
|
159
|
+
|
|
160
|
+
## Schema stability
|
|
161
|
+
|
|
162
|
+
The JSON output is versioned and additive-first — see [SCHEMA.md](SCHEMA.md).
|
|
163
|
+
Consumers must ignore unknown fields. The field names `autonomy_level`,
|
|
164
|
+
`loss_scenarios`, `liveness_state`, `policy_lines`, and `exposure_class` are
|
|
165
|
+
reserved for future versions. Treat `stoa-registry.json` as a CI artifact;
|
|
166
|
+
committing it to the repository is not recommended.
|
|
167
|
+
|
|
168
|
+
## Limitations
|
|
169
|
+
|
|
170
|
+
- Regex and pattern-based; no AST or semantic analysis.
|
|
171
|
+
- No runtime behavior: capability evidence does not prove a code path
|
|
172
|
+
executes, and call sites are not API call counts.
|
|
173
|
+
- No cross-repository or organization-wide infrastructure visibility: a
|
|
174
|
+
control "not observed in this file" may exist elsewhere.
|
|
175
|
+
- No definitive ownership inference — "last touched by" is commit history,
|
|
176
|
+
not ownership; CODEOWNERS support covers the common gitignore-style subset
|
|
177
|
+
of GitHub's pattern syntax (order-sensitive last-match-wins; bracket
|
|
178
|
+
character classes and per-file section syntax are not supported).
|
|
179
|
+
- Python, JavaScript, and TypeScript only.
|
|
180
|
+
- Only the repository-root `.gitignore` and `.stoaignore` are consulted.
|
|
181
|
+
|
|
182
|
+
## CI bypass considerations
|
|
183
|
+
|
|
184
|
+
- The workflow installs a **pinned** Stoa release from PyPI rather than
|
|
185
|
+
executing scanner code from the pull request, so a PR cannot modify the
|
|
186
|
+
scanner to bypass enforcement.
|
|
187
|
+
- Protect `.github/workflows/stoa.yml`, `stoa.toml`, and `.stoaignore` with
|
|
188
|
+
CODEOWNERS and branch protection — a PR that edits them can weaken the
|
|
189
|
+
gate, so those edits deserve review.
|
|
190
|
+
- Inline suppressions (`# stoa: ignore[...]`) change what the gate sees;
|
|
191
|
+
review them like any other security-relevant change.
|
|
192
|
+
|
|
193
|
+
## Development
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
python -m venv .venv && .venv/bin/pip install -e ".[dev]"
|
|
197
|
+
.venv/bin/pytest
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## License
|
|
201
|
+
|
|
202
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "stoa-agent-risk"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Local-first AI agent inventory and risk scanner: finds agent candidates with evidence, maps capabilities and integrations, and gates newly introduced high-confidence critical risks."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { file = "LICENSE" }
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [{ name = "Ved Upadhyay", email = "iamved05@gmail.com" }]
|
|
13
|
+
keywords = ["ai-agents", "security", "static-analysis", "llm", "sast"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Topic :: Security",
|
|
24
|
+
"Topic :: Software Development :: Quality Assurance",
|
|
25
|
+
]
|
|
26
|
+
dependencies = [
|
|
27
|
+
"pathspec>=0.11",
|
|
28
|
+
"tomli>=2.0; python_version < '3.11'",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
dev = ["pytest>=7.4"]
|
|
33
|
+
|
|
34
|
+
[project.scripts]
|
|
35
|
+
stoa = "stoa.cli:main"
|
|
36
|
+
|
|
37
|
+
[project.urls]
|
|
38
|
+
Homepage = "https://stoa-features.vercel.app"
|
|
39
|
+
Repository = "https://github.com/iamved/stoa-agent-risk"
|
|
40
|
+
Issues = "https://github.com/iamved/stoa-agent-risk/issues"
|
|
41
|
+
Documentation = "https://github.com/iamved/stoa-agent-risk#readme"
|
|
42
|
+
|
|
43
|
+
[tool.setuptools.packages.find]
|
|
44
|
+
where = ["src"]
|
|
45
|
+
|
|
46
|
+
[tool.setuptools.package-data]
|
|
47
|
+
stoa = ["templates/*"]
|
|
48
|
+
|
|
49
|
+
[tool.pytest.ini_options]
|
|
50
|
+
testpaths = ["tests"]
|