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.
- kestrix_scan-0.1.0/LICENSE +202 -0
- kestrix_scan-0.1.0/NOTICE +34 -0
- kestrix_scan-0.1.0/PKG-INFO +371 -0
- kestrix_scan-0.1.0/README.md +337 -0
- kestrix_scan-0.1.0/pyproject.toml +87 -0
- kestrix_scan-0.1.0/pyproject.toml.orig +60 -0
- kestrix_scan-0.1.0/src/kestrix_scan/__init__.py +86 -0
- kestrix_scan-0.1.0/src/kestrix_scan/__main__.py +9 -0
- kestrix_scan-0.1.0/src/kestrix_scan/about.py +8 -0
- kestrix_scan-0.1.0/src/kestrix_scan/agent_config.py +288 -0
- kestrix_scan-0.1.0/src/kestrix_scan/analyze.py +424 -0
- kestrix_scan-0.1.0/src/kestrix_scan/c_tokens.py +486 -0
- kestrix_scan-0.1.0/src/kestrix_scan/ci_rules.py +310 -0
- kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/.claude-plugin/plugin.json +17 -0
- kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/hooks/hooks.json +83 -0
- kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/hooks/kestrix_hook.py +981 -0
- kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/fix/SKILL.md +30 -0
- kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/fixing-security-findings/SKILL.md +3921 -0
- kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/kestrix-security/SKILL.md +244 -0
- kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/kestrix-security/reference/bitcoin.md +52 -0
- kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/kestrix-security/reference/detect.md +99 -0
- kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/kestrix-security/reference/findings-forensics.md +62 -0
- kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/kestrix-security/reference/findings-mail.md +118 -0
- kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/kestrix-security/reference/findings-webcheck.md +97 -0
- kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/kestrix-security/reference/json-fields.md +94 -0
- kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/review/SKILL.md +31 -0
- kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/scan/SKILL.md +32 -0
- kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/secure-code-review/SKILL.md +132 -0
- kestrix_scan-0.1.0/src/kestrix_scan/claude_plugin/kestrix/skills/status/SKILL.md +26 -0
- kestrix_scan-0.1.0/src/kestrix_scan/cli.py +491 -0
- kestrix_scan-0.1.0/src/kestrix_scan/config.py +267 -0
- kestrix_scan-0.1.0/src/kestrix_scan/deps.py +333 -0
- kestrix_scan-0.1.0/src/kestrix_scan/docker_rules.py +291 -0
- kestrix_scan-0.1.0/src/kestrix_scan/ecoversions.py +272 -0
- kestrix_scan-0.1.0/src/kestrix_scan/errors.py +24 -0
- kestrix_scan-0.1.0/src/kestrix_scan/hook.py +296 -0
- kestrix_scan-0.1.0/src/kestrix_scan/html_tokens.py +236 -0
- kestrix_scan-0.1.0/src/kestrix_scan/iac.py +55 -0
- kestrix_scan-0.1.0/src/kestrix_scan/infra_rules.py +490 -0
- kestrix_scan-0.1.0/src/kestrix_scan/init.py +237 -0
- kestrix_scan-0.1.0/src/kestrix_scan/install_guard.py +481 -0
- kestrix_scan-0.1.0/src/kestrix_scan/js_index.py +1498 -0
- kestrix_scan-0.1.0/src/kestrix_scan/js_rules.py +945 -0
- kestrix_scan-0.1.0/src/kestrix_scan/js_tokens.py +311 -0
- kestrix_scan-0.1.0/src/kestrix_scan/lockfiles.py +363 -0
- kestrix_scan-0.1.0/src/kestrix_scan/lockfiles_more.py +325 -0
- kestrix_scan-0.1.0/src/kestrix_scan/models.py +196 -0
- kestrix_scan-0.1.0/src/kestrix_scan/osvdb.py +584 -0
- kestrix_scan-0.1.0/src/kestrix_scan/php_index.py +787 -0
- kestrix_scan-0.1.0/src/kestrix_scan/php_rules.py +599 -0
- kestrix_scan-0.1.0/src/kestrix_scan/php_tokens.py +202 -0
- kestrix_scan-0.1.0/src/kestrix_scan/plugin.py +100 -0
- kestrix_scan-0.1.0/src/kestrix_scan/popular.py +283 -0
- kestrix_scan-0.1.0/src/kestrix_scan/popular_names.json +1 -0
- kestrix_scan-0.1.0/src/kestrix_scan/py.typed +0 -0
- kestrix_scan-0.1.0/src/kestrix_scan/pytest_plugin.py +66 -0
- kestrix_scan-0.1.0/src/kestrix_scan/python_rules.py +1595 -0
- kestrix_scan-0.1.0/src/kestrix_scan/registry.py +2195 -0
- kestrix_scan-0.1.0/src/kestrix_scan/ruby_tokens.py +310 -0
- kestrix_scan-0.1.0/src/kestrix_scan/sarif.py +143 -0
- kestrix_scan-0.1.0/src/kestrix_scan/secrets.py +217 -0
- kestrix_scan-0.1.0/src/kestrix_scan/server_index.py +1022 -0
- kestrix_scan-0.1.0/src/kestrix_scan/server_rules.py +885 -0
- kestrix_scan-0.1.0/src/kestrix_scan/shell_rules.py +299 -0
- kestrix_scan-0.1.0/src/kestrix_scan/skill.py +174 -0
- kestrix_scan-0.1.0/src/kestrix_scan/sql_rules.py +207 -0
- kestrix_scan-0.1.0/src/kestrix_scan/systems_rules.py +809 -0
- kestrix_scan-0.1.0/src/kestrix_scan/taint.py +1055 -0
- kestrix_scan-0.1.0/src/kestrix_scan/versions.py +218 -0
- kestrix_scan-0.1.0/src/kestrix_scan/walk.py +315 -0
- kestrix_scan-0.1.0/src/kestrix_scan/web_rules.py +352 -0
- 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).
|