kuzushi 0.2.0 → 0.9.2
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.
- package/README.md +2 -0
- package/dist/agent-runtime/claude.js +15 -3
- package/dist/agent-runtime/claude.js.map +1 -1
- package/dist/agents/tasks/code-config-detect.js +3 -0
- package/dist/agents/tasks/code-config-detect.js.map +1 -1
- package/dist/agents/tasks/command-injection.js +10 -8
- package/dist/agents/tasks/command-injection.js.map +1 -1
- package/dist/agents/tasks/context-enricher.js +2 -0
- package/dist/agents/tasks/context-enricher.js.map +1 -1
- package/dist/agents/tasks/deserialization-detection.js +4 -1
- package/dist/agents/tasks/deserialization-detection.js.map +1 -1
- package/dist/agents/tasks/graphql-security.js +4 -1
- package/dist/agents/tasks/graphql-security.js.map +1 -1
- package/dist/agents/tasks/nosql-injection.js +6 -3
- package/dist/agents/tasks/nosql-injection.js.map +1 -1
- package/dist/agents/tasks/prototype-pollution.js +4 -1
- package/dist/agents/tasks/prototype-pollution.js.map +1 -1
- package/dist/agents/tasks/race-condition.js +4 -1
- package/dist/agents/tasks/race-condition.js.map +1 -1
- package/dist/agents/tasks/secrets-crypto-detect.js +3 -0
- package/dist/agents/tasks/secrets-crypto-detect.js.map +1 -1
- package/dist/agents/tasks/sharp-edges-detect.js +5 -0
- package/dist/agents/tasks/sharp-edges-detect.js.map +1 -1
- package/dist/agents/tasks/ssrf-detection.js +6 -1
- package/dist/agents/tasks/ssrf-detection.js.map +1 -1
- package/dist/agents/tasks/supply-chain.js +4 -1
- package/dist/agents/tasks/supply-chain.js.map +1 -1
- package/dist/agents/tasks/template-injection.js +6 -3
- package/dist/agents/tasks/template-injection.js.map +1 -1
- package/dist/agents/tasks/threat-modeling/randori-adapter.js +19 -2
- package/dist/agents/tasks/threat-modeling/randori-adapter.js.map +1 -1
- package/dist/agents/tasks/threat-modeling/randori-artifacts.js +69 -13
- package/dist/agents/tasks/threat-modeling/randori-artifacts.js.map +1 -1
- package/dist/agents/tasks/threat-modeling/randori.js +70 -30
- package/dist/agents/tasks/threat-modeling/randori.js.map +1 -1
- package/dist/agents/tasks/xxe-detection.js +4 -1
- package/dist/agents/tasks/xxe-detection.js.map +1 -1
- package/dist/cli/commands/scan.js +35 -5
- package/dist/cli/commands/scan.js.map +1 -1
- package/dist/cli.js +2 -1
- package/dist/cli.js.map +1 -1
- package/dist/migrations/024_rename_scanner_to_task_id.d.ts +13 -0
- package/dist/migrations/024_rename_scanner_to_task_id.js +25 -0
- package/dist/migrations/024_rename_scanner_to_task_id.js.map +1 -0
- package/dist/migrations/index.js +2 -0
- package/dist/migrations/index.js.map +1 -1
- package/dist/migrations/runner.js +7 -0
- package/dist/migrations/runner.js.map +1 -1
- package/dist/prompts/language-tuning.d.ts +38 -0
- package/dist/prompts/language-tuning.js +225 -0
- package/dist/prompts/language-tuning.js.map +1 -0
- package/dist/prompts/languages/c-cpp.d.ts +2 -0
- package/dist/prompts/languages/c-cpp.js +276 -0
- package/dist/prompts/languages/c-cpp.js.map +1 -0
- package/dist/prompts/languages/go.d.ts +2 -0
- package/dist/prompts/languages/go.js +252 -0
- package/dist/prompts/languages/go.js.map +1 -0
- package/dist/prompts/languages/index.d.ts +6 -0
- package/dist/prompts/languages/index.js +44 -0
- package/dist/prompts/languages/index.js.map +1 -0
- package/dist/prompts/languages/java-kotlin.d.ts +2 -0
- package/dist/prompts/languages/java-kotlin.js +495 -0
- package/dist/prompts/languages/java-kotlin.js.map +1 -0
- package/dist/prompts/languages/javascript-typescript.d.ts +2 -0
- package/dist/prompts/languages/javascript-typescript.js +421 -0
- package/dist/prompts/languages/javascript-typescript.js.map +1 -0
- package/dist/prompts/languages/php.d.ts +2 -0
- package/dist/prompts/languages/php.js +277 -0
- package/dist/prompts/languages/php.js.map +1 -0
- package/dist/prompts/languages/python.d.ts +2 -0
- package/dist/prompts/languages/python.js +283 -0
- package/dist/prompts/languages/python.js.map +1 -0
- package/dist/prompts/languages/ruby.d.ts +2 -0
- package/dist/prompts/languages/ruby.js +219 -0
- package/dist/prompts/languages/ruby.js.map +1 -0
- package/dist/prompts/languages/rust.d.ts +2 -0
- package/dist/prompts/languages/rust.js +149 -0
- package/dist/prompts/languages/rust.js.map +1 -0
- package/dist/prompts/languages/types.d.ts +79 -0
- package/dist/prompts/languages/types.js +9 -0
- package/dist/prompts/languages/types.js.map +1 -0
- package/dist/scanners/run-agentic.d.ts +2 -2
- package/dist/scanners/run-agentic.js +11 -3
- package/dist/scanners/run-agentic.js.map +1 -1
- package/dist/store.js +4 -0
- package/dist/store.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
// NOTE: This file contains DETECTION PATTERNS for a security scanner.
|
|
2
|
+
// The API references are DETECTION TARGETS describing what the scanner
|
|
3
|
+
// looks for in scanned codebases, not code this file runs.
|
|
4
|
+
export const rubyProfile = {
|
|
5
|
+
languageId: "Ruby",
|
|
6
|
+
aliases: ["ruby", "rb"],
|
|
7
|
+
generalHints: {
|
|
8
|
+
grepPatterns: [
|
|
9
|
+
"class\\s+\\w+Controller",
|
|
10
|
+
"def\\s+\\w+.*params",
|
|
11
|
+
"before_action",
|
|
12
|
+
"protect_from_forgery",
|
|
13
|
+
"permit\\(",
|
|
14
|
+
"render\\s+",
|
|
15
|
+
],
|
|
16
|
+
fileHints: [
|
|
17
|
+
"Gemfile / Gemfile.lock for dependencies",
|
|
18
|
+
"config/routes.rb for route definitions",
|
|
19
|
+
"config/initializers/ for security configuration",
|
|
20
|
+
"app/controllers/ for request handlers",
|
|
21
|
+
"app/models/ for ActiveRecord models",
|
|
22
|
+
"config/environments/production.rb for production settings",
|
|
23
|
+
],
|
|
24
|
+
instructions: [
|
|
25
|
+
"Check Gemfile for outdated gems with known CVEs (bundle audit)",
|
|
26
|
+
"Look at config/initializers for security settings (CSRF, session, cookies)",
|
|
27
|
+
"Check strong parameters — are permit calls allowing too many fields?",
|
|
28
|
+
"Review before_action chains — are auth filters applied to all sensitive actions?",
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
generalAntiHallucination: [
|
|
32
|
+
"Rails ActiveRecord with parameterized queries (where(field: val)) is SAFE against SQL injection",
|
|
33
|
+
"Rails ERB auto-escapes with <%= %> — only flag raw() or html_safe usage",
|
|
34
|
+
"Rails CSRF protection is ON by default — only flag if protect_from_forgery is explicitly skipped",
|
|
35
|
+
],
|
|
36
|
+
vulnClasses: {
|
|
37
|
+
deserialization: {
|
|
38
|
+
sinks: [
|
|
39
|
+
{ api: "Marshal.load(data)", risk: "Deserializes arbitrary Ruby objects — can trigger method_missing or other gadgets for RCE", cwes: ["CWE-502"] },
|
|
40
|
+
{ api: "YAML.load(data)", risk: "YAML allows Ruby object instantiation via !ruby/object tags", cwes: ["CWE-502"] },
|
|
41
|
+
{ api: "YAML.unsafe_load(data)", risk: "Explicitly unsafe YAML parsing", cwes: ["CWE-502"] },
|
|
42
|
+
],
|
|
43
|
+
safePatterns: [
|
|
44
|
+
{ api: "JSON.parse(data)", why: "JSON parsing does not instantiate objects" },
|
|
45
|
+
{ api: "YAML.safe_load(data)", why: "Restricts allowed YAML tags — blocks object instantiation" },
|
|
46
|
+
{ api: "Psych.safe_load(data, permitted_classes: [...])", why: "Allowlisted classes only" },
|
|
47
|
+
],
|
|
48
|
+
investigationHints: {
|
|
49
|
+
grepPatterns: [
|
|
50
|
+
"Marshal\\.load",
|
|
51
|
+
"Marshal\\.restore",
|
|
52
|
+
"YAML\\.load\\b",
|
|
53
|
+
"YAML\\.unsafe_load",
|
|
54
|
+
"YAML\\.safe_load",
|
|
55
|
+
],
|
|
56
|
+
fileHints: [
|
|
57
|
+
"Session storage configuration",
|
|
58
|
+
"Cache serialization code",
|
|
59
|
+
"Job/worker serialization (Sidekiq, Resque)",
|
|
60
|
+
"Cookie handling",
|
|
61
|
+
],
|
|
62
|
+
instructions: [
|
|
63
|
+
"Check if Marshal.load/YAML.load processes data from cookies, HTTP requests, or message queues",
|
|
64
|
+
"Look at Rails session store — CookieStore uses Marshal by default in older Rails versions",
|
|
65
|
+
"Check Sidekiq/Resque job arguments — are they deserialized from untrusted sources?",
|
|
66
|
+
"In Rails 7+, default session serializer is JSON — check for overrides",
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
fewShots: [
|
|
70
|
+
{
|
|
71
|
+
scenario: "Cookie-based Marshal deserialization",
|
|
72
|
+
vulnerableCode: 'def load_preferences\n data = Base64.decode64(cookies[:prefs])\n @prefs = Marshal.load(data)\nend',
|
|
73
|
+
explanation: "User controls cookie value. Marshal.load instantiates arbitrary Ruby objects. Known gadget chains (ERB::Util, Gem::Requirement) enable RCE.",
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
frameworkGuidance: [
|
|
77
|
+
{
|
|
78
|
+
framework: "Rails",
|
|
79
|
+
defaults: ["Rails 7+ uses JSON for session serialization by default"],
|
|
80
|
+
pitfalls: ["Older Rails versions use Marshal for sessions", "Custom session stores may still use Marshal"],
|
|
81
|
+
configChecks: ["Check config.action_dispatch.cookies_serializer setting"],
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
antiHallucinationExtra: [
|
|
85
|
+
"JSON.parse() is SAFE — does not instantiate objects",
|
|
86
|
+
"YAML.safe_load() is SAFE — only flag YAML.load() or YAML.unsafe_load()",
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
"template-injection": {
|
|
90
|
+
sinks: [
|
|
91
|
+
{ api: "ERB.new(user_str).result", risk: "User-controlled ERB template enables Ruby code via <%= %> tags", cwes: ["CWE-1336"] },
|
|
92
|
+
{ api: "Haml::Engine.new(user_str).render", risk: "Haml template with user-controlled source", cwes: ["CWE-1336"] },
|
|
93
|
+
{ api: "Slim::Template.new { user_str }.render", risk: "Slim template with user source", cwes: ["CWE-1336"] },
|
|
94
|
+
{ api: "send(user_method)", risk: "Calls arbitrary method on object", cwes: ["CWE-470"] },
|
|
95
|
+
],
|
|
96
|
+
safePatterns: [
|
|
97
|
+
{ api: "render template: 'file', locals: { var: user_data }", why: "Template file is fixed, user data is a variable" },
|
|
98
|
+
{ api: "ERB.new(constant_string).result_with_hash(user: data)", why: "Template is constant" },
|
|
99
|
+
],
|
|
100
|
+
investigationHints: {
|
|
101
|
+
grepPatterns: [
|
|
102
|
+
"ERB\\.new\\(",
|
|
103
|
+
"Haml::Engine",
|
|
104
|
+
"\\beval\\(",
|
|
105
|
+
"\\.send\\(",
|
|
106
|
+
"public_send\\(",
|
|
107
|
+
"render\\s+inline:",
|
|
108
|
+
],
|
|
109
|
+
fileHints: [
|
|
110
|
+
"Custom template rendering code",
|
|
111
|
+
"Email/notification templates",
|
|
112
|
+
"Report generation",
|
|
113
|
+
],
|
|
114
|
+
instructions: [
|
|
115
|
+
"Check if the template source (not data) comes from user input",
|
|
116
|
+
"Look for render inline: in Rails controllers — this compiles user string as ERB",
|
|
117
|
+
"Check for send/public_send with user-controlled method names",
|
|
118
|
+
],
|
|
119
|
+
},
|
|
120
|
+
fewShots: [
|
|
121
|
+
{
|
|
122
|
+
scenario: "Rails render inline with user input",
|
|
123
|
+
vulnerableCode: 'def preview\n template = params[:template]\n render inline: template\nend',
|
|
124
|
+
explanation: "render inline: compiles the string as ERB. Attacker sends template with embedded Ruby code tags for RCE.",
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
antiHallucinationExtra: [
|
|
128
|
+
"render template: 'file.html.erb' with user data as local variables is SAFE",
|
|
129
|
+
"Rails ERB auto-escapes with <%= %> for XSS — but if user controls the TEMPLATE itself, it is SSTI",
|
|
130
|
+
],
|
|
131
|
+
},
|
|
132
|
+
"mass-assignment": {
|
|
133
|
+
sinks: [
|
|
134
|
+
{ api: "Model.new(params) without strong params", risk: "Attacker can set any model attribute including admin, role, password", cwes: ["CWE-915"] },
|
|
135
|
+
{ api: "Model.update(params) without permit", risk: "Unfiltered params update any column", cwes: ["CWE-915"] },
|
|
136
|
+
{ api: "Overly broad permit (permit!)", risk: "permit! allows ALL parameters — defeats strong params", cwes: ["CWE-915"] },
|
|
137
|
+
],
|
|
138
|
+
safePatterns: [
|
|
139
|
+
{ api: "params.require(:model).permit(:field1, :field2)", why: "Strong parameters — explicit allowlist" },
|
|
140
|
+
{ api: "attr_accessible in older Rails (< 4)", why: "Model-level attribute allowlist" },
|
|
141
|
+
],
|
|
142
|
+
investigationHints: {
|
|
143
|
+
grepPatterns: [
|
|
144
|
+
"\\.permit\\(",
|
|
145
|
+
"\\.permit!",
|
|
146
|
+
"params\\[",
|
|
147
|
+
"attr_accessible",
|
|
148
|
+
"attr_protected",
|
|
149
|
+
],
|
|
150
|
+
fileHints: [
|
|
151
|
+
"Controller actions (create, update)",
|
|
152
|
+
"Private parameter filtering methods",
|
|
153
|
+
"API controllers",
|
|
154
|
+
],
|
|
155
|
+
instructions: [
|
|
156
|
+
"Check every create/update action — are params filtered through permit?",
|
|
157
|
+
"Look for permit! (bang version) — this allows ALL parameters",
|
|
158
|
+
"Check if sensitive fields (admin, role, email_verified) are excluded from permit lists",
|
|
159
|
+
"In API controllers, check if params are used directly without strong params",
|
|
160
|
+
],
|
|
161
|
+
},
|
|
162
|
+
fewShots: [
|
|
163
|
+
{
|
|
164
|
+
scenario: "Admin privilege escalation via mass assignment",
|
|
165
|
+
vulnerableCode: 'def update\n @user = User.find(params[:id])\n @user.update(params[:user].permit!)\nend',
|
|
166
|
+
explanation: "permit! allows all parameters. Attacker sends user[admin]=true to escalate privileges.",
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
antiHallucinationExtra: [
|
|
170
|
+
"params.require(:model).permit(:specific_fields) is SAFE — properly filtered",
|
|
171
|
+
"Strong parameters in Rails 4+ are the standard protection — do NOT flag properly filtered params",
|
|
172
|
+
],
|
|
173
|
+
},
|
|
174
|
+
"command-injection": {
|
|
175
|
+
sinks: [
|
|
176
|
+
{ api: "system(cmd) single-arg", risk: "Shell interpretation of command string", shellInvoking: true, cwes: ["CWE-78"] },
|
|
177
|
+
{ api: "backtick operator `cmd`", risk: "Shell interpretation", shellInvoking: true, cwes: ["CWE-78"] },
|
|
178
|
+
{ api: "%x{cmd}", risk: "Shell interpretation (alternative syntax)", shellInvoking: true, cwes: ["CWE-78"] },
|
|
179
|
+
{ api: "IO.popen(cmd)", risk: "Shell interpretation", shellInvoking: true, cwes: ["CWE-78"] },
|
|
180
|
+
{ api: "Open3.capture3(cmd) single string", risk: "Shell interpretation for single string arg", shellInvoking: true, cwes: ["CWE-78"] },
|
|
181
|
+
],
|
|
182
|
+
safePatterns: [
|
|
183
|
+
{ api: "system('cmd', arg1, arg2)", why: "Multi-arg system bypasses shell — arguments passed directly" },
|
|
184
|
+
{ api: "Open3.capture3('cmd', arg1, arg2)", why: "Multi-arg form bypasses shell" },
|
|
185
|
+
{ api: "Shellwords.escape(user_input)", why: "Proper shell escaping" },
|
|
186
|
+
],
|
|
187
|
+
investigationHints: {
|
|
188
|
+
grepPatterns: [
|
|
189
|
+
"\\bsystem\\(",
|
|
190
|
+
"IO\\.popen",
|
|
191
|
+
"Open3\\.",
|
|
192
|
+
"Shellwords",
|
|
193
|
+
],
|
|
194
|
+
fileHints: [
|
|
195
|
+
"Rake tasks",
|
|
196
|
+
"Background job processors",
|
|
197
|
+
"File processing handlers",
|
|
198
|
+
],
|
|
199
|
+
instructions: [
|
|
200
|
+
"Check for string interpolation in backtick commands",
|
|
201
|
+
"system() with a single string argument uses shell — multi-arg form is safe",
|
|
202
|
+
"Look for Shellwords.escape — if applied to all user input, it is safe",
|
|
203
|
+
],
|
|
204
|
+
},
|
|
205
|
+
fewShots: [
|
|
206
|
+
{
|
|
207
|
+
scenario: "Backtick command with interpolation",
|
|
208
|
+
vulnerableCode: 'def convert(filename)\n output = `convert #{filename} output.png`\n output\nend',
|
|
209
|
+
explanation: "filename interpolated into shell command via backticks. Attacker sends 'img.png; rm -rf /' — shell interprets the semicolon.",
|
|
210
|
+
},
|
|
211
|
+
],
|
|
212
|
+
antiHallucinationExtra: [
|
|
213
|
+
"system('cmd', arg1, arg2) multi-arg form is SAFE — no shell interpretation",
|
|
214
|
+
"Do NOT flag shell commands with hardcoded strings and no user input",
|
|
215
|
+
],
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
//# sourceMappingURL=ruby.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ruby.js","sourceRoot":"","sources":["../../../src/prompts/languages/ruby.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// NOTE: This file contains DETECTION PATTERNS for a security scanner.
|
|
2
|
+
// The API references are DETECTION TARGETS describing what the scanner
|
|
3
|
+
// looks for in scanned codebases, not code this file executes.
|
|
4
|
+
export const rustProfile = {
|
|
5
|
+
languageId: "Rust",
|
|
6
|
+
aliases: ["rust", "rs"],
|
|
7
|
+
generalHints: {
|
|
8
|
+
grepPatterns: [
|
|
9
|
+
"unsafe\\s*\\{",
|
|
10
|
+
"extern\\s+\"C\"",
|
|
11
|
+
"\\.unwrap\\(",
|
|
12
|
+
"panic!\\(",
|
|
13
|
+
"#\\[no_mangle\\]",
|
|
14
|
+
"std::process::Command",
|
|
15
|
+
],
|
|
16
|
+
fileHints: [
|
|
17
|
+
"Cargo.toml for dependencies and features",
|
|
18
|
+
"src/main.rs or src/lib.rs for entry points",
|
|
19
|
+
"build.rs for build-time code generation and FFI bindings",
|
|
20
|
+
"Files with 'unsafe' blocks",
|
|
21
|
+
],
|
|
22
|
+
instructions: [
|
|
23
|
+
"Check Cargo.toml for known vulnerable crate versions (cargo audit)",
|
|
24
|
+
"Focus on unsafe blocks — Rust's safety guarantees do not apply inside them",
|
|
25
|
+
"Check FFI boundaries — data crossing into/from C code needs manual validation",
|
|
26
|
+
"Look for .unwrap() on user-controlled Results — can panic and crash the service",
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
generalAntiHallucination: [
|
|
30
|
+
"Safe Rust prevents buffer overflows, use-after-free, and data races at compile time — only flag these inside unsafe blocks",
|
|
31
|
+
"Rust's borrow checker prevents most memory safety issues — do NOT flag safe Rust code for memory bugs",
|
|
32
|
+
"serde JSON/TOML/YAML deserialization is SAFE by default — it does not execute code",
|
|
33
|
+
],
|
|
34
|
+
vulnClasses: {
|
|
35
|
+
"unsafe-blocks": {
|
|
36
|
+
sinks: [
|
|
37
|
+
{ api: "unsafe { ptr::read/write }", risk: "Manual pointer operations bypass borrow checker — UB if pointer is invalid", cwes: ["CWE-787", "CWE-416"] },
|
|
38
|
+
{ api: "unsafe { slice::from_raw_parts }", risk: "Creating slice from raw pointer — UB if length is wrong or ptr is invalid", cwes: ["CWE-120"] },
|
|
39
|
+
{ api: "unsafe { transmute }", risk: "Reinterprets bits as different type — UB if invariants violated", cwes: ["CWE-843"] },
|
|
40
|
+
{ api: "unsafe impl Send/Sync", risk: "Manual Send/Sync impl can enable data races if invariants are wrong", cwes: ["CWE-362"] },
|
|
41
|
+
],
|
|
42
|
+
safePatterns: [
|
|
43
|
+
{ api: "unsafe in well-audited FFI wrapper with validation", why: "FFI requires unsafe but wrapper validates inputs" },
|
|
44
|
+
{ api: "unsafe for performance with documented invariants", why: "Acceptable if invariants are proven and tested" },
|
|
45
|
+
],
|
|
46
|
+
investigationHints: {
|
|
47
|
+
grepPatterns: [
|
|
48
|
+
"unsafe\\s*\\{",
|
|
49
|
+
"transmute",
|
|
50
|
+
"from_raw_parts",
|
|
51
|
+
"ptr::",
|
|
52
|
+
"as\\s*\\*const",
|
|
53
|
+
"as\\s*\\*mut",
|
|
54
|
+
],
|
|
55
|
+
fileHints: [
|
|
56
|
+
"FFI binding modules",
|
|
57
|
+
"Performance-critical inner loops",
|
|
58
|
+
"Custom allocator implementations",
|
|
59
|
+
],
|
|
60
|
+
instructions: [
|
|
61
|
+
"For each unsafe block, identify what invariant must hold and whether it can be violated by external input",
|
|
62
|
+
"Check slice::from_raw_parts — is the length from a trusted source? Can an attacker control it?",
|
|
63
|
+
"Look for unsafe impl Send for types containing raw pointers — is concurrent access actually safe?",
|
|
64
|
+
"Check transmute calls — does the source type actually have the same layout as the target?",
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
fewShots: [
|
|
68
|
+
{
|
|
69
|
+
scenario: "Unsafe slice creation with attacker-controlled length",
|
|
70
|
+
vulnerableCode: 'fn parse_packet(data: &[u8]) -> &[u32] {\n let len = u32::from_be_bytes(data[0..4].try_into().unwrap()) as usize;\n unsafe { std::slice::from_raw_parts(data[4..].as_ptr() as *const u32, len) }\n}',
|
|
71
|
+
explanation: "len comes from the packet (attacker-controlled). If len exceeds the actual data size, from_raw_parts creates an out-of-bounds slice — reading arbitrary memory.",
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
antiHallucinationExtra: [
|
|
75
|
+
"Safe Rust code (no unsafe keyword) CANNOT have buffer overflows or use-after-free — do NOT flag it",
|
|
76
|
+
"Unsafe blocks for calling well-known C libraries (libc, OpenSSL bindings) with correct signatures are generally safe",
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
"ffi-boundary": {
|
|
80
|
+
sinks: [
|
|
81
|
+
{ api: "extern \"C\" fn receiving *const/*mut", risk: "C code may pass invalid pointers — Rust code must validate before deref", cwes: ["CWE-476", "CWE-787"] },
|
|
82
|
+
{ api: "CString::from_raw(ptr)", risk: "Takes ownership of C-allocated string — double free if C also frees it", cwes: ["CWE-415"] },
|
|
83
|
+
{ api: "Box::from_raw(ptr)", risk: "Takes ownership — UB if ptr was not from Box::into_raw", cwes: ["CWE-416"] },
|
|
84
|
+
],
|
|
85
|
+
safePatterns: [
|
|
86
|
+
{ api: "CStr::from_ptr(ptr) for borrowed access", why: "Borrows without taking ownership — C retains ownership" },
|
|
87
|
+
{ api: "Null check before deref", why: "Prevents null pointer dereference from C callers" },
|
|
88
|
+
],
|
|
89
|
+
investigationHints: {
|
|
90
|
+
grepPatterns: [
|
|
91
|
+
"extern\\s+\"C\"",
|
|
92
|
+
"#\\[no_mangle\\]",
|
|
93
|
+
"CString",
|
|
94
|
+
"CStr",
|
|
95
|
+
"Box::from_raw",
|
|
96
|
+
"from_raw_parts",
|
|
97
|
+
],
|
|
98
|
+
fileHints: [
|
|
99
|
+
"FFI modules (ffi.rs, bindings.rs, sys/)",
|
|
100
|
+
"build.rs for bindgen usage",
|
|
101
|
+
"C header files (.h) that define the FFI interface",
|
|
102
|
+
],
|
|
103
|
+
instructions: [
|
|
104
|
+
"Check every extern function — are pointer parameters validated for null before use?",
|
|
105
|
+
"Look for ownership confusion: does Rust take ownership (Box::from_raw) of memory C will also free?",
|
|
106
|
+
"Check lifetime assumptions — does Rust hold references to C-allocated memory that C may free?",
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
fewShots: [
|
|
110
|
+
{
|
|
111
|
+
scenario: "FFI callback with null pointer dereference",
|
|
112
|
+
vulnerableCode: '#[no_mangle]\npub extern "C" fn process_buffer(ptr: *const u8, len: usize) -> i32 {\n let data = unsafe { std::slice::from_raw_parts(ptr, len) };\n // ...\n}',
|
|
113
|
+
explanation: "C caller may pass null ptr. from_raw_parts with null pointer is immediate UB. Must check ptr.is_null() before creating the slice.",
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
antiHallucinationExtra: [
|
|
117
|
+
"FFI unsafe blocks are EXPECTED in Rust — the question is whether inputs are validated, not whether unsafe exists",
|
|
118
|
+
],
|
|
119
|
+
},
|
|
120
|
+
"command-injection": {
|
|
121
|
+
sinks: [
|
|
122
|
+
{ api: "std::process::Command::new(\"sh\").arg(\"-c\").arg(user_str)", risk: "Shell interpretation of user-controlled string", shellInvoking: true, cwes: ["CWE-78"] },
|
|
123
|
+
{ api: "std::process::Command::new(user_binary)", risk: "User controls which binary is executed", shellInvoking: false, cwes: ["CWE-78"] },
|
|
124
|
+
],
|
|
125
|
+
safePatterns: [
|
|
126
|
+
{ api: "Command::new(\"fixed-binary\").arg(user_arg)", why: "Fixed binary with user args — no shell involved" },
|
|
127
|
+
],
|
|
128
|
+
investigationHints: {
|
|
129
|
+
grepPatterns: ["Command::new\\(", "\\.arg\\(", "\\.args\\("],
|
|
130
|
+
fileHints: ["Process spawning utilities", "Build/CI helpers"],
|
|
131
|
+
instructions: [
|
|
132
|
+
"Check if Command::new uses \"sh\" or \"bash\" with \"-c\" — this enables shell interpretation",
|
|
133
|
+
"Command::new(\"fixed\").arg(user_input) is safe against shell injection (no shell involved)",
|
|
134
|
+
],
|
|
135
|
+
},
|
|
136
|
+
fewShots: [
|
|
137
|
+
{
|
|
138
|
+
scenario: "Shell command with user-controlled argument",
|
|
139
|
+
vulnerableCode: 'let output = Command::new("sh")\n .arg("-c")\n .arg(format!("ffmpeg -i {} output.mp4", user_filename))\n .output()?;',
|
|
140
|
+
explanation: "user_filename is interpolated into a shell command string. Attacker sends 'input.mp4; rm -rf /' — shell interprets the semicolon.",
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
antiHallucinationExtra: [
|
|
144
|
+
"Command::new(\"binary\").arg(user_input) without shell is NOT vulnerable to shell metachar injection",
|
|
145
|
+
],
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
//# sourceMappingURL=rust.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rust.js","sourceRoot":"","sources":["../../../src/prompts/languages/rust.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Language-specific prompt tuning types.
|
|
3
|
+
*
|
|
4
|
+
* Each language profile provides per-vulnerability-class guidance:
|
|
5
|
+
* sinks, safe patterns, investigation hints, few-shot examples,
|
|
6
|
+
* and framework-specific advice.
|
|
7
|
+
*/
|
|
8
|
+
/** A language-specific dangerous sink/API for a vulnerability class. */
|
|
9
|
+
export interface LanguageSink {
|
|
10
|
+
/** The API or function name */
|
|
11
|
+
api: string;
|
|
12
|
+
/** Why it's dangerous in this context */
|
|
13
|
+
risk: string;
|
|
14
|
+
/** Whether this is a shell-invoking variant (for command injection) */
|
|
15
|
+
shellInvoking?: boolean;
|
|
16
|
+
/** CWEs this sink relates to */
|
|
17
|
+
cwes?: string[];
|
|
18
|
+
}
|
|
19
|
+
/** A safe alternative that should NOT be flagged. */
|
|
20
|
+
export interface LanguageSafePattern {
|
|
21
|
+
api: string;
|
|
22
|
+
why: string;
|
|
23
|
+
}
|
|
24
|
+
/** Investigation methodology hints for the LLM agent. */
|
|
25
|
+
export interface InvestigationHint {
|
|
26
|
+
/** Grep patterns specific to this language (regex strings) */
|
|
27
|
+
grepPatterns: string[];
|
|
28
|
+
/** Files or paths to prioritize reading */
|
|
29
|
+
fileHints: string[];
|
|
30
|
+
/** Step-by-step investigation instructions */
|
|
31
|
+
instructions: string[];
|
|
32
|
+
}
|
|
33
|
+
/** A few-shot example for a specific (language, vuln-class) pair. */
|
|
34
|
+
export interface LanguageFewShot {
|
|
35
|
+
/** Short scenario label */
|
|
36
|
+
scenario: string;
|
|
37
|
+
/** The vulnerable code snippet */
|
|
38
|
+
vulnerableCode: string;
|
|
39
|
+
/** Why it's vulnerable */
|
|
40
|
+
explanation: string;
|
|
41
|
+
}
|
|
42
|
+
/** Framework-specific security guidance within a language. */
|
|
43
|
+
export interface FrameworkGuidance {
|
|
44
|
+
framework: string;
|
|
45
|
+
/** Secure defaults the framework provides */
|
|
46
|
+
defaults: string[];
|
|
47
|
+
/** Known pitfalls or bypass patterns */
|
|
48
|
+
pitfalls: string[];
|
|
49
|
+
/** Config files/settings to check */
|
|
50
|
+
configChecks: string[];
|
|
51
|
+
}
|
|
52
|
+
/** Content for a specific vulnerability class within a language. */
|
|
53
|
+
export interface VulnClassContent {
|
|
54
|
+
/** Dangerous sinks/APIs to detect */
|
|
55
|
+
sinks: LanguageSink[];
|
|
56
|
+
/** Safe patterns to NOT flag */
|
|
57
|
+
safePatterns: LanguageSafePattern[];
|
|
58
|
+
/** Investigation methodology hints */
|
|
59
|
+
investigationHints: InvestigationHint;
|
|
60
|
+
/** Few-shot examples */
|
|
61
|
+
fewShots: LanguageFewShot[];
|
|
62
|
+
/** Framework-specific guidance (filtered by detected frameworks) */
|
|
63
|
+
frameworkGuidance?: FrameworkGuidance[];
|
|
64
|
+
/** Additional anti-hallucination constraints */
|
|
65
|
+
antiHallucinationExtra?: string[];
|
|
66
|
+
}
|
|
67
|
+
/** Complete language security profile. */
|
|
68
|
+
export interface LanguageProfile {
|
|
69
|
+
/** Language identifier matching RepoContext.languages values */
|
|
70
|
+
languageId: string;
|
|
71
|
+
/** Alternative identifiers */
|
|
72
|
+
aliases: string[];
|
|
73
|
+
/** Vulnerability class content, keyed by canonical vuln class ID */
|
|
74
|
+
vulnClasses: Record<string, VulnClassContent>;
|
|
75
|
+
/** Language-wide investigation hints (not vuln-specific) */
|
|
76
|
+
generalHints: InvestigationHint;
|
|
77
|
+
/** Language-wide anti-hallucination constraints */
|
|
78
|
+
generalAntiHallucination: string[];
|
|
79
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Language-specific prompt tuning types.
|
|
3
|
+
*
|
|
4
|
+
* Each language profile provides per-vulnerability-class guidance:
|
|
5
|
+
* sinks, safe patterns, investigation hints, few-shot examples,
|
|
6
|
+
* and framework-specific advice.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/prompts/languages/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AgentRuntime } from "../agent-runtime/types.js";
|
|
2
|
-
import type { ScanOpts } from "../types.js";
|
|
2
|
+
import type { RepoContext, ScanOpts } from "../types.js";
|
|
3
3
|
import type { Finding } from "./types.js";
|
|
4
4
|
import { FINDING_SCHEMA, parseFindingOutput, type FindingOutput, type NormalizedFinding } from "./normalize-findings.js";
|
|
5
5
|
export { FINDING_SCHEMA as AGENTIC_SCHEMA };
|
|
@@ -11,7 +11,7 @@ export interface AgenticRuntimeOptions {
|
|
|
11
11
|
maxBudgetUsd?: number;
|
|
12
12
|
}
|
|
13
13
|
/** Run the agentic scanner and return structured findings. */
|
|
14
|
-
export declare function runAgentic(repoRoot: string, opts: ScanOpts, model: string, defaultMaxFindings: number, runtimeOptions?: AgenticRuntimeOptions): Promise<AgenticOutput>;
|
|
14
|
+
export declare function runAgentic(repoRoot: string, opts: ScanOpts, model: string, defaultMaxFindings: number, runtimeOptions?: AgenticRuntimeOptions, repoContext?: RepoContext): Promise<AgenticOutput>;
|
|
15
15
|
/** Rank and map agentic findings into Finding records. */
|
|
16
16
|
export declare function selectAgenticFindings(output: AgenticOutput, repoRoot: string, repoName: string, ref: string, maxFindings?: number): Finding[];
|
|
17
17
|
/** Parse and normalize structured output from the agentic scanner. */
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { getLogger } from "../logger.js";
|
|
2
|
+
import { languageTuningModule } from "../prompts/language-tuning.js";
|
|
2
3
|
import { FINDING_SCHEMA, parseFindingOutput, selectFindings, computeFingerprint, } from "./normalize-findings.js";
|
|
3
4
|
const log = getLogger("agentic-scan");
|
|
4
5
|
// Re-export under old names for backward compatibility
|
|
5
6
|
export { FINDING_SCHEMA as AGENTIC_SCHEMA };
|
|
6
7
|
/** Run the agentic scanner and return structured findings. */
|
|
7
|
-
export async function runAgentic(repoRoot, opts, model, defaultMaxFindings, runtimeOptions = {}) {
|
|
8
|
+
export async function runAgentic(repoRoot, opts, model, defaultMaxFindings, runtimeOptions = {}, repoContext) {
|
|
8
9
|
const requestedMax = Math.max(1, opts.maxFindings ?? defaultMaxFindings);
|
|
9
|
-
const prompt = buildPrompt(opts, requestedMax);
|
|
10
|
+
const prompt = buildPrompt(opts, requestedMax, repoContext);
|
|
10
11
|
const runtime = runtimeOptions.runtime;
|
|
11
12
|
if (!runtime) {
|
|
12
13
|
throw new Error("Agentic scanner requires an explicit runtime.");
|
|
@@ -68,7 +69,7 @@ export const parseAgenticOutput = parseFindingOutput;
|
|
|
68
69
|
export function computeAgenticFingerprint(repoName, ref, finding) {
|
|
69
70
|
return computeFingerprint(repoName, ref, "agentic", finding);
|
|
70
71
|
}
|
|
71
|
-
function buildPrompt(opts, maxFindings) {
|
|
72
|
+
function buildPrompt(opts, maxFindings, repoContext) {
|
|
72
73
|
const reviewContext = opts.agenticReviewContext
|
|
73
74
|
? [
|
|
74
75
|
"",
|
|
@@ -96,6 +97,13 @@ function buildPrompt(opts, maxFindings) {
|
|
|
96
97
|
"",
|
|
97
98
|
...scanPathsContext,
|
|
98
99
|
...reviewContext,
|
|
100
|
+
...(repoContext?.languages.length
|
|
101
|
+
? [
|
|
102
|
+
`## Detected stack: ${repoContext.languages.join(", ")}${repoContext.frameworks.length ? ` (${repoContext.frameworks.join(", ")})` : ""}`,
|
|
103
|
+
languageTuningModule({ taskId: "agentic", repoContext, frameworks: repoContext.frameworks }),
|
|
104
|
+
"",
|
|
105
|
+
]
|
|
106
|
+
: []),
|
|
99
107
|
`Severity filter: ${opts.severity.join(", ") || "ERROR, WARNING, INFO"}`,
|
|
100
108
|
`Max findings: ${maxFindings}`,
|
|
101
109
|
`Exclude paths/globs: ${opts.excludePatterns.join(", ") || "(none)"}`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-agentic.js","sourceRoot":"","sources":["../../src/scanners/run-agentic.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"run-agentic.js","sourceRoot":"","sources":["../../src/scanners/run-agentic.ts"],"names":[],"mappings":"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"}
|
package/dist/store.js
CHANGED
|
@@ -17,6 +17,10 @@ export function initDb(dbPath) {
|
|
|
17
17
|
db.pragma("journal_mode = WAL");
|
|
18
18
|
db.pragma("busy_timeout = 5000");
|
|
19
19
|
runMigrations(db, allMigrations);
|
|
20
|
+
// Force a WAL checkpoint so the main DB file is fully written before the
|
|
21
|
+
// scan starts. This prevents data loss if the process crashes before
|
|
22
|
+
// SQLite's automatic checkpoint threshold is reached.
|
|
23
|
+
db.pragma("wal_checkpoint(TRUNCATE)");
|
|
20
24
|
return db;
|
|
21
25
|
}
|
|
22
26
|
/** Default DB path: .kuzushi/findings.sqlite3 in the scanned repo root. */
|