vigilsec 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.
Files changed (47) hide show
  1. vigilsec-0.1.0/LICENSE +73 -0
  2. vigilsec-0.1.0/PKG-INFO +290 -0
  3. vigilsec-0.1.0/README.md +276 -0
  4. vigilsec-0.1.0/pyproject.toml +36 -0
  5. vigilsec-0.1.0/setup.cfg +4 -0
  6. vigilsec-0.1.0/src/vigil/__init__.py +2 -0
  7. vigilsec-0.1.0/src/vigil/cli.py +175 -0
  8. vigilsec-0.1.0/src/vigil/config.py +40 -0
  9. vigilsec-0.1.0/src/vigil/engine.py +68 -0
  10. vigilsec-0.1.0/src/vigil/reporter.py +119 -0
  11. vigilsec-0.1.0/src/vigil/rules/__init__.py +103 -0
  12. vigilsec-0.1.0/src/vigil/rules/agency.py +174 -0
  13. vigilsec-0.1.0/src/vigil/rules/base.py +48 -0
  14. vigilsec-0.1.0/src/vigil/rules/deps.py +122 -0
  15. vigilsec-0.1.0/src/vigil/rules/docker.py +145 -0
  16. vigilsec-0.1.0/src/vigil/rules/dockerfile.py +130 -0
  17. vigilsec-0.1.0/src/vigil/rules/iam.py +101 -0
  18. vigilsec-0.1.0/src/vigil/rules/k8s.py +75 -0
  19. vigilsec-0.1.0/src/vigil/rules/mcp_security.py +147 -0
  20. vigilsec-0.1.0/src/vigil/rules/nginx.py +85 -0
  21. vigilsec-0.1.0/src/vigil/rules/prompt_injection.py +185 -0
  22. vigilsec-0.1.0/src/vigil/rules/secrets.py +143 -0
  23. vigilsec-0.1.0/src/vigil/rules/shell.py +96 -0
  24. vigilsec-0.1.0/src/vigil/rules/trivy.py +62 -0
  25. vigilsec-0.1.0/src/vigil/telemetry.py +78 -0
  26. vigilsec-0.1.0/src/vigilsec.egg-info/PKG-INFO +290 -0
  27. vigilsec-0.1.0/src/vigilsec.egg-info/SOURCES.txt +45 -0
  28. vigilsec-0.1.0/src/vigilsec.egg-info/dependency_links.txt +1 -0
  29. vigilsec-0.1.0/src/vigilsec.egg-info/entry_points.txt +2 -0
  30. vigilsec-0.1.0/src/vigilsec.egg-info/top_level.txt +1 -0
  31. vigilsec-0.1.0/tests/test_cli_init.py +59 -0
  32. vigilsec-0.1.0/tests/test_config.py +91 -0
  33. vigilsec-0.1.0/tests/test_engine.py +91 -0
  34. vigilsec-0.1.0/tests/test_reporter.py +81 -0
  35. vigilsec-0.1.0/tests/test_rules_agency.py +97 -0
  36. vigilsec-0.1.0/tests/test_rules_docker.py +219 -0
  37. vigilsec-0.1.0/tests/test_rules_dockerfile.py +71 -0
  38. vigilsec-0.1.0/tests/test_rules_iam.py +129 -0
  39. vigilsec-0.1.0/tests/test_rules_k8s.py +121 -0
  40. vigilsec-0.1.0/tests/test_rules_mcp.py +100 -0
  41. vigilsec-0.1.0/tests/test_rules_nginx.py +95 -0
  42. vigilsec-0.1.0/tests/test_rules_prompt_injection.py +118 -0
  43. vigilsec-0.1.0/tests/test_rules_secrets.py +79 -0
  44. vigilsec-0.1.0/tests/test_rules_secrets_extended.py +95 -0
  45. vigilsec-0.1.0/tests/test_rules_shell.py +91 -0
  46. vigilsec-0.1.0/tests/test_rules_trivy.py +89 -0
  47. vigilsec-0.1.0/tests/test_telemetry.py +148 -0
vigilsec-0.1.0/LICENSE ADDED
@@ -0,0 +1,73 @@
1
+ Business Source License 1.1
2
+
3
+ Parameters
4
+
5
+ Licensor: Prem Kumar Akula
6
+ Licensed Work: Vigil
7
+ The Licensed Work is (c) 2026 Prem Kumar Akula
8
+ Additional Use Grant: You may make production use of the Licensed Work,
9
+ provided such use does not include offering the Licensed
10
+ Work to third parties on a hosted or embedded basis in
11
+ order to compete with Vigil's paid commercial offerings.
12
+ Change Date: Four years from the date the specific Licensed Work
13
+ version is first publicly distributed under this License.
14
+ Change License: MIT License
15
+
16
+ For information about alternative licensing arrangements for the Licensed
17
+ Work, please contact: prem.fwss@gmail.com
18
+
19
+ Notice
20
+
21
+ The Business Source License (this document, or the "License") is not an Open
22
+ Source License, as defined by the Open Source Initiative. However, the
23
+ Licensed Work will eventually be made available under an Open Source License,
24
+ as stated in this License.
25
+
26
+ License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.
27
+ "Business Source License" is a trademark of MariaDB Corporation Ab.
28
+
29
+ -----------------------------------------------------------------------------
30
+
31
+ Business Source License 1.1
32
+
33
+ Terms
34
+
35
+ The Licensor hereby grants you the right to copy, modify, create derivative
36
+ works, redistribute, and make non-production use of the Licensed Work. The
37
+ Licensor may make an Additional Use Grant, above, permitting limited
38
+ production use.
39
+
40
+ Effective on the Change Date, or the fourth anniversary of the first publicly
41
+ available distribution of a specific version of the Licensed Work under this
42
+ License, whichever comes first, the Licensor hereby grants you rights under
43
+ the terms of the Change License, and the rights granted in the paragraph
44
+ above terminate.
45
+
46
+ If your use of the Licensed Work does not comply with the requirements
47
+ currently in effect as described in this License, you must purchase a
48
+ commercial license from the Licensor, its affiliated entities, or authorized
49
+ resellers, or you must refrain from using the Licensed Work.
50
+
51
+ All copies of the original and modified Licensed Work, and derivative works
52
+ of the Licensed Work, are subject to this License. This License applies
53
+ separately for each version of the Licensed Work and the Change Date may vary
54
+ for each version of the Licensed Work released by Licensor.
55
+
56
+ You must conspicuously display this License on each original or modified copy
57
+ of the Licensed Work. If you receive the Licensed Work in original or
58
+ modified form from a third party, the terms and conditions set forth in this
59
+ License apply to your use of that work.
60
+
61
+ Any use of the Licensed Work in violation of this License will automatically
62
+ terminate your rights under this License for the current and all other
63
+ versions of the Licensed Work.
64
+
65
+ This License does not grant you any right in any trademark or logo of
66
+ Licensor or its affiliates (provided that you may use a trademark or logo of
67
+ Licensor as expressly required by this License).
68
+
69
+ TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
70
+ AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
71
+ EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
72
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
73
+ TITLE.
@@ -0,0 +1,290 @@
1
+ Metadata-Version: 2.4
2
+ Name: vigilsec
3
+ Version: 0.1.0
4
+ Summary: AI coding security co-pilot — blocks insecure code at generation time
5
+ Author-email: Prem Kumar Akula <prem.fwss@gmail.com>
6
+ License-Expression: BUSL-1.1
7
+ Project-URL: Homepage, https://thefwss.com/vigil
8
+ Project-URL: Feedback, https://thefwss.com/vigil
9
+ Keywords: security,devsecops,docker,ai,claude,static-analysis,linter
10
+ Requires-Python: >=3.11
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Dynamic: license-file
14
+
15
+ # Vigil
16
+
17
+ **AI coding security co-pilot — blocks insecure code at the moment of generation.**
18
+
19
+ Vigil intercepts every file an AI coding assistant writes and blocks it if CRITICAL or HIGH security findings are detected — before the file hits disk. It's the only tool that operates at generation time rather than post-commit.
20
+
21
+ ```
22
+ AI writes file → vigil scan → exit 2 → Claude Code blocks the write
23
+ ```
24
+
25
+ ---
26
+
27
+ ## The Problem
28
+
29
+ AI coding assistants reproduce the most common patterns in their training data. The most common patterns are insecure defaults.
30
+
31
+ The clearest example: every existing IaC scanner (Checkov, Trivy, Snyk, Semgrep) misses the docker-compose port binding that exposes your database to the internet:
32
+
33
+ ```yaml
34
+ ports:
35
+ - "5432:5432" # ← binds to 0.0.0.0, bypasses UFW, reachable from anywhere
36
+ ```
37
+
38
+ The correct form is `"127.0.0.1:5432:5432"`. Vigil catches it. Nothing else does.
39
+
40
+ ---
41
+
42
+ ## Install
43
+
44
+ ```bash
45
+ pip install vigilsec
46
+ ```
47
+
48
+ **Wire the Claude Code hook (one time):**
49
+
50
+ ```bash
51
+ vigil init --global
52
+ ```
53
+
54
+ That's it. Every file Claude Code writes is now scanned before it saves. Reload Claude Code to activate.
55
+
56
+ ---
57
+
58
+ ## Usage
59
+
60
+ ```bash
61
+ # Scan a single file
62
+ vigil scan docker-compose.yml
63
+
64
+ # Scan a directory
65
+ vigil scan ./my-project/
66
+
67
+ # JSON output (for CI / dashboards)
68
+ vigil scan ./my-project/ --format json
69
+
70
+ # SARIF output (for GitHub Advanced Security)
71
+ vigil scan ./my-project/ --format sarif > results.sarif
72
+
73
+ # Only report HIGH and above
74
+ vigil scan ./my-project/ --severity HIGH
75
+
76
+ # Open feedback & waitlist form
77
+ vigil feedback
78
+ ```
79
+
80
+ **Exit codes:**
81
+
82
+ | Code | Meaning |
83
+ |------|---------|
84
+ | `0` | No findings — write proceeds |
85
+ | `1` | Advisory findings only (MEDIUM / LOW / INFO) |
86
+ | `2` | CRITICAL or HIGH found — **Claude Code blocks the write** |
87
+
88
+ ---
89
+
90
+ ## Rules
91
+
92
+ 35 rules across 9 categories. All built-in, stdlib-only, zero runtime dependencies.
93
+
94
+ ### Secrets & Injection (10 rules)
95
+
96
+ | Rule | Severity | What it catches |
97
+ |------|----------|----------------|
98
+ | VGL-S001 | CRITICAL | Hardcoded AWS / cloud API keys |
99
+ | VGL-S002 | CRITICAL | Hardcoded passwords (`password =`, `passwd =`) |
100
+ | VGL-S003 | HIGH | Generic API key / token assignments |
101
+ | VGL-S004 | HIGH | Generic secret / credential assignments |
102
+ | VGL-S005 | CRITICAL | JWT signing secrets |
103
+ | VGL-S006 | CRITICAL | PEM private keys |
104
+ | VGL-S007 | CRITICAL | Credential-embedded database URLs (`postgres://user:pass@host`) |
105
+ | VGL-S008 | CRITICAL | Stripe live keys (`sk_live_...`) |
106
+ | VGL-S009 | CRITICAL | Slack tokens (`xoxb-`, `xoxp-`) |
107
+ | VGL-S010 | CRITICAL | OpenAI, GitHub, GitLab, Google provider keys |
108
+ | VGL-I001 | CRITICAL | `eval()` with variable input |
109
+ | VGL-I002 | HIGH | `subprocess(shell=True)` with variable input |
110
+ | VGL-I003 | HIGH | `os.system()` with variable input |
111
+
112
+ ### Docker IaC (2 rules)
113
+
114
+ | Rule | Severity | What it catches |
115
+ |------|----------|----------------|
116
+ | VGL-D001 | CRITICAL | `"PORT:PORT"` binding — bypasses UFW, exposes to internet |
117
+ | VGL-D002 | HIGH | Hardcoded secrets in `environment:` blocks |
118
+
119
+ ### Dockerfile Hardening (3 rules)
120
+
121
+ | Rule | Severity | What it catches |
122
+ |------|----------|----------------|
123
+ | VGL-DF001 | HIGH | Container running as root (no `USER` directive) |
124
+ | VGL-DF002 | MEDIUM | Unpinned `:latest` base image |
125
+ | VGL-DF003 | CRITICAL | Secrets baked into image layers via `ENV`/`ARG` |
126
+
127
+ ### nginx (1 rule)
128
+
129
+ | Rule | Severity | What it catches |
130
+ |------|----------|----------------|
131
+ | VGL-N001 | HIGH | Missing security headers, `server_tokens on`, deprecated TLS |
132
+
133
+ ### Kubernetes (1 rule)
134
+
135
+ | Rule | Severity | What it catches |
136
+ |------|----------|----------------|
137
+ | VGL-K001 | CRITICAL/HIGH | `privileged: true`, `hostNetwork/hostPID/hostIPC: true` |
138
+
139
+ ### IAM Policies (1 rule)
140
+
141
+ | Rule | Severity | What it catches |
142
+ |------|----------|----------------|
143
+ | VGL-IAM001 | CRITICAL/HIGH | `"Action": "*"` and `"Resource": "*"` wildcards |
144
+
145
+ ### AI Agent Patterns (7 rules)
146
+
147
+ New category — catches the security anti-patterns unique to AI-generated agentic code.
148
+
149
+ | Rule | Severity | What it catches |
150
+ |------|----------|----------------|
151
+ | VGL-A001 | CRITICAL | LLM output piped to `subprocess.run()` / `os.system()` |
152
+ | VGL-A002 | HIGH | Hardcoded `auto_approve = True` / `skip_confirmation = True` |
153
+ | VGL-A003 | HIGH | Unbounded `while True` loop making LLM calls with no iteration cap |
154
+ | VGL-A004 | HIGH | LLM response content written directly to filesystem |
155
+ | VGL-PI001 | CRITICAL | User input embedded in system prompt |
156
+ | VGL-PI002 | HIGH | Raw `request.body` passed as LLM message content |
157
+ | VGL-PI003 | HIGH | `str.format()` on `system_prompt` variables with user-controlled data |
158
+ | VGL-PI004 | MEDIUM | Unsanitized tool output appended to conversation |
159
+
160
+ ### MCP Server Security (3 rules)
161
+
162
+ | Rule | Severity | What it catches |
163
+ |------|----------|----------------|
164
+ | VGL-MCP001 | CRITICAL | Injection strings in tool descriptions (`ignore previous instructions`) |
165
+ | VGL-MCP002 | HIGH | Dynamic tool descriptions built from user-controlled data |
166
+ | VGL-MCP003 | HIGH | Shell execution inside MCP handlers without a sandbox |
167
+
168
+ ### Shell Scripts (1 rule)
169
+
170
+ | Rule | Severity | What it catches |
171
+ |------|----------|----------------|
172
+ | VGL-S011 | HIGH | Secret variable passed inline to subprocess or SSH command — visible in `ps aux` on both machines |
173
+
174
+ ### Dependency CVEs (2 rules)
175
+
176
+ | Rule | Severity | What it catches |
177
+ |------|----------|----------------|
178
+ | VGL-DEP001 | HIGH | Python CVEs via `pip-audit` (runs on every `requirements.txt` change) |
179
+ | VGL-DEP002 | HIGH | npm CVEs via `npm audit` (runs on every `package.json` change) |
180
+
181
+ ### Trivy IaC Deep Scan (1 rule)
182
+
183
+ | Rule | Severity | What it catches |
184
+ |------|----------|----------------|
185
+ | VGL-T001 | HIGH | Dockerfile and Terraform misconfigurations via Trivy |
186
+
187
+ ---
188
+
189
+ ## Configuration
190
+
191
+ Place a `.vigilrc` file in your project root (or any ancestor directory):
192
+
193
+ ```toml
194
+ # .vigilrc
195
+ disabled_rules = ["VGL-T001"] # skip trivy scan for this project
196
+ min_severity = "HIGH" # only report HIGH and above
197
+ exclude_paths = ["vendor", "legacy"]
198
+ telemetry = false # opt out of anonymous local telemetry
199
+ ```
200
+
201
+ Vigil walks up the directory tree to find the nearest `.vigilrc`. Child config always wins over parent. Monorepos can have per-project overrides alongside a workspace default.
202
+
203
+ **Inline suppression** — for a specific line you've reviewed and accepted:
204
+
205
+ ```python
206
+ auto_approve = True # vigil: ignore
207
+ ```
208
+
209
+ Same pattern as `# noqa` (flake8) and `# nosec` (bandit).
210
+
211
+ ---
212
+
213
+ ## Opt-out
214
+
215
+ Vigil collects anonymous, local-only telemetry: rule ID, severity, and file extension. No file paths, no code, no identifiable data. Stored at `~/.vigil/events.jsonl` — never sent anywhere.
216
+
217
+ Opt out permanently:
218
+
219
+ ```bash
220
+ export VIGIL_NO_TELEMETRY=1
221
+ ```
222
+
223
+ Or in `.vigilrc`:
224
+
225
+ ```toml
226
+ telemetry = false
227
+ ```
228
+
229
+ ---
230
+
231
+ ## Adding a Rule
232
+
233
+ ```python
234
+ # src/vigil/rules/my_category.py
235
+ from pathlib import Path
236
+ from .base import Finding, Rule, Severity
237
+
238
+ class MyRule(Rule):
239
+ id = "VGL-X001"
240
+ name = "Descriptive rule name"
241
+ severity = Severity.HIGH
242
+
243
+ def applies_to(self, path: Path) -> bool:
244
+ return path.suffix == ".yml"
245
+
246
+ def check(self, path: Path) -> list[Finding]:
247
+ findings = []
248
+ for i, line in enumerate(path.read_text().splitlines(), 1):
249
+ if "bad_pattern" in line:
250
+ findings.append(Finding(
251
+ rule_id=self.id,
252
+ severity=self.severity,
253
+ message="Found bad pattern",
254
+ file_path=path,
255
+ line=i,
256
+ snippet=line.strip(),
257
+ fix="Do this instead.",
258
+ ))
259
+ return findings
260
+ ```
261
+
262
+ Then add it to `DEFAULT_RULES` in `src/vigil/rules/__init__.py`. Write tests. Done.
263
+
264
+ ---
265
+
266
+ ## Development
267
+
268
+ ```bash
269
+ git clone http://your-gitea/fwss/vigil.git
270
+ cd vigil
271
+ python3 -m venv venv && source venv/bin/activate
272
+ pip install -e ".[dev]"
273
+ pytest tests/ -v
274
+ ```
275
+
276
+ ---
277
+
278
+ ## License
279
+
280
+ [Business Source License 1.1](LICENSE) — free for non-commercial use. Commercial use requires a license agreement. Converts to MIT on 2030-06-26.
281
+
282
+ ---
283
+
284
+ ## Feedback & Waitlist
285
+
286
+ Found a false positive? Want a rule that doesn't exist yet? Building with AI agents and hitting patterns Vigil should catch?
287
+
288
+ [Join the waitlist → thefwss.com/vigil](https://thefwss.com/vigil)
289
+
290
+ Or: `vigil feedback`
@@ -0,0 +1,276 @@
1
+ # Vigil
2
+
3
+ **AI coding security co-pilot — blocks insecure code at the moment of generation.**
4
+
5
+ Vigil intercepts every file an AI coding assistant writes and blocks it if CRITICAL or HIGH security findings are detected — before the file hits disk. It's the only tool that operates at generation time rather than post-commit.
6
+
7
+ ```
8
+ AI writes file → vigil scan → exit 2 → Claude Code blocks the write
9
+ ```
10
+
11
+ ---
12
+
13
+ ## The Problem
14
+
15
+ AI coding assistants reproduce the most common patterns in their training data. The most common patterns are insecure defaults.
16
+
17
+ The clearest example: every existing IaC scanner (Checkov, Trivy, Snyk, Semgrep) misses the docker-compose port binding that exposes your database to the internet:
18
+
19
+ ```yaml
20
+ ports:
21
+ - "5432:5432" # ← binds to 0.0.0.0, bypasses UFW, reachable from anywhere
22
+ ```
23
+
24
+ The correct form is `"127.0.0.1:5432:5432"`. Vigil catches it. Nothing else does.
25
+
26
+ ---
27
+
28
+ ## Install
29
+
30
+ ```bash
31
+ pip install vigilsec
32
+ ```
33
+
34
+ **Wire the Claude Code hook (one time):**
35
+
36
+ ```bash
37
+ vigil init --global
38
+ ```
39
+
40
+ That's it. Every file Claude Code writes is now scanned before it saves. Reload Claude Code to activate.
41
+
42
+ ---
43
+
44
+ ## Usage
45
+
46
+ ```bash
47
+ # Scan a single file
48
+ vigil scan docker-compose.yml
49
+
50
+ # Scan a directory
51
+ vigil scan ./my-project/
52
+
53
+ # JSON output (for CI / dashboards)
54
+ vigil scan ./my-project/ --format json
55
+
56
+ # SARIF output (for GitHub Advanced Security)
57
+ vigil scan ./my-project/ --format sarif > results.sarif
58
+
59
+ # Only report HIGH and above
60
+ vigil scan ./my-project/ --severity HIGH
61
+
62
+ # Open feedback & waitlist form
63
+ vigil feedback
64
+ ```
65
+
66
+ **Exit codes:**
67
+
68
+ | Code | Meaning |
69
+ |------|---------|
70
+ | `0` | No findings — write proceeds |
71
+ | `1` | Advisory findings only (MEDIUM / LOW / INFO) |
72
+ | `2` | CRITICAL or HIGH found — **Claude Code blocks the write** |
73
+
74
+ ---
75
+
76
+ ## Rules
77
+
78
+ 35 rules across 9 categories. All built-in, stdlib-only, zero runtime dependencies.
79
+
80
+ ### Secrets & Injection (10 rules)
81
+
82
+ | Rule | Severity | What it catches |
83
+ |------|----------|----------------|
84
+ | VGL-S001 | CRITICAL | Hardcoded AWS / cloud API keys |
85
+ | VGL-S002 | CRITICAL | Hardcoded passwords (`password =`, `passwd =`) |
86
+ | VGL-S003 | HIGH | Generic API key / token assignments |
87
+ | VGL-S004 | HIGH | Generic secret / credential assignments |
88
+ | VGL-S005 | CRITICAL | JWT signing secrets |
89
+ | VGL-S006 | CRITICAL | PEM private keys |
90
+ | VGL-S007 | CRITICAL | Credential-embedded database URLs (`postgres://user:pass@host`) |
91
+ | VGL-S008 | CRITICAL | Stripe live keys (`sk_live_...`) |
92
+ | VGL-S009 | CRITICAL | Slack tokens (`xoxb-`, `xoxp-`) |
93
+ | VGL-S010 | CRITICAL | OpenAI, GitHub, GitLab, Google provider keys |
94
+ | VGL-I001 | CRITICAL | `eval()` with variable input |
95
+ | VGL-I002 | HIGH | `subprocess(shell=True)` with variable input |
96
+ | VGL-I003 | HIGH | `os.system()` with variable input |
97
+
98
+ ### Docker IaC (2 rules)
99
+
100
+ | Rule | Severity | What it catches |
101
+ |------|----------|----------------|
102
+ | VGL-D001 | CRITICAL | `"PORT:PORT"` binding — bypasses UFW, exposes to internet |
103
+ | VGL-D002 | HIGH | Hardcoded secrets in `environment:` blocks |
104
+
105
+ ### Dockerfile Hardening (3 rules)
106
+
107
+ | Rule | Severity | What it catches |
108
+ |------|----------|----------------|
109
+ | VGL-DF001 | HIGH | Container running as root (no `USER` directive) |
110
+ | VGL-DF002 | MEDIUM | Unpinned `:latest` base image |
111
+ | VGL-DF003 | CRITICAL | Secrets baked into image layers via `ENV`/`ARG` |
112
+
113
+ ### nginx (1 rule)
114
+
115
+ | Rule | Severity | What it catches |
116
+ |------|----------|----------------|
117
+ | VGL-N001 | HIGH | Missing security headers, `server_tokens on`, deprecated TLS |
118
+
119
+ ### Kubernetes (1 rule)
120
+
121
+ | Rule | Severity | What it catches |
122
+ |------|----------|----------------|
123
+ | VGL-K001 | CRITICAL/HIGH | `privileged: true`, `hostNetwork/hostPID/hostIPC: true` |
124
+
125
+ ### IAM Policies (1 rule)
126
+
127
+ | Rule | Severity | What it catches |
128
+ |------|----------|----------------|
129
+ | VGL-IAM001 | CRITICAL/HIGH | `"Action": "*"` and `"Resource": "*"` wildcards |
130
+
131
+ ### AI Agent Patterns (7 rules)
132
+
133
+ New category — catches the security anti-patterns unique to AI-generated agentic code.
134
+
135
+ | Rule | Severity | What it catches |
136
+ |------|----------|----------------|
137
+ | VGL-A001 | CRITICAL | LLM output piped to `subprocess.run()` / `os.system()` |
138
+ | VGL-A002 | HIGH | Hardcoded `auto_approve = True` / `skip_confirmation = True` |
139
+ | VGL-A003 | HIGH | Unbounded `while True` loop making LLM calls with no iteration cap |
140
+ | VGL-A004 | HIGH | LLM response content written directly to filesystem |
141
+ | VGL-PI001 | CRITICAL | User input embedded in system prompt |
142
+ | VGL-PI002 | HIGH | Raw `request.body` passed as LLM message content |
143
+ | VGL-PI003 | HIGH | `str.format()` on `system_prompt` variables with user-controlled data |
144
+ | VGL-PI004 | MEDIUM | Unsanitized tool output appended to conversation |
145
+
146
+ ### MCP Server Security (3 rules)
147
+
148
+ | Rule | Severity | What it catches |
149
+ |------|----------|----------------|
150
+ | VGL-MCP001 | CRITICAL | Injection strings in tool descriptions (`ignore previous instructions`) |
151
+ | VGL-MCP002 | HIGH | Dynamic tool descriptions built from user-controlled data |
152
+ | VGL-MCP003 | HIGH | Shell execution inside MCP handlers without a sandbox |
153
+
154
+ ### Shell Scripts (1 rule)
155
+
156
+ | Rule | Severity | What it catches |
157
+ |------|----------|----------------|
158
+ | VGL-S011 | HIGH | Secret variable passed inline to subprocess or SSH command — visible in `ps aux` on both machines |
159
+
160
+ ### Dependency CVEs (2 rules)
161
+
162
+ | Rule | Severity | What it catches |
163
+ |------|----------|----------------|
164
+ | VGL-DEP001 | HIGH | Python CVEs via `pip-audit` (runs on every `requirements.txt` change) |
165
+ | VGL-DEP002 | HIGH | npm CVEs via `npm audit` (runs on every `package.json` change) |
166
+
167
+ ### Trivy IaC Deep Scan (1 rule)
168
+
169
+ | Rule | Severity | What it catches |
170
+ |------|----------|----------------|
171
+ | VGL-T001 | HIGH | Dockerfile and Terraform misconfigurations via Trivy |
172
+
173
+ ---
174
+
175
+ ## Configuration
176
+
177
+ Place a `.vigilrc` file in your project root (or any ancestor directory):
178
+
179
+ ```toml
180
+ # .vigilrc
181
+ disabled_rules = ["VGL-T001"] # skip trivy scan for this project
182
+ min_severity = "HIGH" # only report HIGH and above
183
+ exclude_paths = ["vendor", "legacy"]
184
+ telemetry = false # opt out of anonymous local telemetry
185
+ ```
186
+
187
+ Vigil walks up the directory tree to find the nearest `.vigilrc`. Child config always wins over parent. Monorepos can have per-project overrides alongside a workspace default.
188
+
189
+ **Inline suppression** — for a specific line you've reviewed and accepted:
190
+
191
+ ```python
192
+ auto_approve = True # vigil: ignore
193
+ ```
194
+
195
+ Same pattern as `# noqa` (flake8) and `# nosec` (bandit).
196
+
197
+ ---
198
+
199
+ ## Opt-out
200
+
201
+ Vigil collects anonymous, local-only telemetry: rule ID, severity, and file extension. No file paths, no code, no identifiable data. Stored at `~/.vigil/events.jsonl` — never sent anywhere.
202
+
203
+ Opt out permanently:
204
+
205
+ ```bash
206
+ export VIGIL_NO_TELEMETRY=1
207
+ ```
208
+
209
+ Or in `.vigilrc`:
210
+
211
+ ```toml
212
+ telemetry = false
213
+ ```
214
+
215
+ ---
216
+
217
+ ## Adding a Rule
218
+
219
+ ```python
220
+ # src/vigil/rules/my_category.py
221
+ from pathlib import Path
222
+ from .base import Finding, Rule, Severity
223
+
224
+ class MyRule(Rule):
225
+ id = "VGL-X001"
226
+ name = "Descriptive rule name"
227
+ severity = Severity.HIGH
228
+
229
+ def applies_to(self, path: Path) -> bool:
230
+ return path.suffix == ".yml"
231
+
232
+ def check(self, path: Path) -> list[Finding]:
233
+ findings = []
234
+ for i, line in enumerate(path.read_text().splitlines(), 1):
235
+ if "bad_pattern" in line:
236
+ findings.append(Finding(
237
+ rule_id=self.id,
238
+ severity=self.severity,
239
+ message="Found bad pattern",
240
+ file_path=path,
241
+ line=i,
242
+ snippet=line.strip(),
243
+ fix="Do this instead.",
244
+ ))
245
+ return findings
246
+ ```
247
+
248
+ Then add it to `DEFAULT_RULES` in `src/vigil/rules/__init__.py`. Write tests. Done.
249
+
250
+ ---
251
+
252
+ ## Development
253
+
254
+ ```bash
255
+ git clone http://your-gitea/fwss/vigil.git
256
+ cd vigil
257
+ python3 -m venv venv && source venv/bin/activate
258
+ pip install -e ".[dev]"
259
+ pytest tests/ -v
260
+ ```
261
+
262
+ ---
263
+
264
+ ## License
265
+
266
+ [Business Source License 1.1](LICENSE) — free for non-commercial use. Commercial use requires a license agreement. Converts to MIT on 2030-06-26.
267
+
268
+ ---
269
+
270
+ ## Feedback & Waitlist
271
+
272
+ Found a false positive? Want a rule that doesn't exist yet? Building with AI agents and hitting patterns Vigil should catch?
273
+
274
+ [Join the waitlist → thefwss.com/vigil](https://thefwss.com/vigil)
275
+
276
+ Or: `vigil feedback`
@@ -0,0 +1,36 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "vigilsec"
7
+ version = "0.1.0"
8
+ description = "AI coding security co-pilot — blocks insecure code at generation time"
9
+ readme = "README.md"
10
+ license = "BUSL-1.1"
11
+ license-files = ["LICENSE"]
12
+ authors = [{name = "Prem Kumar Akula", email = "prem.fwss@gmail.com"}]
13
+ requires-python = ">=3.11"
14
+ dependencies = []
15
+ keywords = ["security", "devsecops", "docker", "ai", "claude", "static-analysis", "linter"]
16
+
17
+ [project.urls]
18
+ Homepage = "https://thefwss.com/vigil"
19
+ Feedback = "https://thefwss.com/vigil"
20
+
21
+ [project.scripts]
22
+ vigil = "vigil.cli:main"
23
+
24
+ [tool.setuptools.packages.find]
25
+ where = ["src"]
26
+
27
+ [tool.pytest.ini_options]
28
+ testpaths = ["tests"]
29
+ pythonpath = ["src"]
30
+
31
+ [tool.bandit]
32
+ exclude_dirs = ["tests", ".venv", "venv"]
33
+ # B101: assert in tests; B404/B603/B607: vigil intentionally shells out to trivy/pip-audit/npm
34
+ # with hardcoded command names and list-form args — no shell injection possible
35
+ # B110: bare except in telemetry.py is intentional — telemetry must never crash a scan
36
+ skips = ["B101", "B404", "B603", "B607", "B110"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,2 @@
1
+ """Vigil — AI coding security co-pilot."""
2
+ __version__ = "0.1.0"