kifaru 1.0.182 → 1.0.183
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.
|
@@ -74,7 +74,7 @@ export function auditText(content: string): { routes: string[]; secrets: string[
|
|
|
74
74
|
for (const regex of AUDIT_PATTERNS.LOGIC) {
|
|
75
75
|
const matches = content.matchAll(regex)
|
|
76
76
|
for (const m of matches) {
|
|
77
|
-
const val =
|
|
77
|
+
const val = m[0].trim().slice(0, 120)
|
|
78
78
|
if (val.length > 3) logicFlags.add(val)
|
|
79
79
|
}
|
|
80
80
|
}
|
|
@@ -184,18 +184,24 @@ export default function (pi: ExtensionAPI) {
|
|
|
184
184
|
promptSnippet: "Perform client-side static forensics on HTML and JavaScript bundles",
|
|
185
185
|
parameters: Type.Object({
|
|
186
186
|
target: Type.String({ description: "Target HTTP URL or local file path to HTML/JS artifact" }),
|
|
187
|
-
depth: Type.Optional(
|
|
188
|
-
|
|
189
|
-
|
|
187
|
+
depth: Type.Optional(
|
|
188
|
+
Type.Union([Type.Literal("shallow"), Type.Literal("deep")], {
|
|
189
|
+
description: "Audit depth: 'shallow' (target only) or 'deep' (fetches and scans linked JS scripts)",
|
|
190
|
+
}),
|
|
191
|
+
),
|
|
190
192
|
content: Type.Optional(Type.String({ description: "Optional raw string content to audit directly" })),
|
|
191
193
|
}),
|
|
192
|
-
async execute(
|
|
194
|
+
async execute(
|
|
195
|
+
_toolCallId,
|
|
196
|
+
params: { target: string; depth?: "shallow" | "deep"; content?: string },
|
|
197
|
+
signal?: AbortSignal,
|
|
198
|
+
): Promise<AgentToolResult<AuditResults>> {
|
|
193
199
|
try {
|
|
194
200
|
const result = await runClientSideAudit({ ...params, signal })
|
|
195
201
|
const lines: string[] = [
|
|
196
202
|
`Client-Side Audit: ${params.target} (${result.scriptsAnalyzed.length} asset(s) analyzed)`,
|
|
197
203
|
"",
|
|
198
|
-
`Routes Discovered (${result.routes.length})
|
|
204
|
+
`Routes Discovered (${result.routes.length}):`,
|
|
199
205
|
...result.routes.slice(0, 20).map((r) => ` - ${r}`),
|
|
200
206
|
result.routes.length > 20 ? ` ... (${result.routes.length - 20} more)` : "",
|
|
201
207
|
"",
|
|
@@ -133,7 +133,9 @@ export function generateSanitizerBuild(opts: {
|
|
|
133
133
|
return [compiler, ...flags, opts.target, "-o", output, ...extra].join(" ")
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
export function generateInvalidTransitions(
|
|
136
|
+
export function generateInvalidTransitions(
|
|
137
|
+
transitions: Array<{ from: string; to: string }>,
|
|
138
|
+
): Array<{ from: string; to: string; reason: string }> {
|
|
137
139
|
const states = new Set<string>()
|
|
138
140
|
const validMap = new Map<string, Set<string>>()
|
|
139
141
|
|
|
@@ -171,40 +173,60 @@ export default function (pi: ExtensionAPI) {
|
|
|
171
173
|
"Generate test configurations and payloads for dual-parser discrepancies (JSON vs form, CL.TE smuggling), fault injection (disk/memory/network), sanitizer build commands, or invalid business logic transitions.",
|
|
172
174
|
promptSnippet: "Generate dual-parser discrepancy tests, fault injection, or sanitizer build commands",
|
|
173
175
|
parameters: Type.Object({
|
|
174
|
-
category: Type.Union(
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
176
|
+
category: Type.Union(
|
|
177
|
+
[
|
|
178
|
+
Type.Literal("dual_parser"),
|
|
179
|
+
Type.Literal("fault_injection"),
|
|
180
|
+
Type.Literal("sanitizer_build"),
|
|
181
|
+
Type.Literal("state_machine"),
|
|
182
|
+
],
|
|
183
|
+
{ description: "Type of test generator to run" },
|
|
184
|
+
),
|
|
180
185
|
url: Type.Optional(Type.String({ description: "Target URL for dual_parser tests" })),
|
|
181
186
|
field: Type.Optional(Type.String({ description: "Parameter or body field name" })),
|
|
182
187
|
value: Type.Optional(Type.String({ description: "Parameter value" })),
|
|
183
|
-
faultMode: Type.Optional(
|
|
184
|
-
Type.
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
188
|
+
faultMode: Type.Optional(
|
|
189
|
+
Type.Union(
|
|
190
|
+
[
|
|
191
|
+
Type.Literal("latency"),
|
|
192
|
+
Type.Literal("disk"),
|
|
193
|
+
Type.Literal("fd"),
|
|
194
|
+
Type.Literal("clock"),
|
|
195
|
+
Type.Literal("memory"),
|
|
196
|
+
],
|
|
197
|
+
{ description: "Fault injection type" },
|
|
198
|
+
),
|
|
199
|
+
),
|
|
200
|
+
level: Type.Optional(
|
|
201
|
+
Type.Integer({ minimum: 1, maximum: 10, description: "Intensity level for fault injection" }),
|
|
202
|
+
),
|
|
203
|
+
sanitizer: Type.Optional(
|
|
204
|
+
Type.Union([Type.Literal("asan"), Type.Literal("ubsan"), Type.Literal("tsan")], {
|
|
205
|
+
description: "Compiler sanitizer",
|
|
198
206
|
}),
|
|
199
|
-
|
|
200
|
-
|
|
207
|
+
),
|
|
208
|
+
compiler: Type.Optional(
|
|
209
|
+
Type.Union([Type.Literal("clang"), Type.Literal("gcc")], { description: "Compiler binary" }),
|
|
210
|
+
),
|
|
211
|
+
sourceFile: Type.Optional(Type.String({ description: "Source code file to compile" })),
|
|
212
|
+
transitions: Type.Optional(
|
|
213
|
+
Type.Array(
|
|
214
|
+
Type.Object({
|
|
215
|
+
from: Type.String({ description: "Starting state" }),
|
|
216
|
+
to: Type.String({ description: "Target state" }),
|
|
217
|
+
}),
|
|
218
|
+
{ description: "Valid transitions for state_machine analysis" },
|
|
219
|
+
),
|
|
220
|
+
),
|
|
201
221
|
}),
|
|
202
222
|
async execute(_toolCallId, params): Promise<AgentToolResult<PayloadGeneratorDetails>> {
|
|
203
223
|
switch (params.category) {
|
|
204
224
|
case "dual_parser": {
|
|
205
225
|
const cases = generateDualParserCases(params.url || "https://example.com/api", params.field, params.value)
|
|
206
226
|
return {
|
|
207
|
-
content: [
|
|
227
|
+
content: [
|
|
228
|
+
{ type: "text", text: `Dual-Parser Cases (${cases.length}):\n` + JSON.stringify(cases, null, 2) },
|
|
229
|
+
],
|
|
208
230
|
details: { category: "dual_parser", cases },
|
|
209
231
|
}
|
|
210
232
|
}
|
|
@@ -212,7 +234,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
212
234
|
const mode = params.faultMode ?? "latency"
|
|
213
235
|
const cmds = generateFaultInjection(mode, params.level ?? 1)
|
|
214
236
|
return {
|
|
215
|
-
content: [
|
|
237
|
+
content: [
|
|
238
|
+
{ type: "text", text: `Fault Injection Commands [${mode}]:\n` + cmds.map((c) => ` $ ${c}`).join("\n") },
|
|
239
|
+
],
|
|
216
240
|
details: { category: "fault_injection", mode, commands: cmds },
|
|
217
241
|
}
|
|
218
242
|
}
|
|
@@ -231,11 +255,14 @@ export default function (pi: ExtensionAPI) {
|
|
|
231
255
|
const transitions = params.transitions ?? []
|
|
232
256
|
const invalid = generateInvalidTransitions(transitions)
|
|
233
257
|
return {
|
|
234
|
-
content: [
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
258
|
+
content: [
|
|
259
|
+
{
|
|
260
|
+
type: "text",
|
|
261
|
+
text:
|
|
262
|
+
`Invalid State Transitions (${invalid.length} potential logic bypasses):\n` +
|
|
263
|
+
invalid.map((t) => ` - [SKIP/BYPASS] ${t.from} -> ${t.to}: ${t.reason}`).join("\n"),
|
|
264
|
+
},
|
|
265
|
+
],
|
|
239
266
|
details: { category: "state_machine", invalidTransitions: invalid },
|
|
240
267
|
}
|
|
241
268
|
}
|
|
@@ -248,7 +275,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
248
275
|
handler: async (args, ctx) => {
|
|
249
276
|
const cat = (args ?? "").trim().toLowerCase()
|
|
250
277
|
if (cat !== "dual_parser" && cat !== "fault_injection" && cat !== "sanitizer_build" && cat !== "state_machine") {
|
|
251
|
-
ctx.ui.notify(
|
|
278
|
+
ctx.ui.notify(
|
|
279
|
+
"usage: /kifaru-payload <dual_parser | fault_injection | sanitizer_build | state_machine>",
|
|
280
|
+
"warning",
|
|
281
|
+
)
|
|
252
282
|
return
|
|
253
283
|
}
|
|
254
284
|
pi.sendMessage({
|
|
@@ -38,7 +38,10 @@ export function cveYear(id: string): string | undefined {
|
|
|
38
38
|
return parts.length >= 2 ? parts[1] : undefined
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
export async function fetchNomiSecPoc(
|
|
41
|
+
export async function fetchNomiSecPoc(
|
|
42
|
+
cveId: string,
|
|
43
|
+
signal?: AbortSignal,
|
|
44
|
+
): Promise<{ repos: RepoResult[]; error?: string }> {
|
|
42
45
|
if (process.env.PI_OFFLINE === "1") return { repos: [] }
|
|
43
46
|
const cve = normalizeCve(cveId)
|
|
44
47
|
const year = cveYear(cve)
|
|
@@ -128,10 +131,7 @@ export async function searchPocs(cveId: string, customQuery?: string, signal?: A
|
|
|
128
131
|
let exploitDbUrls: string[] = []
|
|
129
132
|
|
|
130
133
|
if (isCve) {
|
|
131
|
-
const [nomi, edb] = await Promise.all([
|
|
132
|
-
fetchNomiSecPoc(norm, signal),
|
|
133
|
-
fetchExploitDb(norm, signal),
|
|
134
|
-
])
|
|
134
|
+
const [nomi, edb] = await Promise.all([fetchNomiSecPoc(norm, signal), fetchExploitDb(norm, signal)])
|
|
135
135
|
repos = nomi.repos
|
|
136
136
|
exploitDbUrls = edb
|
|
137
137
|
}
|
|
@@ -190,8 +190,12 @@ export default function (pi: ExtensionAPI) {
|
|
|
190
190
|
"Search for disclosed security reports, bug bounty writeups (HackerOne, Bugcrowd), and GitHub security advisories for a given target, framework, or vulnerability class.",
|
|
191
191
|
promptSnippet: "Search prior vulnerability writeups and bug bounty disclosures",
|
|
192
192
|
parameters: Type.Object({
|
|
193
|
-
query: Type.String({
|
|
194
|
-
|
|
193
|
+
query: Type.String({
|
|
194
|
+
description: "Target technology, endpoint, or vulnerability pattern (e.g. 'Next.js SSRF' or 'GraphQL IDOR')",
|
|
195
|
+
}),
|
|
196
|
+
numResults: Type.Optional(
|
|
197
|
+
Type.Integer({ minimum: 1, maximum: 20, description: "Maximum results to return (default: 6)" }),
|
|
198
|
+
),
|
|
195
199
|
}),
|
|
196
200
|
async execute(_toolCallId, params: { query: string; numResults?: number }, signal?: AbortSignal) {
|
|
197
201
|
const items = await searchPriorArt(params.query, params.numResults ?? 6, signal)
|
|
@@ -202,10 +206,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
202
206
|
}
|
|
203
207
|
}
|
|
204
208
|
|
|
205
|
-
const lines: string[] = [
|
|
206
|
-
`Prior Art Results for: "${params.query}" (${items.length} records)`,
|
|
207
|
-
"",
|
|
208
|
-
]
|
|
209
|
+
const lines: string[] = [`Prior Art Results for: "${params.query}" (${items.length} records)`, ""]
|
|
209
210
|
for (const item of items) {
|
|
210
211
|
lines.push(`[${item.source.toUpperCase()}] ${item.title} (${item.severity.toUpperCase()})`)
|
|
211
212
|
lines.push(` URL: ${item.url}`)
|
package/kifaru-pi.js
CHANGED
|
@@ -58212,7 +58212,7 @@ Ctrl+C stops the gateway.`);
|
|
|
58212
58212
|
async function handleCli() {
|
|
58213
58213
|
const args = process.argv.slice(2);
|
|
58214
58214
|
if (args.includes("--version") || args.includes("-v")) {
|
|
58215
|
-
console.log("1.0.
|
|
58215
|
+
console.log("1.0.183");
|
|
58216
58216
|
process.exit(0);
|
|
58217
58217
|
}
|
|
58218
58218
|
if (args[0] === "dashboard") {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kifaru",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"gitHead": "
|
|
3
|
+
"version": "1.0.183",
|
|
4
|
+
"gitHead": "a470d168bc35a08eecad543456ac3ec82344877e",
|
|
5
5
|
"description": "Kifaru security agent on the Pi runtime",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|