kestrix-scan 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 (72) hide show
  1. kestrix_scan-0.1.0/LICENSE +202 -0
  2. kestrix_scan-0.1.0/NOTICE +34 -0
  3. kestrix_scan-0.1.0/PKG-INFO +371 -0
  4. kestrix_scan-0.1.0/README.md +337 -0
  5. kestrix_scan-0.1.0/pyproject.toml +87 -0
  6. kestrix_scan-0.1.0/pyproject.toml.orig +60 -0
  7. kestrix_scan-0.1.0/src/kestrix_scan/__init__.py +86 -0
  8. kestrix_scan-0.1.0/src/kestrix_scan/__main__.py +9 -0
  9. kestrix_scan-0.1.0/src/kestrix_scan/about.py +8 -0
  10. kestrix_scan-0.1.0/src/kestrix_scan/agent_config.py +288 -0
  11. kestrix_scan-0.1.0/src/kestrix_scan/analyze.py +424 -0
  12. kestrix_scan-0.1.0/src/kestrix_scan/c_tokens.py +486 -0
  13. kestrix_scan-0.1.0/src/kestrix_scan/ci_rules.py +310 -0
  14. kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/.claude-plugin/plugin.json +17 -0
  15. kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/hooks/hooks.json +83 -0
  16. kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/hooks/kestrix_hook.py +981 -0
  17. kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/fix/SKILL.md +30 -0
  18. kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/fixing-security-findings/SKILL.md +3921 -0
  19. kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/kestrix-security/SKILL.md +244 -0
  20. kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/kestrix-security/reference/bitcoin.md +52 -0
  21. kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/kestrix-security/reference/detect.md +99 -0
  22. kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/kestrix-security/reference/findings-forensics.md +62 -0
  23. kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/kestrix-security/reference/findings-mail.md +118 -0
  24. kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/kestrix-security/reference/findings-webcheck.md +97 -0
  25. kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/kestrix-security/reference/json-fields.md +94 -0
  26. kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/review/SKILL.md +31 -0
  27. kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/scan/SKILL.md +32 -0
  28. kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/secure-code-review/SKILL.md +132 -0
  29. kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/status/SKILL.md +26 -0
  30. kestrix_scan-0.1.0/src/kestrix_scan/cli.py +491 -0
  31. kestrix_scan-0.1.0/src/kestrix_scan/config.py +267 -0
  32. kestrix_scan-0.1.0/src/kestrix_scan/deps.py +333 -0
  33. kestrix_scan-0.1.0/src/kestrix_scan/docker_rules.py +291 -0
  34. kestrix_scan-0.1.0/src/kestrix_scan/ecoversions.py +272 -0
  35. kestrix_scan-0.1.0/src/kestrix_scan/errors.py +24 -0
  36. kestrix_scan-0.1.0/src/kestrix_scan/hook.py +296 -0
  37. kestrix_scan-0.1.0/src/kestrix_scan/html_tokens.py +236 -0
  38. kestrix_scan-0.1.0/src/kestrix_scan/iac.py +55 -0
  39. kestrix_scan-0.1.0/src/kestrix_scan/infra_rules.py +490 -0
  40. kestrix_scan-0.1.0/src/kestrix_scan/init.py +237 -0
  41. kestrix_scan-0.1.0/src/kestrix_scan/install_guard.py +481 -0
  42. kestrix_scan-0.1.0/src/kestrix_scan/js_index.py +1498 -0
  43. kestrix_scan-0.1.0/src/kestrix_scan/js_rules.py +945 -0
  44. kestrix_scan-0.1.0/src/kestrix_scan/js_tokens.py +311 -0
  45. kestrix_scan-0.1.0/src/kestrix_scan/lockfiles.py +363 -0
  46. kestrix_scan-0.1.0/src/kestrix_scan/lockfiles_more.py +325 -0
  47. kestrix_scan-0.1.0/src/kestrix_scan/models.py +196 -0
  48. kestrix_scan-0.1.0/src/kestrix_scan/osvdb.py +584 -0
  49. kestrix_scan-0.1.0/src/kestrix_scan/php_index.py +787 -0
  50. kestrix_scan-0.1.0/src/kestrix_scan/php_rules.py +599 -0
  51. kestrix_scan-0.1.0/src/kestrix_scan/php_tokens.py +202 -0
  52. kestrix_scan-0.1.0/src/kestrix_scan/plugin.py +100 -0
  53. kestrix_scan-0.1.0/src/kestrix_scan/popular.py +283 -0
  54. kestrix_scan-0.1.0/src/kestrix_scan/popular_names.json +1 -0
  55. kestrix_scan-0.1.0/src/kestrix_scan/py.typed +0 -0
  56. kestrix_scan-0.1.0/src/kestrix_scan/pytest_plugin.py +66 -0
  57. kestrix_scan-0.1.0/src/kestrix_scan/python_rules.py +1595 -0
  58. kestrix_scan-0.1.0/src/kestrix_scan/registry.py +2195 -0
  59. kestrix_scan-0.1.0/src/kestrix_scan/ruby_tokens.py +310 -0
  60. kestrix_scan-0.1.0/src/kestrix_scan/sarif.py +143 -0
  61. kestrix_scan-0.1.0/src/kestrix_scan/secrets.py +217 -0
  62. kestrix_scan-0.1.0/src/kestrix_scan/server_index.py +1022 -0
  63. kestrix_scan-0.1.0/src/kestrix_scan/server_rules.py +885 -0
  64. kestrix_scan-0.1.0/src/kestrix_scan/shell_rules.py +299 -0
  65. kestrix_scan-0.1.0/src/kestrix_scan/skill.py +174 -0
  66. kestrix_scan-0.1.0/src/kestrix_scan/sql_rules.py +207 -0
  67. kestrix_scan-0.1.0/src/kestrix_scan/systems_rules.py +809 -0
  68. kestrix_scan-0.1.0/src/kestrix_scan/taint.py +1055 -0
  69. kestrix_scan-0.1.0/src/kestrix_scan/versions.py +218 -0
  70. kestrix_scan-0.1.0/src/kestrix_scan/walk.py +315 -0
  71. kestrix_scan-0.1.0/src/kestrix_scan/web_rules.py +352 -0
  72. kestrix_scan-0.1.0/src/kestrix_scan/yaml_lite.py +475 -0
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
@@ -0,0 +1,34 @@
1
+ Kestrix
2
+ Copyright 2026 Ruthvik Bandari
3
+
4
+ The Bitcoin quantum-risk module is adapted from BitShield (MIT Bitcoin Expo 2026, Team ACE).
5
+ The forensics module is adapted from CyberSafeX Detection Suite (MIT License, Ruthvik Bandari).
6
+
7
+ The code scanner's rules (packages/kestrix-scan/src/kestrix_scan/registry.py) were written for Kestrix from their CWE entries
8
+ and the language, library and standard documentation cited per rule in
9
+ docs/modules/code-rules-provenance.md. No rule text, pattern or code from other scanners is included.
10
+
11
+ Dependency scanning (packages/kestrix-scan/src/kestrix_scan/osvdb.py, deps.py, versions.py, lockfiles.py):
12
+ no advisory data is included in this repository or in the kestrix-scan package. `kestrix-scan db update`
13
+ downloads it to the user's cache from OSV (https://osv.dev, https://google.github.io/osv.dev/data/), and
14
+ findings and install-guard messages quote advisory ids and summaries from it. OSV redistributes each source
15
+ under that source's license; the sources present in the PyPI and npm exports (checked 2026-10-20) are:
16
+
17
+ - GitHub Advisory Database (GHSA- ids), GitHub, Inc.: CC-BY 4.0. https://github.com/github/advisory-database
18
+ - PyPI Advisory Database (PYSEC- ids), Python Packaging Authority: CC-BY 4.0. https://github.com/pypa/advisory-database
19
+ - OpenSSF Malicious Packages (MAL- ids), Open Source Security Foundation: Apache-2.0.
20
+ https://github.com/ossf/malicious-packages
21
+ - OSS-Fuzz (OSV- ids), Google: CC-BY 4.0. https://github.com/google/oss-fuzz-vulns
22
+ - Erlang Ecosystem Foundation CNA (EEF- ids): CC-BY 4.0. https://github.com/erlef/security-database
23
+ - Global Security Database (GSD- ids), Cloud Security Alliance: CC0 1.0. https://github.com/cloudsecurityalliance/gsd-database
24
+
25
+ The OSV schema (https://ossf.github.io/osv-schema/) is Apache-2.0. PEP 440 version ordering and SemVer 2.0
26
+ precedence were implemented for Kestrix from the PEP 440 text (public domain) and the SemVer specification
27
+ (CC BY 3.0); no code from `packaging` or any other version library is included. The CVSS v3.1 base-score
28
+ formula follows the FIRST CVSS v3.1 specification (https://www.first.org/cvss/v3.1/specification-document).
29
+ The tests use synthetic advisories only.
30
+
31
+ Third-party notices policy: third-party code, rules or data are added to this repository only under a
32
+ license that permits redistribution with Apache-2.0, and each addition is recorded in this file with its
33
+ source, copyright holder and license in the same change. Datasets for the code-vulnerability research are
34
+ not redistributed; their licenses and usage tiers are recorded in docs/research/dataset-licenses.md.
@@ -0,0 +1,371 @@
1
+ Metadata-Version: 2.4
2
+ Name: kestrix-scan
3
+ Version: 0.1.0
4
+ Summary: Kestrix code scanner: local, zero-dependency security checks for 13 languages (Python, JavaScript, TypeScript, PHP, Go, Java, Kotlin, C#, Ruby, C, C++, Rust, Swift), web, SQL, CI and infrastructure files, hard-coded secrets and dependency lockfiles (offline OSV), with SARIF, pre-commit, pytest and a Claude Code plugin.
5
+ Keywords: security,sast,static analysis,security scanner,vulnerability scanner,secret scanning,dependency scanning,sca,osv,cwe,sarif,pre-commit,pytest,claude code,claude-code,ai coding assistant,python,javascript,typescript,php,go,java,kotlin,c#,ruby,c,c++,rust,swift
6
+ Author: Ruthvik Bandari
7
+ Author-email: Ruthvik Bandari <bandari.ru@northeastern.edu>
8
+ License-Expression: Apache-2.0
9
+ License-File: LICENSE
10
+ License-File: NOTICE
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Framework :: Pytest
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Information Technology
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Security
24
+ Classifier: Topic :: Software Development :: Quality Assurance
25
+ Classifier: Typing :: Typed
26
+ Requires-Dist: tomli>=2 ; python_full_version < '3.11'
27
+ Requires-Python: >=3.10
28
+ Project-URL: Homepage, https://github.com/Ruthvik-Bandari/kestrix/tree/main/packages/kestrix-scan
29
+ Project-URL: Documentation, https://github.com/Ruthvik-Bandari/kestrix/blob/main/packages/kestrix-scan/README.md
30
+ Project-URL: Repository, https://github.com/Ruthvik-Bandari/kestrix
31
+ Project-URL: Issues, https://github.com/Ruthvik-Bandari/kestrix/issues
32
+ Project-URL: Changelog, https://github.com/Ruthvik-Bandari/kestrix/blob/main/packages/kestrix-scan/CHANGELOG.md
33
+ Description-Content-Type: text/markdown
34
+
35
+ # kestrix-scan
36
+
37
+ **A security scanner for developers and anyone coding with an AI assistant: it runs locally with no dependencies,
38
+ checks each file Claude Code writes as Claude writes it, and is measured on real CVE fixes
39
+ ([accuracy table](#languages-and-measured-accuracy)).**
40
+
41
+ ```bash
42
+ pip install kestrix-scan # or: uv tool install kestrix-scan / pipx install kestrix-scan
43
+ kestrix-scan src # text report; exit 1 on high or critical findings
44
+ kestrix-scan install-claude-plugin # the Claude Code plugin; enable it as in "Claude Code plugin" below
45
+ ```
46
+
47
+ It covers code in 13 languages (Python, JavaScript, TypeScript, PHP, Go, Java, Kotlin, C#, Ruby, C, C++, Rust and Swift),
48
+ web files (HTML, Vue, Svelte, CSS), SQL files, GitHub Actions, Dockerfiles, shell, Terraform and Kubernetes, hard-coded
49
+ secrets and dependencies in 9 lockfile ecosystems. It finds shell and SQL injection, XSS sinks, unsafe deserialization,
50
+ disabled TLS checks, weak hashes and randomness, leaked API keys, and lockfile dependencies with known vulnerabilities or
51
+ reported as malware, with a CWE and a concrete fix for every finding. It runs in your terminal, in CI with SARIF for
52
+ GitHub code scanning, in pre-commit and pytest, and inside Claude Code, where it has Claude fix what it finds while it
53
+ writes code.
54
+
55
+ - **No dependencies** on Python 3.11 and newer (only `tomli` on 3.10). Python 3.10 to 3.13.
56
+ - **Nothing leaves your machine.** Files are read as data: never imported, executed or uploaded. Scans open no
57
+ network connections. The only command that uses the network is `kestrix-scan db update`, which you run to
58
+ download the public OSV vulnerability data; dependency checks read that local copy.
59
+ - **Fast to start:** `kestrix-scan --version` takes about 40 to 55 ms, a few milliseconds more than Python itself.
60
+
61
+ Part of [Kestrix](https://github.com/Ruthvik-Bandari/kestrix) by Ruthvik Bandari. Apache-2.0.
62
+
63
+ ## Quick start
64
+
65
+ Before the first PyPI release, install it from GitHub:
66
+ `pip install "git+https://github.com/Ruthvik-Bandari/kestrix#subdirectory=packages/kestrix-scan"`.
67
+
68
+ ```text
69
+ $ kestrix-scan app.py
70
+ app.py
71
+ 4:5 HIGH py.subprocess.shell_true CWE-78
72
+ subprocess.run runs a built command through the shell (shell=True).
73
+ fix: Pass the command as a list of arguments without shell=True, for example subprocess.run(['git', 'log', ref], check=True). Use shlex.quote only when a shell is unavoidable.
74
+
75
+ 1 finding(s): 0 critical, 1 high, 0 medium, 0 low in 1 file(s); 0 suppressed, 0 in baseline, 0 skipped; fail-on high.
76
+ Rule-based pattern analysis on this machine. Rules miss things and can be wrong; no detection rate is claimed. No findings means no rule fired, not that the code is secure.
77
+ ```
78
+
79
+ | Option | Meaning |
80
+ | --- | --- |
81
+ | `PATH ...` | Files or directories to scan (default `.`). Directories skip `.gitignore`d, vendored and build paths. |
82
+ | `--format text\|json\|sarif` | Output format. JSON has a `schema_version`; SARIF 2.1.0 is for GitHub code scanning. |
83
+ | `--output FILE` | Write the report to a file instead of stdout. |
84
+ | `--fail-on low\|medium\|high\|critical\|none` | Lowest severity that makes the command exit 1 (default `high`, or `[tool.kestrix]` `fail-on`). |
85
+ | `--diff REF` | Only report findings on lines changed since a git ref (untracked files count as new). |
86
+ | `--baseline FILE` / `--write-baseline FILE` | Leave out known findings / record the current ones, to adopt the scanner gradually. |
87
+ | `--config FILE` / `--no-config` | Use one settings file / ignore settings files. |
88
+ | `--hook` | Claude Code hook mode: read the hook JSON on stdin; always exit 0. |
89
+
90
+ **Exit codes:** 0 nothing at or above `--fail-on`, 1 findings at or above it, 2 usage or input error.
91
+ `kestrix-scan rules` lists every rule; `kestrix-scan --help` lists the commands. `python -m kestrix_scan` works too.
92
+
93
+ Silence a confirmed false positive on its line, or the line above, with a reason (required):
94
+
95
+ ```python
96
+ subprocess.run(
97
+ deploy.command, shell=True
98
+ ) # kestrix: ignore[py.subprocess.shell_true] command from the reviewed deploy config
99
+ ```
100
+
101
+ ## Dependency scanning
102
+
103
+ ```bash
104
+ kestrix-scan db update # downloads the OSV data for the ecosystems your lockfiles use (the only network step)
105
+ kestrix-scan . # lockfiles are now checked too, offline
106
+ kestrix-scan db status # where the index is, how old, how many advisories
107
+ ```
108
+
109
+ `db update` downloads the [OSV](https://osv.dev) export of each ecosystem
110
+ (`https://storage.googleapis.com/osv-vulnerabilities/<ECOSYSTEM>/all.zip`) over HTTPS, with a 2 GiB cap,
111
+ keeps it in your cache directory (`$KESTRIX_SCAN_DB`, or `~/Library/Caches/kestrix-scan`,
112
+ `$XDG_CACHE_HOME/kestrix-scan`, `%LOCALAPPDATA%\kestrix-scan`) and builds a SQLite index from it, recording
113
+ each download's SHA-256 and time. The exports include the OpenSSF malicious-packages feed. On 2026-10-20
114
+ PyPI was 36.5 MB and npm 218.6 MB, and the index 86 MB; on 2026-10-23 Packagist was 11.0 MB, Go 12.6 MB, Maven 10.4 MB,
115
+ RubyGems 5.2 MB, crates.io 3.6 MB, NuGet 2.7 MB and Pub 0.03 MB. Without `--ecosystem`, `db update` downloads only the
116
+ ecosystems of the dependency files it finds (plus those already indexed and `db-ecosystems` from `[tool.kestrix]`;
117
+ PyPI and npm when there are none); `--ecosystem Go Packagist` names them and `--all` takes all nine. A repeat
118
+ update sends `If-None-Match` and `If-Modified-Since`: an unchanged export is a 304 and the index is not rebuilt.
119
+
120
+ Scans then read `requirements*.txt` (exact `==` pins; other lines are noted as not checked), `uv.lock`,
121
+ `poetry.lock`, `pdm.lock`, `Pipfile.lock`, `package-lock.json` (v2 and v3), `yarn.lock` (v1 and Berry),
122
+ `pnpm-lock.yaml`, `bun.lock`, `composer.lock` (PHP), `go.mod`/`go.sum`, `Cargo.lock`, `pom.xml`/`gradle.lockfile`,
123
+ `Gemfile.lock`, `packages.lock.json` (NuGet) and `pubspec.lock`, and match each version against the advisories with
124
+ the ecosystem's own ordering (PEP 440, SemVer, Composer, RubyGems, NuGet, Maven). A version that cannot be compared is
125
+ reported as "possibly affected" at low confidence, never skipped:
126
+
127
+ ```text
128
+ package-lock.json
129
+ 12:1 CRITICAL dep.vulnerable CWE-1321
130
+ minimist@1.2.0 (npm) has 2 known vulnerability(ies): GHSA-vh95-rmgr-6w4m (CVE-2020-7598), GHSA-xvch-5gv4-984h (CVE-2021-44906). Prototype Pollution in minimist; fixed in 1.2.3, 1.2.6.
131
+ fix: Upgrade minimist to 1.2.6 or later and update the lockfile.
132
+ 15:1 CRITICAL dep.malicious CWE-506
133
+ react-0b1@1.0.0 (npm) is reported as a malicious package: GHSA-8ghv-p6hq-5px9 (MAL-2023-722). Malicious code in react-0b1 (npm)
134
+ fix: Remove react-0b1 from the project and its lockfile, then rotate every credential, token and key on machines where it was installed.
135
+ ```
136
+
137
+ - `dep.vulnerable`: the advisories' highest CVSS severity, their CWE, ids and summary, and "Upgrade X to V or
138
+ later" with the lowest version that fixes all of them. `dep.malicious`: critical; remove it and rotate
139
+ credentials.
140
+ - A `dep.db_stale` note (never a failure) in text, JSON and SARIF output when the index is missing or older than
141
+ `db-max-age-days` (default 7; `KESTRIX_SCAN_MAX_AGE_DAYS` overrides). The Claude hook, `/kestrix:status` and the install
142
+ guard say so too. `dep.ecosystem_missing` notes an ecosystem the index has no data for.
143
+ - Suppress with `# kestrix: ignore[GHSA-...] reason` on a requirements line, or for any file with
144
+ `ignore-advisories = {"GHSA-..." = "reason"}` in `[tool.kestrix]`. Baselines, `--diff` and `fail-on` apply.
145
+ - Reachability is not analyzed. A language runtime (for example the PHP interpreter) is not a lockfile dependency and is
146
+ not checked; the website check's exposure finding covers server and runtime versions. Details:
147
+ [docs/modules/code.md](https://github.com/Ruthvik-Bandari/kestrix/blob/main/docs/modules/code.md#dependencies).
148
+
149
+ ## Configuration
150
+
151
+ `[tool.kestrix]` in `pyproject.toml`, or the same keys at the top level of `.kestrix.toml`:
152
+
153
+ ```toml
154
+ [tool.kestrix]
155
+ fail-on = "medium" # low, medium, high, critical or none
156
+ exclude = ["tests/fixtures/", "*.min.js"] # globs, as in .gitignore
157
+ baseline = ".kestrix-baseline.json" # relative to this file
158
+ rules.enable = ["py.", "secret."] # rule ids or prefixes; default: every rule
159
+ rules.disable = ["py.crypto.weak_hash"]
160
+ ignore-advisories = {"GHSA-xxxx-xxxx-xxxx" = "not reachable: we never parse untrusted XML"}
161
+ claude.install-guard = false # turn off the Claude Code install guard here
162
+ db-max-age-days = 7 # warn when the OSV index is older than this
163
+ db-ecosystems = ["PyPI", "npm", "Go"] # extra ecosystems for `db update`
164
+ ```
165
+
166
+ - The nearest file wins, searching upwards from the scan root and stopping at the git root. In each directory
167
+ `.kestrix.toml` is read before `pyproject.toml`; a `pyproject.toml` without `[tool.kestrix]` is skipped.
168
+ - Command-line flags override the file.
169
+ - An unknown key is a warning. An unknown rule id or prefix is an error (exit 2) with a suggestion, so a
170
+ typo never silently disables nothing.
171
+ - Excludes apply to files named on the command line too, which is how pre-commit passes them.
172
+
173
+ ## Set up a project: `kestrix-scan init`
174
+
175
+ ```bash
176
+ kestrix-scan init # append a minimal [tool.kestrix] to pyproject.toml
177
+ kestrix-scan init --pre-commit # add the pre-commit hook
178
+ kestrix-scan init --ci github # write .github/workflows/kestrix.yml
179
+ kestrix-scan init --claude-plugin # install the Claude Code plugin
180
+ ```
181
+
182
+ `init` appends to `pyproject.toml` as text and never rewrites it; it leaves an existing `[tool.kestrix]`
183
+ alone unless you pass `--force`. Without a `pyproject.toml` it writes `.kestrix.toml`. It writes
184
+ `.pre-commit-config.yaml` only when it is missing or empty, and otherwise prints the entry to add. Running
185
+ it again is safe: each step reports what is already in place.
186
+
187
+ ## pre-commit
188
+
189
+ ```yaml
190
+ repos:
191
+ - repo: https://github.com/Ruthvik-Bandari/kestrix
192
+ rev: v0.1.0
193
+ hooks:
194
+ - id: kestrix-scan
195
+ ```
196
+
197
+ The hook scans the staged Python and text files, lockfiles included, and honours `[tool.kestrix]`. Dependency results
198
+ use the local index and pre-commit never refreshes it, so run `kestrix-scan db update` daily (cron, a scheduled job or
199
+ the CI workflow below); a stale index is reported as a note.
200
+
201
+ ## GitHub code scanning
202
+
203
+ `kestrix-scan init --ci github` writes a workflow that runs on every push and pull request and daily at 05:17 UTC, so a
204
+ vulnerability published tomorrow in a locked dependency appears without a commit. It caches the OSV download directory
205
+ (`actions/cache`), so the daily refresh is a conditional request per ecosystem. Its actions are pinned to commit SHAs and
206
+ its job has only `contents: read` and `security-events: write`. The steps that matter:
207
+
208
+ ```yaml
209
+ - run: pip install kestrix-scan==0.1.0
210
+ - run: kestrix-scan db update # downloads the OSV data of your lockfiles' ecosystems; needs network access
211
+ - run: kestrix-scan --format sarif --output kestrix.sarif || true
212
+ - uses: github/codeql-action/upload-sarif@6f2ac81f5cd81fe351a197ba0b00d91d03cd2aee # v4.39.0
213
+ with:
214
+ sarif_file: kestrix.sarif
215
+ ```
216
+
217
+ Findings then appear under **Security → Code scanning**. To fail the build instead, drop `|| true`.
218
+
219
+ ## pytest
220
+
221
+ ```bash
222
+ pytest --kestrix # adds one "kestrix-scan" item that scans the rootdir
223
+ pytest --kestrix --kestrix-fail-on=medium
224
+ ```
225
+
226
+ The item fails when findings meet the threshold (default: `[tool.kestrix]` `fail-on`, else `high`), and its
227
+ failure report is the scanner's text report. Without `--kestrix` the plugin only registers its options; the
228
+ scanner is not even imported.
229
+
230
+ ## Claude Code plugin
231
+
232
+ ```bash
233
+ kestrix-scan install-claude-plugin # copies the plugin to ~/.claude/kestrix-plugin
234
+ claude plugin marketplace add ~/.claude/kestrix-plugin
235
+ claude plugin install kestrix@kestrix-local
236
+ ```
237
+
238
+ Or from the repository's marketplace: `/plugin marketplace add Ruthvik-Bandari/kestrix`, then
239
+ `/plugin install kestrix@kestrix`. Nothing in your Claude Code settings changes until you run those commands.
240
+
241
+ - **After every Write or Edit** the plugin runs `kestrix-scan --hook` on the changed file and hands Claude the
242
+ findings the edit introduced, with the rule, CWE and fix, so Claude fixes them in the same turn.
243
+ - **Skills and commands:** `secure-code-review`, a per-rule `fixing-security-findings` playbook,
244
+ `/kestrix:scan`, `/kestrix:fix` and `/kestrix:review` (a review of the current git diff).
245
+ - **Install guard:** before a `pip`, `uv`, `npm`, `pnpm`, `yarn`, `bun`, `composer require`, `go get`, `cargo add`, `gem install` or `dotnet add package` install runs, the plugin checks the packages
246
+ against the local OSV index. A known malicious package is denied; a known-vulnerable pinned version gets a
247
+ warning naming the fixed version. No index means no check; an old index adds a line saying the result may be stale. Turn it off with `KESTRIX_INSTALL_GUARD=0` or
248
+ `claude.install-guard = false`.
249
+ - **Opt-in Stop gate:** with `KESTRIX_BLOCK_ON_STOP=1`, Claude cannot finish while new high or critical
250
+ findings remain in files it changed (at most three times per session).
251
+ - **Fails open:** a missing scanner, a timeout or an error never blocks an edit. Findings never contain secret
252
+ values, only their kind and first four characters.
253
+
254
+ `kestrix-scan install-claude-skill` installs only the `kestrix-security` skill;
255
+ `package-claude-plugin` and `package-claude-skill` write zips. Full details:
256
+ [docs/claude-plugin.md](https://github.com/Ruthvik-Bandari/kestrix/blob/main/docs/claude-plugin.md).
257
+
258
+ ## Python API
259
+
260
+ ```python
261
+ import kestrix_scan
262
+
263
+ config = kestrix_scan.load_config("src") # [tool.kestrix] or .kestrix.toml, if any
264
+ report = kestrix_scan.scan(["src"], config=config, fail_on="high")
265
+ for finding in report.findings: # kestrix_scan.Finding: frozen dataclass
266
+ print(finding.path, finding.line, finding.rule_id, finding.cwe, finding.fix)
267
+ print(report.to_json()) # the same JSON as --format json
268
+ raise SystemExit(kestrix_scan.exit_code(report))
269
+
270
+ for rule in kestrix_scan.rules(): # the registry, in its stable order
271
+ print(rule.id, rule.severity, rule.cwe, rule.title)
272
+ ```
273
+
274
+ `scan` raises `kestrix_scan.Rejected` for a missing path, a bad baseline, an unknown git ref or bad
275
+ settings. The package is typed (`py.typed`).
276
+
277
+ ## Privacy
278
+
279
+ `kestrix-scan` reads files as bytes, decodes them as text, parses Python with the standard-library `ast` and
280
+ splits every other language with its own bounded, standard-library tokenizer.
281
+ It never imports or runs the code it scans, never follows symbolic links out of the scan root, and caps
282
+ file size and count. Scans, the plugin hooks and the install guard make no network requests; the test suite
283
+ proves they work with every socket call refused. The one exception is `kestrix-scan db update`, which you run
284
+ explicitly: it downloads the public OSV exports over HTTPS and sends nothing about your project. `--diff` and directory walks run the local `git` binary.
285
+
286
+ ## Languages and measured accuracy
287
+
288
+ **What the numbers mean.** Each language was measured on real security fixes from [CVEfixes](https://github.com/secureIT-project/CVEfixes) and the GitHub Advisory Database: does a rule fire on the vulnerable version of a file a fix changed? Rules were tuned on one half of the projects, then run **once** on the other half, which they had never seen, next to an established open-source tool on the same files. *Caught* is the share of in-scope vulnerable files flagged, with a 95% confidence interval; *false alarms* are alerts per 1,000 lines of the fixed (safe) code. Every tool catches a small share on this benchmark: many CVEs are logic or authorization flaws no pattern rule sees, and a fix commit often changes files that never held the bug. Method, per-rule numbers and limits: [CVE-fix benchmark](https://github.com/Ruthvik-Bandari/kestrix/blob/main/docs/benchmarks/cvefixes.md).
289
+
290
+ | Language or files | Rules | Caught (held-out) | Compared on the same files | False alarms per 1,000 lines |
291
+ | --- | --- | --- | --- | --- |
292
+ | Python | 30 `py.*` | 7.7% [4.2, 12.0] | Bandit 1.9.4: 10.2% at 0.99 false alarms | **0.23** |
293
+ | JavaScript, TypeScript (JSX, TSX) | 16 `js.*` | 10.3% [7.2, 13.9] | eslint-plugin-security: 12.4% at 16.9 false alarms | **0.43** |
294
+ | PHP and Blade | 9 `php.*` | **5.4% [2.8, 10.2]** | Psalm 6.20 taint: 3.3% at 0.66 | 0.80 |
295
+ | Java and Kotlin | 7 `java.*` | **10.9% [5.9, 18.4]** | Opengrep: 5.8% at 0.34 | **0.20** |
296
+ | Ruby and ERB | 6 `rb.*` | 4.7% [1.0, 10.0] (ERB views: 13 of 16) | Opengrep: 11.2% at 1.91 | 1.55 |
297
+ | Go | 4 `go.*` | 1.1% [0.0, 6.7] | gosec 2.30: 6.7% at 0.78 | **0.13** |
298
+ | C# | 4 `cs.*` | 2.4% [0.0, 16.7] (41 files) | Opengrep: 0.0% at 0.05 | 0.15 |
299
+ | C and C++ | 7 `c.*` | 3.4% [0.7, 6.7] | flawfinder 2.0.19: 19.4% at 6.13; Opengrep: 4.6% at 0.62 | **0.34** |
300
+ | Rust | 3 `rust.*` | not measurable: 14 fixes, no tool caught any | Opengrep: 0.0% at 2.33 | 0.05 |
301
+ | Swift | 3 `swift.*` | not measurable: 1 fix | | 0 to 0.11 on 3 clean projects |
302
+ | HTML, Vue, Svelte, CSS, `next.config` | 12 `html.*` `vue.*` `svelte.*` `web.*` `css.*` `next.*` | tuning data only: 27.4% [7.4, 50.9] of 73 files; held-out run waits for new advisories | no licensed tool | 0.47 on clean web files |
303
+ | SQL files | 3 `sql.*` | no `.sql` files in the fix data | | |
304
+ | GitHub Actions, Dockerfile, shell, Terraform (AWS), Kubernetes | 24 `gha.*` `docker.*` `sh.*` `tf.*` `k8s.*` | no CVE-fix data for these formats; agrees with zizmor, hadolint and checkov on 94% to 100% of the files where the checks mean the same | | on 16,157 real files: 4.5 for unpinned actions, 0.03 for workflow script injection |
305
+ | Claude Code and MCP settings | 5 `config.*` | not benchmarked | | |
306
+ | Secrets in any text file | 11 `secret.*` | not on this benchmark; shapes are high-precision on purpose | | |
307
+ | Dependencies (9 lockfile ecosystems) | 2 `dep.*` | exact version match against OSV advisories, not a heuristic | | |
308
+
309
+ Bold marks where Kestrix is ahead of the compared tool. Python and JavaScript/TypeScript are from the second held-out run (`test2`); the Python rules added later were measured on tuning data only. Some rules ship with little or no evidence; the [Limits](https://github.com/Ruthvik-Bandari/kestrix/blob/main/docs/modules/code.md#limits) list names them.
310
+
311
+ ## Rules
312
+
313
+ There are 146 rules. They cover Python (30 `py.*` rules: `eval`/`exec`, `shell=True` and `os.system`, pickle and
314
+ unsafe YAML, tar extraction without a filter, SQL built from strings, disabled TLS checks, MD5/SHA-1, `random` for secrets, `tempfile.mktemp`,
315
+ Flask debug, unverified JWTs, stdlib XML parsers, Jinja2 environments without autoescape, `assert` for access checks, and, through intraprocedural taint
316
+ analysis from Flask (including route parameters), Django, FastAPI, Starlette, aiohttp, Tornado and LLM-client sources, path traversal, SSRF, open redirects, XSS/SSTI and
317
+ LLM output reaching code, a shell, SQL or a path; plus unsafe model loading), JavaScript and TypeScript (16 `js.*`
318
+ rules for `.js`, `.mjs`, `.cjs`, `.jsx`, `.ts`, `.tsx`, `.mts` and `.cts`: `eval` and `new Function`,
319
+ `child_process` shells, DOM and React HTML sinks, SQL built from strings, `rejectUnauthorized: false`, MD5/SHA-1,
320
+ `Math.random()` for secrets, JWT `none` and `ignoreExpiration`, Express, Koa and hapi request data (including the request URL) reaching files, URLs and
321
+ redirects, prototype pollution, wildcard CORS with credentials, Angular `bypassSecurityTrust*`, and LLM output reaching `eval`, a shell or HTML; request
322
+ sources also include Next.js route handlers, `params` and server-action `FormData`, Fastify, Koa and NestJS decorators),
323
+ web files (12 rules in `vue.*`, `svelte.*`, `web.*`, `html.*`, `css.*` and `next.*` for `.vue`, `.svelte`, `.html`, `.htm`,
324
+ `.css`, `.scss` and `next.config.*`: `v-html` and `{@html}` with a non-literal value, `javascript:` links, inline event
325
+ handlers, `target="_blank"` without `noopener`, forms and subresources over `http:`, Angular `[innerHTML]`, remote CSS over
326
+ `http:` and `expression()`, and a `**` image host in `next.config`; mostly low severity, with `<script>` blocks run through the
327
+ `js.*` rules), PHP and Blade (9 `php.*` rules for `.php`, `.phtml` and `.blade.php`: request values from `$_GET`, `$_POST`, `$_REQUEST`,
328
+ `$_COOKIE`, `php://input` and Laravel/Symfony request objects reaching commands, `include`, SQL, `echo`, URLs and file paths inside one
329
+ function, `extract($_REQUEST)`, `md5`/`sha1` of passwords and Blade `{!! !!}`), SQL files
330
+ (3 `sql.*` rules for `.sql`: `GRANT ALL`, plaintext account passwords and PostgreSQL `SECURITY DEFINER` functions without a fixed `search_path`), Go (4 `go.*` rules for `.go`:
331
+ request data from `net/http`, gin, echo, fiber or chi reaching `exec.Command`, SQL or `template.HTML`, and `InsecureSkipVerify: true`), Java and Kotlin
332
+ (7 `java.*` rules for `.java`, `.kt` and `.kts`: servlet, Spring, JAX-RS, Stapler and Ktor request data reaching JDBC and JPA SQL, `Runtime.exec` and
333
+ `ProcessBuilder`, file paths, outbound URLs and the response writer, plus `ObjectInputStream`, XStream, Jackson default typing and SnakeYAML
334
+ deserialization and XML parser factories without DOCTYPE protection), C# (4 `cs.*` rules for `.cs`: ASP.NET request data reaching `SqlCommand`, Entity
335
+ Framework and Dapper SQL, `Process.Start` and file paths, and `BinaryFormatter` and Json.NET `TypeNameHandling`), Ruby on Rails (6 `rb.*` rules for `.rb`
336
+ and `.erb`: `params` reaching `where`/`find_by_sql`/`order`, `html_safe`/`raw`/`<%== %>`, `constantize`, `send`, `system` and backticks, and file
337
+ paths), C and C++ (7 `c.*` rules for `.c`, `.h`, `.cc`, `.cpp`, `.cxx`, `.hpp`, `.hh` and `.hxx`: `gets`, `strcpy`/`strcat`/`sprintf` into arrays
338
+ declared with a size, `system`/`popen` with a built command, `printf`-family formats that are not literals, `scanf` `%s` without a width, `rand()`
339
+ next to security values and `tmpnam`/`mktemp`), Rust (3 `rust.*` rules: `Command` running a shell with a built script, TLS verification turned
340
+ off, unchecked memory operations in `unsafe` blocks on input-derived values), Swift (3 `swift.*` rules: trust-all `URLSession` challenge handlers
341
+ and Alamofire's disabled evaluator, `NSAllowsArbitraryLoads` in `.plist` files, secrets in `UserDefaults`); these systems-language rules flag only
342
+ lexically obvious patterns and cannot judge memory safety, CI and infrastructure files (24 rules in `gha.*`, `docker.*`, `sh.*`, `tf.*` and `k8s.*` for GitHub Actions
343
+ workflows, Dockerfiles, `.sh` and `.bash` scripts, Terraform and Kubernetes manifests: `pull_request_target` checking out the PR head,
344
+ `${{ github.event.* }}` in `run:`, unpinned third-party actions, `permissions: write-all`, running as root, `ADD` of a URL,
345
+ `curl | sh`, `latest` images, secrets in `ENV`/`ARG`, `eval` and `rm -rf` of variables, `chmod 777`, public S3 buckets, admin
346
+ ports open to the internet, unencrypted storage, and privileged or host-mounted pods; read with a bounded YAML subset reader,
347
+ nothing is run), Claude Code and MCP configuration
348
+ (5 `config.*` rules: hooks that run downloaded scripts, permission bypasses, unpinned `npx -y`/`uvx` servers and
349
+ literal credentials), secrets in any text file (11 `secret.*` rules: AWS, GitHub, Slack, Stripe, Google, Anthropic
350
+ and OpenAI-style keys, private keys, JWTs and high-entropy credentials), and dependencies in lockfiles (2 `dep.*`
351
+ rules: `dep.vulnerable`, `dep.malicious`). The full table with CWEs and severities is in
352
+ [docs/modules/code.md](https://github.com/Ruthvik-Bandari/kestrix/blob/main/docs/modules/code.md#rules), and
353
+ each rule's sources are in
354
+ [docs/modules/code-rules-provenance.md](https://github.com/Ruthvik-Bandari/kestrix/blob/main/docs/modules/code-rules-provenance.md).
355
+
356
+ **JavaScript and TypeScript: precision first, no full parser.** The scanner stays dependency-free, so it does not
357
+ ship a JavaScript parser. A bounded tokenizer (strings, nested templates, comments, regex versus division, JSX and
358
+ TypeScript annotations) feeds a structural matcher that knows calls, member chains, assignments, object keys, JSX
359
+ attributes, function scopes and `import`/`require` aliases, plus a light same-function taint for Express request
360
+ data, the URL and LLM output. Every rule matches a precise shape and stays quiet when the code is ambiguous, so it
361
+ misses more than a parser-based tool would, by design. Minified files (a `.min.` name or an average line over 500
362
+ characters) are skipped as `minified`. Vue, Svelte and HTML files are read with a bounded tag scanner (no HTML parser): the
363
+ template rules look at directives and attributes, `<script>` bodies go through the JavaScript rules with the file's line
364
+ numbers, and a missing Content-Security-Policy is deliberately not reported.
365
+
366
+ Rules are pattern analysis: they miss things and can be wrong in context, and no findings means no rule fired, not
367
+ that the code is secure. The measured rates are in [Languages and measured accuracy](#languages-and-measured-accuracy). A
368
+ [benchmark scorecard](https://github.com/Ruthvik-Bandari/kestrix/blob/main/docs/benchmarks/benchmarkpython.md)
369
+ measures category coverage on synthetic code (OWASP BenchmarkPython v0.1 and the project's own labelled cases)
370
+ against Bandit and the security-guidance regex layer, including the categories where Kestrix loses. Rule ids are stable; renaming one is a breaking
371
+ change recorded in the [CHANGELOG](CHANGELOG.md).