valca 0.3.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 (81) hide show
  1. valca-0.3.0/AUTHORS +1 -0
  2. valca-0.3.0/LICENSE +73 -0
  3. valca-0.3.0/NOTICE +16 -0
  4. valca-0.3.0/PKG-INFO +430 -0
  5. valca-0.3.0/README.md +340 -0
  6. valca-0.3.0/pyproject.toml +40 -0
  7. valca-0.3.0/setup.cfg +4 -0
  8. valca-0.3.0/src/valca.egg-info/PKG-INFO +430 -0
  9. valca-0.3.0/src/valca.egg-info/SOURCES.txt +79 -0
  10. valca-0.3.0/src/valca.egg-info/dependency_links.txt +1 -0
  11. valca-0.3.0/src/valca.egg-info/entry_points.txt +3 -0
  12. valca-0.3.0/src/valca.egg-info/top_level.txt +1 -0
  13. valca-0.3.0/src/vigil/__init__.py +2 -0
  14. valca-0.3.0/src/vigil/cli.py +331 -0
  15. valca-0.3.0/src/vigil/config.py +40 -0
  16. valca-0.3.0/src/vigil/engine.py +79 -0
  17. valca-0.3.0/src/vigil/findingslog.py +76 -0
  18. valca-0.3.0/src/vigil/reporter.py +166 -0
  19. valca-0.3.0/src/vigil/rules/__init__.py +217 -0
  20. valca-0.3.0/src/vigil/rules/agency.py +178 -0
  21. valca-0.3.0/src/vigil/rules/auth.py +203 -0
  22. valca-0.3.0/src/vigil/rules/base.py +51 -0
  23. valca-0.3.0/src/vigil/rules/crypto.py +71 -0
  24. valca-0.3.0/src/vigil/rules/deps.py +180 -0
  25. valca-0.3.0/src/vigil/rules/deserialization.py +239 -0
  26. valca-0.3.0/src/vigil/rules/docker.py +340 -0
  27. valca-0.3.0/src/vigil/rules/dockerfile.py +318 -0
  28. valca-0.3.0/src/vigil/rules/gha.py +593 -0
  29. valca-0.3.0/src/vigil/rules/github_actions.py +186 -0
  30. valca-0.3.0/src/vigil/rules/iam.py +101 -0
  31. valca-0.3.0/src/vigil/rules/js_security.py +130 -0
  32. valca-0.3.0/src/vigil/rules/k8s.py +250 -0
  33. valca-0.3.0/src/vigil/rules/logging_secrets.py +339 -0
  34. valca-0.3.0/src/vigil/rules/mcp_security.py +147 -0
  35. valca-0.3.0/src/vigil/rules/nginx.py +85 -0
  36. valca-0.3.0/src/vigil/rules/packages.py +305 -0
  37. valca-0.3.0/src/vigil/rules/prompt_injection.py +185 -0
  38. valca-0.3.0/src/vigil/rules/python.py +81 -0
  39. valca-0.3.0/src/vigil/rules/rls.py +154 -0
  40. valca-0.3.0/src/vigil/rules/secrets.py +189 -0
  41. valca-0.3.0/src/vigil/rules/shell.py +96 -0
  42. valca-0.3.0/src/vigil/rules/swift.py +258 -0
  43. valca-0.3.0/src/vigil/rules/terraform.py +232 -0
  44. valca-0.3.0/src/vigil/rules/trivy.py +75 -0
  45. valca-0.3.0/src/vigil/rules/web.py +252 -0
  46. valca-0.3.0/src/vigil/rules/xss.py +144 -0
  47. valca-0.3.0/src/vigil/telemetry.py +169 -0
  48. valca-0.3.0/tests/test_cli_init.py +59 -0
  49. valca-0.3.0/tests/test_config.py +91 -0
  50. valca-0.3.0/tests/test_dedup.py +105 -0
  51. valca-0.3.0/tests/test_engine.py +131 -0
  52. valca-0.3.0/tests/test_findingslog.py +179 -0
  53. valca-0.3.0/tests/test_reporter.py +81 -0
  54. valca-0.3.0/tests/test_rules_agency.py +120 -0
  55. valca-0.3.0/tests/test_rules_auth.py +166 -0
  56. valca-0.3.0/tests/test_rules_crypto.py +80 -0
  57. valca-0.3.0/tests/test_rules_deps.py +188 -0
  58. valca-0.3.0/tests/test_rules_deserialization.py +218 -0
  59. valca-0.3.0/tests/test_rules_docker.py +528 -0
  60. valca-0.3.0/tests/test_rules_dockerfile.py +290 -0
  61. valca-0.3.0/tests/test_rules_gha.py +679 -0
  62. valca-0.3.0/tests/test_rules_github_actions.py +172 -0
  63. valca-0.3.0/tests/test_rules_iam.py +129 -0
  64. valca-0.3.0/tests/test_rules_js_security.py +127 -0
  65. valca-0.3.0/tests/test_rules_k8s.py +361 -0
  66. valca-0.3.0/tests/test_rules_logging.py +313 -0
  67. valca-0.3.0/tests/test_rules_mcp.py +100 -0
  68. valca-0.3.0/tests/test_rules_nginx.py +95 -0
  69. valca-0.3.0/tests/test_rules_packages.py +392 -0
  70. valca-0.3.0/tests/test_rules_prompt_injection.py +118 -0
  71. valca-0.3.0/tests/test_rules_python.py +107 -0
  72. valca-0.3.0/tests/test_rules_rls.py +117 -0
  73. valca-0.3.0/tests/test_rules_secrets.py +197 -0
  74. valca-0.3.0/tests/test_rules_secrets_extended.py +99 -0
  75. valca-0.3.0/tests/test_rules_shell.py +91 -0
  76. valca-0.3.0/tests/test_rules_swift.py +273 -0
  77. valca-0.3.0/tests/test_rules_terraform.py +288 -0
  78. valca-0.3.0/tests/test_rules_trivy.py +89 -0
  79. valca-0.3.0/tests/test_rules_web.py +173 -0
  80. valca-0.3.0/tests/test_rules_xss.py +112 -0
  81. valca-0.3.0/tests/test_telemetry.py +346 -0
valca-0.3.0/AUTHORS ADDED
@@ -0,0 +1 @@
1
+ Prem Kumar Akula
valca-0.3.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: https://github.com/vigilsec-io/cordon/issues
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.
valca-0.3.0/NOTICE ADDED
@@ -0,0 +1,16 @@
1
+ Valca (formerly published as Vigil / vigilsec)
2
+ Copyright (c) 2026 Prem Kumar Akula. All rights reserved.
3
+
4
+ Created: 2026-06-26
5
+ Author: Prem Kumar Akula
6
+
7
+ This software and all associated ideas, algorithms, rule definitions,
8
+ and product concepts are the exclusive intellectual property of
9
+ Prem Kumar Akula.
10
+
11
+ The VGL-D001 rule (docker-compose port binding to 0.0.0.0 without
12
+ 127.0.0.1 prefix) represents a novel detection approach not implemented
13
+ by any known IaC scanning tool as of the creation date above.
14
+
15
+ Commercial use requires a separate license agreement.
16
+ Contact: https://github.com/vigilsec-io/cordon/issues
valca-0.3.0/PKG-INFO ADDED
@@ -0,0 +1,430 @@
1
+ Metadata-Version: 2.4
2
+ Name: valca
3
+ Version: 0.3.0
4
+ Summary: AI coding security co-pilot — blocks insecure code at generation time
5
+ Author: Prem Kumar Akula
6
+ License: Business Source License 1.1
7
+
8
+ Parameters
9
+
10
+ Licensor: Prem Kumar Akula
11
+ Licensed Work: Vigil
12
+ The Licensed Work is (c) 2026 Prem Kumar Akula
13
+ Additional Use Grant: You may make production use of the Licensed Work,
14
+ provided such use does not include offering the Licensed
15
+ Work to third parties on a hosted or embedded basis in
16
+ order to compete with Vigil's paid commercial offerings.
17
+ Change Date: Four years from the date the specific Licensed Work
18
+ version is first publicly distributed under this License.
19
+ Change License: MIT License
20
+
21
+ For information about alternative licensing arrangements for the Licensed
22
+ Work, please contact: https://github.com/vigilsec-io/cordon/issues
23
+
24
+ Notice
25
+
26
+ The Business Source License (this document, or the "License") is not an Open
27
+ Source License, as defined by the Open Source Initiative. However, the
28
+ Licensed Work will eventually be made available under an Open Source License,
29
+ as stated in this License.
30
+
31
+ License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.
32
+ "Business Source License" is a trademark of MariaDB Corporation Ab.
33
+
34
+ -----------------------------------------------------------------------------
35
+
36
+ Business Source License 1.1
37
+
38
+ Terms
39
+
40
+ The Licensor hereby grants you the right to copy, modify, create derivative
41
+ works, redistribute, and make non-production use of the Licensed Work. The
42
+ Licensor may make an Additional Use Grant, above, permitting limited
43
+ production use.
44
+
45
+ Effective on the Change Date, or the fourth anniversary of the first publicly
46
+ available distribution of a specific version of the Licensed Work under this
47
+ License, whichever comes first, the Licensor hereby grants you rights under
48
+ the terms of the Change License, and the rights granted in the paragraph
49
+ above terminate.
50
+
51
+ If your use of the Licensed Work does not comply with the requirements
52
+ currently in effect as described in this License, you must purchase a
53
+ commercial license from the Licensor, its affiliated entities, or authorized
54
+ resellers, or you must refrain from using the Licensed Work.
55
+
56
+ All copies of the original and modified Licensed Work, and derivative works
57
+ of the Licensed Work, are subject to this License. This License applies
58
+ separately for each version of the Licensed Work and the Change Date may vary
59
+ for each version of the Licensed Work released by Licensor.
60
+
61
+ You must conspicuously display this License on each original or modified copy
62
+ of the Licensed Work. If you receive the Licensed Work in original or
63
+ modified form from a third party, the terms and conditions set forth in this
64
+ License apply to your use of that work.
65
+
66
+ Any use of the Licensed Work in violation of this License will automatically
67
+ terminate your rights under this License for the current and all other
68
+ versions of the Licensed Work.
69
+
70
+ This License does not grant you any right in any trademark or logo of
71
+ Licensor or its affiliates (provided that you may use a trademark or logo of
72
+ Licensor as expressly required by this License).
73
+
74
+ TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
75
+ AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
76
+ EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
77
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
78
+ TITLE.
79
+
80
+ Project-URL: Homepage, https://valca.io
81
+ Project-URL: Source, https://github.com/vigilsec-io/cordon
82
+ Project-URL: Issues, https://github.com/vigilsec-io/cordon/issues
83
+ Keywords: security,devsecops,docker,ai,claude,static-analysis,linter
84
+ Requires-Python: >=3.11
85
+ Description-Content-Type: text/markdown
86
+ License-File: LICENSE
87
+ License-File: NOTICE
88
+ License-File: AUTHORS
89
+ Dynamic: license-file
90
+
91
+ # Valca
92
+
93
+ **AI coding security co-pilot — blocks insecure code at the moment of generation.**
94
+
95
+ > **Formerly published as `vigilsec`.** The package is now `valca`. Both the `valca` and `vigil`
96
+ > commands work, so existing hooks and scripts keep running unchanged.
97
+
98
+ Valca 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.
99
+
100
+ ```
101
+ AI writes file → vigil scan → exit 2 → Claude Code blocks the write
102
+ ```
103
+
104
+ ---
105
+
106
+ ## The Problem
107
+
108
+ AI coding assistants reproduce the most common patterns in their training data. The most common patterns are insecure defaults.
109
+
110
+ The clearest example: every existing IaC scanner (Checkov, Trivy, Snyk, Semgrep) misses the docker-compose port binding that exposes your database to the internet:
111
+
112
+ ```yaml
113
+ ports:
114
+ - "5432:5432" # ← binds to 0.0.0.0, bypasses UFW, reachable from anywhere
115
+ ```
116
+
117
+ The correct form is `"127.0.0.1:5432:5432"`. Vigil catches it. Nothing else does.
118
+
119
+ ---
120
+
121
+ ## Install
122
+
123
+ ```bash
124
+ pip install valca
125
+ ```
126
+
127
+ **Wire the Claude Code hook (one time):**
128
+
129
+ ```bash
130
+ valca init --global # `vigil init --global` also works
131
+ ```
132
+
133
+ That's it. Every file Claude Code writes is now scanned before it saves. Reload Claude Code to activate.
134
+
135
+ ---
136
+
137
+ ## Network access
138
+
139
+ Valca's core scanning is fully offline — the package has **zero runtime dependencies** and the
140
+ engine never sends your code, file paths, or findings anywhere.
141
+
142
+ Three rules do reach the network, because checking whether a dependency is vulnerable or fabricated
143
+ is impossible offline. When a manifest (`requirements.txt`, `package.json`, lockfiles) is scanned,
144
+ these rules send **package names and version strings only** to:
145
+
146
+ | Host | Used by | What is sent |
147
+ |---|---|---|
148
+ | `api.osv.dev` | VGL-PKG001 (known CVE in a pinned version) | package name + version |
149
+ | `pypi.org` | VGL-PKG002/003/004 (hallucinated, stale, or suspicious package) | package name |
150
+ | `registry.npmjs.org` | VGL-PKG002/003/004 | package name |
151
+
152
+ Your source code, file contents, file paths, and scan results are never transmitted. If your
153
+ dependency inventory is itself sensitive, turn these rules off in `.vigilrc` and Valca runs
154
+ completely offline:
155
+
156
+ ```ini
157
+ disabled_rules = ["VGL-PKG001", "VGL-PKG002", "VGL-PKG003", "VGL-PKG004"]
158
+ ```
159
+
160
+ ---
161
+
162
+ ## Usage
163
+
164
+ ```bash
165
+ # Scan a single file
166
+ vigil scan docker-compose.yml
167
+
168
+ # Scan a directory
169
+ vigil scan ./my-project/
170
+
171
+ # JSON output (for CI / dashboards)
172
+ vigil scan ./my-project/ --format json
173
+
174
+ # SARIF output (for GitHub Advanced Security)
175
+ vigil scan ./my-project/ --format sarif > results.sarif
176
+
177
+ # Only report HIGH and above
178
+ vigil scan ./my-project/ --severity HIGH
179
+
180
+ # Open feedback & waitlist form
181
+ vigil feedback
182
+ ```
183
+
184
+ **Exit codes:**
185
+
186
+ | Code | Meaning |
187
+ |------|---------|
188
+ | `0` | No findings — write proceeds |
189
+ | `1` | Advisory findings only (MEDIUM / LOW / INFO) |
190
+ | `2` | CRITICAL or HIGH found — **Claude Code blocks the write** |
191
+
192
+ ---
193
+
194
+ ## See It in Action
195
+
196
+ **Blocking a vulnerable GitHub Actions workflow at write time:**
197
+
198
+ <!-- GIF: terminal showing claude writing ai-review.yml → vigil hook fires → BLOCKED + VGL-GHA009 CRITICAL → fix applied → clean -->
199
+ ![Vigil blocking Comment and Control attack](docs/demo-gha.gif)
200
+
201
+ In April 2026, researchers found that all three major AI coding agents (Claude Code, Gemini CLI, Copilot) could be hijacked to exfiltrate `ANTHROPIC_API_KEY` and `GITHUB_TOKEN` via a hidden HTML comment in a GitHub issue. CVSS 9.4. No special access required.
202
+
203
+ Vigil catches the vulnerable workflow (`issues:` trigger + AI agent + API key in env) before it reaches git — the only tool that does.
204
+
205
+ → [Full writeup: The Attack That Steals Your API Keys Through a GitHub Issue Comment](https://medium.com/@rjbdjnf/the-attack-that-steals-your-api-keys-through-a-github-issue-comment-b0301c1906dc)
206
+
207
+ ---
208
+
209
+ ## Rules
210
+
211
+ 36 rules across 9 categories. All built-in, stdlib-only, zero runtime dependencies.
212
+
213
+ ### Secrets & Injection (10 rules)
214
+
215
+ | Rule | Severity | What it catches |
216
+ |------|----------|----------------|
217
+ | VGL-S001 | CRITICAL | Hardcoded AWS / cloud API keys |
218
+ | VGL-S002 | CRITICAL | Hardcoded passwords (`password =`, `passwd =`) |
219
+ | VGL-S003 | HIGH | Generic API key / token assignments |
220
+ | VGL-S004 | HIGH | Generic secret / credential assignments |
221
+ | VGL-S005 | CRITICAL | JWT signing secrets |
222
+ | VGL-S006 | CRITICAL | PEM private keys |
223
+ | VGL-S007 | CRITICAL | Credential-embedded database URLs (`postgres://user:pass@host`) |
224
+ | VGL-S008 | CRITICAL | Stripe live keys (`sk_live_...`) |
225
+ | VGL-S009 | CRITICAL | Slack tokens (`xoxb-`, `xoxp-`) |
226
+ | VGL-S010 | CRITICAL | OpenAI, GitHub, GitLab, Google provider keys |
227
+ | VGL-I001 | CRITICAL | `eval()` with variable input |
228
+ | VGL-I002 | HIGH | `subprocess(shell=True)` with variable input |
229
+ | VGL-I003 | HIGH | `os.system()` with variable input |
230
+
231
+ ### Docker IaC (2 rules)
232
+
233
+ | Rule | Severity | What it catches |
234
+ |------|----------|----------------|
235
+ | VGL-D001 | CRITICAL | `"PORT:PORT"` binding — bypasses UFW, exposes to internet |
236
+ | VGL-D002 | HIGH | Hardcoded secrets in `environment:` blocks |
237
+
238
+ ### Dockerfile Hardening (3 rules)
239
+
240
+ | Rule | Severity | What it catches |
241
+ |------|----------|----------------|
242
+ | VGL-DF001 | HIGH | Container running as root (no `USER` directive) |
243
+ | VGL-DF002 | MEDIUM | Unpinned `:latest` base image |
244
+ | VGL-DF003 | CRITICAL | Secrets baked into image layers via `ENV`/`ARG` |
245
+
246
+ ### nginx (1 rule)
247
+
248
+ | Rule | Severity | What it catches |
249
+ |------|----------|----------------|
250
+ | VGL-N001 | HIGH | Missing security headers, `server_tokens on`, deprecated TLS |
251
+
252
+ ### Kubernetes (1 rule)
253
+
254
+ | Rule | Severity | What it catches |
255
+ |------|----------|----------------|
256
+ | VGL-K001 | CRITICAL/HIGH | `privileged: true`, `hostNetwork/hostPID/hostIPC: true` |
257
+
258
+ ### IAM Policies (1 rule)
259
+
260
+ | Rule | Severity | What it catches |
261
+ |------|----------|----------------|
262
+ | VGL-IAM001 | CRITICAL/HIGH | `"Action": "*"` and `"Resource": "*"` wildcards |
263
+
264
+ ### AI Agent Patterns (7 rules)
265
+
266
+ New category — catches the security anti-patterns unique to AI-generated agentic code.
267
+
268
+ | Rule | Severity | What it catches |
269
+ |------|----------|----------------|
270
+ | VGL-A001 | CRITICAL | LLM output piped to `subprocess.run()` / `os.system()` |
271
+ | VGL-A002 | HIGH | Hardcoded `auto_approve = True` / `skip_confirmation = True` |
272
+ | VGL-A003 | HIGH | Unbounded `while True` loop making LLM calls with no iteration cap |
273
+ | VGL-A004 | HIGH | LLM response content written directly to filesystem |
274
+ | VGL-PI001 | CRITICAL | User input embedded in system prompt |
275
+ | VGL-PI002 | HIGH | Raw `request.body` passed as LLM message content |
276
+ | VGL-PI003 | HIGH | `str.format()` on `system_prompt` variables with user-controlled data |
277
+ | VGL-PI004 | MEDIUM | Unsanitized tool output appended to conversation |
278
+
279
+ ### MCP Server Security (3 rules)
280
+
281
+ | Rule | Severity | What it catches |
282
+ |------|----------|----------------|
283
+ | VGL-MCP001 | CRITICAL | Injection strings in tool descriptions (`ignore previous instructions`) |
284
+ | VGL-MCP002 | HIGH | Dynamic tool descriptions built from user-controlled data |
285
+ | VGL-MCP003 | HIGH | Shell execution inside MCP handlers without a sandbox |
286
+
287
+ ### Shell Scripts (1 rule)
288
+
289
+ | Rule | Severity | What it catches |
290
+ |------|----------|----------------|
291
+ | VGL-S011 | HIGH | Secret variable passed inline to subprocess or SSH command — visible in `ps aux` on both machines |
292
+
293
+ ### Dependency CVEs (2 rules)
294
+
295
+ | Rule | Severity | What it catches |
296
+ |------|----------|----------------|
297
+ | VGL-DEP001 | HIGH | Python CVEs via `pip-audit` (runs on every `requirements.txt` change) |
298
+ | VGL-DEP002 | HIGH | npm CVEs via `npm audit` (runs on every `package.json` change) |
299
+
300
+ ### Trivy IaC Deep Scan (1 rule)
301
+
302
+ | Rule | Severity | What it catches |
303
+ |------|----------|----------------|
304
+ | VGL-T001 | HIGH | Dockerfile and Terraform misconfigurations via Trivy |
305
+
306
+ ---
307
+
308
+ ## Configuration
309
+
310
+ Place a `.vigilrc` file in your project root (or any ancestor directory):
311
+
312
+ ```toml
313
+ # .vigilrc
314
+ disabled_rules = ["VGL-T001"] # skip trivy scan for this project
315
+ min_severity = "HIGH" # only report HIGH and above
316
+ exclude_paths = ["vendor", "legacy"]
317
+ telemetry = false # opt out of anonymous local telemetry
318
+ ```
319
+
320
+ 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.
321
+
322
+ **Inline suppression** — for a specific line you've reviewed and accepted:
323
+
324
+ ```python
325
+ auto_approve = True # vigil: ignore
326
+ ```
327
+
328
+ Same pattern as `# noqa` (flake8) and `# nosec` (bandit).
329
+
330
+ ---
331
+
332
+ ## Opt-out
333
+
334
+ 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.
335
+
336
+ Opt out permanently:
337
+
338
+ ```bash
339
+ export VIGIL_NO_TELEMETRY=1
340
+ ```
341
+
342
+ Or in `.vigilrc`:
343
+
344
+ ```toml
345
+ telemetry = false
346
+ ```
347
+
348
+ ---
349
+
350
+ ## Adding a Rule
351
+
352
+ ```python
353
+ # src/vigil/rules/my_category.py
354
+ from pathlib import Path
355
+ from .base import Finding, Rule, Severity
356
+
357
+ class MyRule(Rule):
358
+ id = "VGL-X001"
359
+ name = "Descriptive rule name"
360
+ severity = Severity.HIGH
361
+
362
+ def applies_to(self, path: Path) -> bool:
363
+ return path.suffix == ".yml"
364
+
365
+ def check(self, path: Path) -> list[Finding]:
366
+ findings = []
367
+ for i, line in enumerate(path.read_text().splitlines(), 1):
368
+ if "bad_pattern" in line:
369
+ findings.append(Finding(
370
+ rule_id=self.id,
371
+ severity=self.severity,
372
+ message="Found bad pattern",
373
+ file_path=path,
374
+ line=i,
375
+ snippet=line.strip(),
376
+ fix="Do this instead.",
377
+ ))
378
+ return findings
379
+ ```
380
+
381
+ Then add it to `DEFAULT_RULES` in `src/vigil/rules/__init__.py`. Write tests. Done.
382
+
383
+ ---
384
+
385
+ ## GitHub Actions
386
+
387
+ Add Vigil to any CI pipeline — copy `vigil-action/workflow-template.yml` into your project's `.github/workflows/vigil.yml`:
388
+
389
+ ```yaml
390
+ - name: Install Vigil
391
+ run: pip install valca --quiet
392
+
393
+ - name: Scan with Vigil
394
+ run: vigil scan . --no-color
395
+
396
+ - name: Upload SARIF to GitHub Code Scanning
397
+ uses: github/codeql-action/upload-sarif@v3
398
+ with:
399
+ sarif_file: vigil-results.sarif
400
+ ```
401
+
402
+ Findings appear as inline annotations on PR diffs in the GitHub Security tab.
403
+
404
+ ---
405
+
406
+ ## Development
407
+
408
+ ```bash
409
+ git clone https://github.com/vigilsec-io/cordon.git
410
+ cd vigil
411
+ python3 -m venv venv && source venv/bin/activate
412
+ pip install -e ".[dev]"
413
+ pytest tests/ -v
414
+ ```
415
+
416
+ ---
417
+
418
+ ## License
419
+
420
+ [Business Source License 1.1](LICENSE) — free for non-commercial use. Commercial use requires a license agreement. Converts to MIT on 2030-06-26.
421
+
422
+ ---
423
+
424
+ ## Feedback
425
+
426
+ Found a false positive? Want a rule that doesn't exist yet? Building with AI agents and hitting patterns Vigil should catch?
427
+
428
+ [Open an issue → github.com/vigilsec-io/cordon/issues](https://github.com/vigilsec-io/cordon/issues)
429
+
430
+ Or: `vigil feedback`