@kinosec/cli 0.11.1 → 0.11.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/dist/cli.js +172 -76
- package/package.json +1 -1
- package/dist/cli.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -8435,28 +8435,111 @@ ${import_picocolors3.default.dim("use of its services.")}
|
|
|
8435
8435
|
// src/commands/schedule.ts
|
|
8436
8436
|
var import_picocolors4 = __toESM(require_picocolors(), 1);
|
|
8437
8437
|
|
|
8438
|
-
// src/lib/validate-
|
|
8439
|
-
var
|
|
8440
|
-
|
|
8441
|
-
|
|
8442
|
-
|
|
8443
|
-
|
|
8438
|
+
// src/lib/validate-schedule.ts
|
|
8439
|
+
var SCHEDULE_PATTERNS = ["once", "daily", "weekly", "biweekly", "monthly"];
|
|
8440
|
+
var SCHEDULE_MODES = ["quick", "full"];
|
|
8441
|
+
var TIME_OF_DAY = /^([01]?\d|2[0-3]):[0-5]\d$/;
|
|
8442
|
+
var DIGITS = /^\d+$/;
|
|
8443
|
+
var ONCE_AT = /^(\d{4})-(\d{2})-(\d{2})T([01]\d|2[0-3]):[0-5]\d(:[0-5]\d(\.\d{3})?)?(Z|[+-]([01]\d|2[0-3]):[0-5]\d)$/;
|
|
8444
|
+
function scheduleInputError(flags, now) {
|
|
8445
|
+
const { pattern, mode, at, time, timezone, dayOfWeek, dayOfMonth } = flags;
|
|
8446
|
+
if (pattern !== void 0 && !SCHEDULE_PATTERNS.includes(pattern)) {
|
|
8447
|
+
return `Invalid --pattern "${pattern}". Must be one of: ${SCHEDULE_PATTERNS.join(", ")}.`;
|
|
8448
|
+
}
|
|
8449
|
+
if (mode !== void 0 && !SCHEDULE_MODES.includes(mode)) {
|
|
8450
|
+
return `Invalid --mode "${mode}". Schedules support: ${SCHEDULE_MODES.join(", ")}.`;
|
|
8451
|
+
}
|
|
8452
|
+
if (at !== void 0) {
|
|
8453
|
+
const atError = onceAtError(at, now);
|
|
8454
|
+
if (atError) return atError;
|
|
8455
|
+
}
|
|
8456
|
+
if (time !== void 0 && !TIME_OF_DAY.test(time)) {
|
|
8457
|
+
return `Invalid --time "${time}". Use 24-hour HH:MM, e.g. 09:00.`;
|
|
8458
|
+
}
|
|
8459
|
+
if (timezone !== void 0 && !isKnownTimezone(timezone)) {
|
|
8460
|
+
return `Invalid --timezone "${timezone}". Use an IANA name, e.g. America/New_York.`;
|
|
8461
|
+
}
|
|
8462
|
+
if (dayOfWeek !== void 0 && !isWholeNumberIn(dayOfWeek, 0, 6)) {
|
|
8463
|
+
return `Invalid --day-of-week "${dayOfWeek}". Use a whole number 0-6 (0=Sunday).`;
|
|
8464
|
+
}
|
|
8465
|
+
if (dayOfMonth !== void 0 && !isWholeNumberIn(dayOfMonth, 1, 31)) {
|
|
8466
|
+
return `Invalid --day-of-month "${dayOfMonth}". Use a whole number 1-31.`;
|
|
8467
|
+
}
|
|
8468
|
+
if (pattern === void 0 && at !== void 0) return "--at requires --pattern once.";
|
|
8469
|
+
if (pattern === void 0) return null;
|
|
8470
|
+
return patternFitError(pattern, flags);
|
|
8471
|
+
}
|
|
8472
|
+
function patternFitError(pattern, flags) {
|
|
8473
|
+
if (pattern === "once" && flags.at === void 0) {
|
|
8474
|
+
return "--at is required for once schedules: YYYY-MM-DDTHH:MM followed by Z or \xB1HH:MM.";
|
|
8475
|
+
}
|
|
8476
|
+
if (pattern === "once" && flags.time !== void 0) {
|
|
8477
|
+
return "--time does not apply to once schedules; put the time in --at.";
|
|
8478
|
+
}
|
|
8479
|
+
if (pattern !== "once" && flags.at !== void 0) {
|
|
8480
|
+
return "--at only applies to once schedules.";
|
|
8481
|
+
}
|
|
8482
|
+
const isWeekly = pattern === "weekly" || pattern === "biweekly";
|
|
8483
|
+
if (isWeekly && flags.dayOfWeek === void 0) {
|
|
8484
|
+
return `--day-of-week is required for ${pattern} schedules.`;
|
|
8485
|
+
}
|
|
8486
|
+
if (!isWeekly && flags.dayOfWeek !== void 0) {
|
|
8487
|
+
return "--day-of-week only applies to weekly and biweekly schedules.";
|
|
8444
8488
|
}
|
|
8489
|
+
if (pattern === "monthly" && flags.dayOfMonth === void 0) {
|
|
8490
|
+
return "--day-of-month is required for monthly schedules.";
|
|
8491
|
+
}
|
|
8492
|
+
if (pattern !== "monthly" && flags.dayOfMonth !== void 0) {
|
|
8493
|
+
return "--day-of-month only applies to monthly schedules.";
|
|
8494
|
+
}
|
|
8495
|
+
return null;
|
|
8496
|
+
}
|
|
8497
|
+
function onceAtError(at, now) {
|
|
8498
|
+
const match = ONCE_AT.exec(at);
|
|
8499
|
+
const ms = Date.parse(at);
|
|
8500
|
+
if (!match || Number.isNaN(ms) || !isCalendarDate(Number(match[1]), Number(match[2]), Number(match[3]))) {
|
|
8501
|
+
return `Invalid --at "${at}". Use YYYY-MM-DDTHH:MM followed by Z or \xB1HH:MM, on a real date.`;
|
|
8502
|
+
}
|
|
8503
|
+
if (ms <= now.getTime()) return `--at "${at}" is in the past. Pick a future time.`;
|
|
8504
|
+
return null;
|
|
8505
|
+
}
|
|
8506
|
+
function isCalendarDate(year, month, day) {
|
|
8507
|
+
const date = new Date(Date.UTC(year, month - 1, day));
|
|
8508
|
+
return date.getUTCMonth() === month - 1 && date.getUTCDate() === day;
|
|
8509
|
+
}
|
|
8510
|
+
function isKnownTimezone(timezone) {
|
|
8511
|
+
try {
|
|
8512
|
+
new Intl.DateTimeFormat("en-US", { timeZone: timezone });
|
|
8513
|
+
return true;
|
|
8514
|
+
} catch (error2) {
|
|
8515
|
+
if (error2 instanceof RangeError) return false;
|
|
8516
|
+
throw error2;
|
|
8517
|
+
}
|
|
8518
|
+
}
|
|
8519
|
+
function isWholeNumberIn(value, min, max) {
|
|
8520
|
+
if (!DIGITS.test(value)) return false;
|
|
8521
|
+
const n = Number(value);
|
|
8522
|
+
return n >= min && n <= max;
|
|
8445
8523
|
}
|
|
8446
8524
|
|
|
8447
8525
|
// src/commands/schedule.ts
|
|
8448
|
-
var VALID_PATTERNS = ["once", "daily", "weekly", "biweekly", "monthly"];
|
|
8449
8526
|
var DAY_NAMES = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
|
8450
8527
|
function extractTime(scheduledAt) {
|
|
8451
8528
|
if (!scheduledAt) return "\u2014";
|
|
8452
8529
|
const d = new Date(scheduledAt);
|
|
8453
8530
|
return d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", hour12: false });
|
|
8454
8531
|
}
|
|
8532
|
+
function extractDate(scheduledAt) {
|
|
8533
|
+
if (!scheduledAt) return "\u2014";
|
|
8534
|
+
const d = new Date(scheduledAt);
|
|
8535
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
8536
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
8537
|
+
}
|
|
8455
8538
|
function formatPattern(s) {
|
|
8456
8539
|
const time = extractTime(s.scheduled_at);
|
|
8457
8540
|
switch (s.recurrence_pattern) {
|
|
8458
8541
|
case "once":
|
|
8459
|
-
return `Once at ${time}`;
|
|
8542
|
+
return `Once on ${extractDate(s.scheduled_at)} at ${time}`;
|
|
8460
8543
|
case "daily":
|
|
8461
8544
|
return `Daily at ${time}`;
|
|
8462
8545
|
case "weekly":
|
|
@@ -8469,6 +8552,22 @@ function formatPattern(s) {
|
|
|
8469
8552
|
return s.recurrence_pattern;
|
|
8470
8553
|
}
|
|
8471
8554
|
}
|
|
8555
|
+
function modeTypedOnPentest(pentestCmd) {
|
|
8556
|
+
return pentestCmd.getOptionValueSource("mode") === "cli" ? String(pentestCmd.getOptionValue("mode")) : void 0;
|
|
8557
|
+
}
|
|
8558
|
+
function yesTypedOnPentest(pentestCmd) {
|
|
8559
|
+
return pentestCmd.getOptionValueSource("yes") === "cli";
|
|
8560
|
+
}
|
|
8561
|
+
function exitOnInputError(flags) {
|
|
8562
|
+
const error2 = scheduleInputError(flags, /* @__PURE__ */ new Date());
|
|
8563
|
+
if (!error2) return;
|
|
8564
|
+
console.error(error2);
|
|
8565
|
+
process.exit(2);
|
|
8566
|
+
}
|
|
8567
|
+
function scheduleMode(mode) {
|
|
8568
|
+
if (mode === "quick" || mode === "full") return mode;
|
|
8569
|
+
throw new Error(`Unchecked schedule mode "${mode}".`);
|
|
8570
|
+
}
|
|
8472
8571
|
function registerScheduleCommand(pentestCmd) {
|
|
8473
8572
|
const schedule = pentestCmd.command("schedule").description("Manage scheduled pentests");
|
|
8474
8573
|
schedule.command("list").description("List scheduled pentests").option("--limit <n>", "Max results per page", "20").option("--cursor <cursor>", "Pagination cursor").option("--status <status>", "Filter: active, paused, or all", "all").addHelpText("after", `
|
|
@@ -8543,36 +8642,35 @@ Examples:
|
|
|
8543
8642
|
handleError(error2);
|
|
8544
8643
|
}
|
|
8545
8644
|
});
|
|
8546
|
-
schedule.command("create").description("Create a scheduled pentest").requiredOption("--asset <id>", "Asset ID to scan").requiredOption("--pattern <pattern>", "Recurrence: once, daily, weekly, biweekly, monthly").option("--name <name>", "Schedule name").option("--mode <mode>", "Scan mode (default: full)", "full").option("--time <HH:MM>", "Time of day
|
|
8645
|
+
schedule.command("create").description("Create a scheduled pentest").requiredOption("--asset <id>", "Asset ID to scan").requiredOption("--pattern <pattern>", "Recurrence: once, daily, weekly, biweekly, monthly").option("--name <name>", "Schedule name").option("--mode <mode>", "Scan mode: quick or full (default: full)", "full").option("--at <datetime>", "Run time for --pattern once: YYYY-MM-DDTHH:MM followed by Z or \xB1HH:MM").option("--time <HH:MM>", "Time of day, 24h, for recurring patterns (default: 09:00)").option("--day-of-week <0-6>", "Day of week (0=Sun..6=Sat) for weekly/biweekly").option("--day-of-month <1-31>", "Day of month for monthly").option("--timezone <tz>", "Timezone (e.g. America/New_York)", Intl.DateTimeFormat().resolvedOptions().timeZone).addHelpText("after", `
|
|
8547
8646
|
Examples:
|
|
8548
8647
|
$ kinosec pentest schedule create --asset abc123 --pattern weekly --day-of-week 1 --time 09:00
|
|
8549
8648
|
$ kinosec pentest schedule create --asset abc123 --pattern daily --time 14:00
|
|
8550
|
-
$ kinosec pentest schedule create --asset abc123 --pattern monthly --day-of-month 15 --time 03:00 --timezone UTC
|
|
8551
|
-
|
|
8552
|
-
|
|
8553
|
-
|
|
8554
|
-
|
|
8555
|
-
|
|
8556
|
-
|
|
8557
|
-
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
|
|
8561
|
-
|
|
8562
|
-
process.exit(2);
|
|
8563
|
-
}
|
|
8649
|
+
$ kinosec pentest schedule create --asset abc123 --pattern monthly --day-of-month 15 --time 03:00 --timezone UTC
|
|
8650
|
+
$ kinosec pentest schedule create --asset abc123 --pattern once --at 2099-12-01T09:00+01:00`).action(async (options) => {
|
|
8651
|
+
const mode = modeTypedOnPentest(pentestCmd) ?? options.mode;
|
|
8652
|
+
exitOnInputError({
|
|
8653
|
+
pattern: options.pattern,
|
|
8654
|
+
mode,
|
|
8655
|
+
at: options.at,
|
|
8656
|
+
time: options.time,
|
|
8657
|
+
timezone: options.timezone,
|
|
8658
|
+
dayOfWeek: options.dayOfWeek,
|
|
8659
|
+
dayOfMonth: options.dayOfMonth
|
|
8660
|
+
});
|
|
8564
8661
|
try {
|
|
8565
8662
|
const opts = schedule.parent.parent.opts();
|
|
8566
8663
|
const { token, apiUrl } = resolveToken(opts);
|
|
8567
8664
|
const client = new KinoSecClient({ apiUrl, token });
|
|
8568
8665
|
const params = {
|
|
8569
|
-
asset_id: options.
|
|
8570
|
-
name: options.name ?? `${options.pattern} ${
|
|
8571
|
-
scan_mode:
|
|
8666
|
+
asset_id: options.asset,
|
|
8667
|
+
name: options.name ?? `${options.pattern} ${mode} pentest`,
|
|
8668
|
+
scan_mode: scheduleMode(mode),
|
|
8572
8669
|
recurrence_pattern: options.pattern,
|
|
8573
|
-
time_of_day: options.time,
|
|
8574
8670
|
timezone: options.timezone
|
|
8575
8671
|
};
|
|
8672
|
+
if (options.pattern === "once") params.once_at = new Date(options.at).toISOString();
|
|
8673
|
+
else params.time_of_day = options.time ?? "09:00";
|
|
8576
8674
|
if (options.dayOfWeek !== void 0) params.day_of_week = parseInt(options.dayOfWeek, 10);
|
|
8577
8675
|
if (options.dayOfMonth !== void 0) params.day_of_month = parseInt(options.dayOfMonth, 10);
|
|
8578
8676
|
const s = await client.schedules.create(params);
|
|
@@ -8590,17 +8688,26 @@ Manage: kinosec pentest schedule get ${s.id}`);
|
|
|
8590
8688
|
handleError(error2);
|
|
8591
8689
|
}
|
|
8592
8690
|
});
|
|
8593
|
-
schedule.command("update").description("Update a schedule").argument("<id>", "Schedule ID").option("--pattern <pattern>", "Recurrence: once, daily, weekly, biweekly, monthly").option("--name <name>", "Schedule name").option("--mode <mode>", "Scan mode").option("--time <HH:MM>", "Time of day (24h format)").option("--day-of-week <0-6>", "Day of week (0=Sun..6=Sat)").option("--day-of-month <1-31>", "Day of month").option("--timezone <tz>", "Timezone").addHelpText("after", `
|
|
8691
|
+
schedule.command("update").description("Update a schedule").argument("<id>", "Schedule ID").option("--pattern <pattern>", "Recurrence: once, daily, weekly, biweekly, monthly").option("--name <name>", "Schedule name").option("--mode <mode>", "Scan mode: quick or full").option("--at <datetime>", "Run time with --pattern once: ISO date and time with an offset").option("--time <HH:MM>", "Time of day (24h format)").option("--day-of-week <0-6>", "Day of week (0=Sun..6=Sat)").option("--day-of-month <1-31>", "Day of month").option("--timezone <tz>", "Timezone").addHelpText("after", `
|
|
8594
8692
|
Examples:
|
|
8595
8693
|
$ kinosec pentest schedule update abc123 --pattern daily --time 14:00
|
|
8596
|
-
$ kinosec pentest schedule update abc123 --time 14:00
|
|
8694
|
+
$ kinosec pentest schedule update abc123 --time 14:00
|
|
8695
|
+
$ kinosec pentest schedule update abc123 --pattern once --at 2099-12-01T09:00Z`).action(async (id, options) => {
|
|
8696
|
+
const mode = modeTypedOnPentest(pentestCmd) ?? options.mode;
|
|
8697
|
+
exitOnInputError({
|
|
8698
|
+
pattern: options.pattern,
|
|
8699
|
+
mode,
|
|
8700
|
+
at: options.at,
|
|
8701
|
+
time: options.time,
|
|
8702
|
+
timezone: options.timezone,
|
|
8703
|
+
dayOfWeek: options.dayOfWeek,
|
|
8704
|
+
dayOfMonth: options.dayOfMonth
|
|
8705
|
+
});
|
|
8597
8706
|
const params = {};
|
|
8598
8707
|
if (options.pattern) params.recurrence_pattern = options.pattern;
|
|
8599
8708
|
if (options.name) params.name = options.name;
|
|
8600
|
-
if (
|
|
8601
|
-
|
|
8602
|
-
params.scan_mode = options.mode;
|
|
8603
|
-
}
|
|
8709
|
+
if (mode) params.scan_mode = scheduleMode(mode);
|
|
8710
|
+
if (options.at !== void 0) params.once_at = new Date(options.at).toISOString();
|
|
8604
8711
|
if (options.time) params.time_of_day = options.time;
|
|
8605
8712
|
if (options.dayOfWeek !== void 0) params.day_of_week = parseInt(options.dayOfWeek, 10);
|
|
8606
8713
|
if (options.dayOfMonth !== void 0) params.day_of_month = parseInt(options.dayOfMonth, 10);
|
|
@@ -8630,7 +8737,7 @@ Examples:
|
|
|
8630
8737
|
$ kinosec pentest schedule delete abc123
|
|
8631
8738
|
$ kinosec pentest schedule delete abc123 --yes`).action(async (id, options) => {
|
|
8632
8739
|
try {
|
|
8633
|
-
await confirmDestructive(`Delete schedule ${id}?`, Boolean(options.yes));
|
|
8740
|
+
await confirmDestructive(`Delete schedule ${id}?`, Boolean(options.yes) || yesTypedOnPentest(pentestCmd));
|
|
8634
8741
|
const opts = schedule.parent.parent.opts();
|
|
8635
8742
|
const { token, apiUrl } = resolveToken(opts);
|
|
8636
8743
|
const client = new KinoSecClient({ apiUrl, token });
|
|
@@ -11904,18 +12011,6 @@ function normalizeActivityHistory(raw) {
|
|
|
11904
12011
|
return JSON.stringify(entry);
|
|
11905
12012
|
});
|
|
11906
12013
|
}
|
|
11907
|
-
function filterActivityForTier(entries, showFullDetails) {
|
|
11908
|
-
if (showFullDetails) return entries;
|
|
11909
|
-
return entries.filter((line) => !/^\s{4,}/.test(line)).map((line) => {
|
|
11910
|
-
if (/\] Running:/.test(line)) {
|
|
11911
|
-
return line.replace(
|
|
11912
|
-
/Running:.*/,
|
|
11913
|
-
"Running: [upgrade to Security Pro for full details]"
|
|
11914
|
-
);
|
|
11915
|
-
}
|
|
11916
|
-
return line;
|
|
11917
|
-
});
|
|
11918
|
-
}
|
|
11919
12014
|
|
|
11920
12015
|
// src/lib/buzzwords.ts
|
|
11921
12016
|
var SCAN_EXECUTION_PHRASES = [
|
|
@@ -12019,15 +12114,6 @@ function printActivityLines(entries, tty3) {
|
|
|
12019
12114
|
console.log(`${prompt} ${text}`);
|
|
12020
12115
|
}
|
|
12021
12116
|
}
|
|
12022
|
-
async function resolveShowFullDetails(client) {
|
|
12023
|
-
try {
|
|
12024
|
-
const me = await client.me.get();
|
|
12025
|
-
const slug = me.plan.slug;
|
|
12026
|
-
return slug === "security_pro" || slug === "enterprise";
|
|
12027
|
-
} catch {
|
|
12028
|
-
return false;
|
|
12029
|
-
}
|
|
12030
|
-
}
|
|
12031
12117
|
async function watchPentest(client, profileId, options) {
|
|
12032
12118
|
const { timeoutMs, intervalMs, useJson, showFindingsSummary } = options;
|
|
12033
12119
|
const tty3 = isTTY();
|
|
@@ -12056,7 +12142,6 @@ async function watchPentest(client, profileId, options) {
|
|
|
12056
12142
|
console.log("\nWatch cancelled. Pentest is still running.");
|
|
12057
12143
|
process.exit(0);
|
|
12058
12144
|
});
|
|
12059
|
-
const showFullDetails = await resolveShowFullDetails(client);
|
|
12060
12145
|
let consecutiveErrors = 0;
|
|
12061
12146
|
const MAX_CONSECUTIVE_ERRORS = 2;
|
|
12062
12147
|
let deferredExitCode = null;
|
|
@@ -12104,17 +12189,16 @@ ${icon2} Lost connection to pentest.`);
|
|
|
12104
12189
|
JSON.stringify({ ...scanDetail, elapsed_seconds: elapsed }) + "\n"
|
|
12105
12190
|
);
|
|
12106
12191
|
} else {
|
|
12107
|
-
const
|
|
12108
|
-
|
|
12109
|
-
|
|
12110
|
-
const newEntries = filtered.slice(printedCount);
|
|
12192
|
+
const entries = normalizeActivityHistory(scanDetail.activity_history);
|
|
12193
|
+
if (printedCount > entries.length) printedCount = 0;
|
|
12194
|
+
const newEntries = entries.slice(printedCount);
|
|
12111
12195
|
if (newEntries.length > 0) {
|
|
12112
12196
|
if (spinner) spinner.stop();
|
|
12113
12197
|
printActivityLines(newEntries, tty3);
|
|
12114
12198
|
printedCount += newEntries.length;
|
|
12115
12199
|
if (spinner) spinner = ora({ color: "green", isEnabled: true, discardStdin: false }).start();
|
|
12116
12200
|
}
|
|
12117
|
-
currentPhase = extractPhase(
|
|
12201
|
+
currentPhase = extractPhase(entries);
|
|
12118
12202
|
updateSpinnerText();
|
|
12119
12203
|
}
|
|
12120
12204
|
const status = scanDetail.scan_status;
|
|
@@ -12317,6 +12401,15 @@ Timeout: Scout did not connect within ${secs}s.`);
|
|
|
12317
12401
|
}
|
|
12318
12402
|
}
|
|
12319
12403
|
|
|
12404
|
+
// src/lib/validate-mode.ts
|
|
12405
|
+
var VALID_SCAN_MODES = ["full", "quick", "htb", "defcon", "exploit-only"];
|
|
12406
|
+
function validateScanMode(mode) {
|
|
12407
|
+
if (!VALID_SCAN_MODES.includes(mode)) {
|
|
12408
|
+
console.error(`Invalid mode "${mode}". Must be one of: ${VALID_SCAN_MODES.join(", ")}.`);
|
|
12409
|
+
process.exit(2);
|
|
12410
|
+
}
|
|
12411
|
+
}
|
|
12412
|
+
|
|
12320
12413
|
// src/lib/scope.ts
|
|
12321
12414
|
var import_picocolors7 = __toESM(require_picocolors(), 1);
|
|
12322
12415
|
|
|
@@ -12778,12 +12871,10 @@ Examples:
|
|
|
12778
12871
|
$ kinosec pentest -t target.htb --mode htb --source ./challenge.zip --zip-password hackthebox
|
|
12779
12872
|
|
|
12780
12873
|
Graybox (--source):
|
|
12781
|
-
Packs the target's source
|
|
12782
|
-
|
|
12783
|
-
|
|
12784
|
-
|
|
12785
|
-
The source is sent over HTTPS, used only on the ephemeral scan droplet, and is NOT stored
|
|
12786
|
-
server-side (the training log records just a "[GRAYBOX] N bytes injected" marker, never the source).`).action(async (options) => {
|
|
12874
|
+
Packs the target's source and sends it with the pentest as extra context.
|
|
12875
|
+
Works with --mode full and quick on your own assets. --budget controls how much
|
|
12876
|
+
source is packed (bigger bundles add context and cost).
|
|
12877
|
+
The source is sent over HTTPS, used only while the pentest runs, and is NOT stored.`).action(async (options) => {
|
|
12787
12878
|
if (!options.target && !options.profile) {
|
|
12788
12879
|
console.error("Provide --target <domain> or --profile <id>.");
|
|
12789
12880
|
process.exit(2);
|
|
@@ -13456,10 +13547,9 @@ Examples:
|
|
|
13456
13547
|
// src/commands/asset.ts
|
|
13457
13548
|
function registerAssetCommand(program3) {
|
|
13458
13549
|
const asset = program3.command("asset").description("Manage assets");
|
|
13459
|
-
asset.command("list").description("List assets").option("--limit <n>", "Max results per page", "20").option("--cursor <cursor>", "Pagination cursor").option("--
|
|
13550
|
+
asset.command("list").description("List assets").option("--limit <n>", "Max results per page", "20").option("--cursor <cursor>", "Pagination cursor").option("--status <status>", "Filter by status (verified, unverified)").option("--type <type>", "Filter by type (domain, subdomain, ip)").addHelpText("after", `
|
|
13460
13551
|
Examples:
|
|
13461
13552
|
$ kinosec asset list
|
|
13462
|
-
$ kinosec asset list --search example.com
|
|
13463
13553
|
$ kinosec asset list --type subdomain --status verified
|
|
13464
13554
|
$ kinosec asset list --limit 50 --json`).action(async (options) => {
|
|
13465
13555
|
try {
|
|
@@ -13469,7 +13559,6 @@ Examples:
|
|
|
13469
13559
|
const result = await client.assets.list({
|
|
13470
13560
|
limit: parseInt(options.limit, 10),
|
|
13471
13561
|
cursor: options.cursor,
|
|
13472
|
-
search: options.search,
|
|
13473
13562
|
status: options.status,
|
|
13474
13563
|
type: options.type
|
|
13475
13564
|
});
|
|
@@ -13704,7 +13793,7 @@ function registerFindingCommand(program3) {
|
|
|
13704
13793
|
const finding = program3.command("finding").description("Manage findings");
|
|
13705
13794
|
finding.command("list").description("List findings").argument("[profile-id]", "Pentest profile ID").option("--limit <n>", "Max results per page", "20").option("--cursor <cursor>", "Pagination cursor").addHelpText("after", `
|
|
13706
13795
|
Examples:
|
|
13707
|
-
$ kinosec finding list
|
|
13796
|
+
$ kinosec finding list a1b2c3d4-0000-0000-0000-000000000001
|
|
13708
13797
|
$ kinosec finding list --limit 50 --json`).action(async (profileId, options) => {
|
|
13709
13798
|
try {
|
|
13710
13799
|
const opts = program3.opts();
|
|
@@ -13713,7 +13802,7 @@ Examples:
|
|
|
13713
13802
|
const result = await client.findings.list({
|
|
13714
13803
|
limit: parseInt(options.limit, 10),
|
|
13715
13804
|
cursor: options.cursor,
|
|
13716
|
-
|
|
13805
|
+
scan_profile_id: profileId
|
|
13717
13806
|
});
|
|
13718
13807
|
if (opts.json || opts.output === "json") {
|
|
13719
13808
|
printJson(result);
|
|
@@ -13970,6 +14059,7 @@ Examples:
|
|
|
13970
14059
|
|
|
13971
14060
|
// src/commands/token.ts
|
|
13972
14061
|
var import_picocolors13 = __toESM(require_picocolors(), 1);
|
|
14062
|
+
var WEB_APP_TOKENS_URL = "https://kinosec.ai/settings?tab=api-tokens";
|
|
13973
14063
|
function registerTokenCommand(program3) {
|
|
13974
14064
|
const token = program3.command("token").description("Manage API tokens");
|
|
13975
14065
|
token.command("list").description("List API tokens").option("--limit <n>", "Max results per page", "20").option("--cursor <cursor>", "Pagination cursor").addHelpText("after", `
|
|
@@ -14015,8 +14105,8 @@ More results available. Use --cursor ${result.next_cursor}`));
|
|
|
14015
14105
|
Examples:
|
|
14016
14106
|
$ kinosec token create --name "CI" --scopes assets:read,scans:create
|
|
14017
14107
|
$ kinosec token create --name "Full" --scopes assets:read,scans:read --expires 30`).action(async (options) => {
|
|
14108
|
+
const opts = program3.opts();
|
|
14018
14109
|
try {
|
|
14019
|
-
const opts = program3.opts();
|
|
14020
14110
|
const { token: authToken, apiUrl } = resolveToken(opts);
|
|
14021
14111
|
const client = new KinoSecClient({ apiUrl, token: authToken });
|
|
14022
14112
|
const scopes = options.scopes.split(",").map((s) => s.trim());
|
|
@@ -14038,6 +14128,13 @@ Examples:
|
|
|
14038
14128
|
console.log(` Scopes: ${result.scopes.join(", ")}`);
|
|
14039
14129
|
console.log(` Expires: ${new Date(result.expires_at).toLocaleDateString()}`);
|
|
14040
14130
|
} catch (error2) {
|
|
14131
|
+
const isJson = opts.json || opts.output === "json";
|
|
14132
|
+
if (error2 instanceof ApiError && error2.code === "pat_cannot_create_token" && !isJson) {
|
|
14133
|
+
printWarning("API tokens can't create other API tokens.");
|
|
14134
|
+
console.error("Create a new token in the KinoSec web app:");
|
|
14135
|
+
console.error(` ${WEB_APP_TOKENS_URL}`);
|
|
14136
|
+
console.error("");
|
|
14137
|
+
}
|
|
14041
14138
|
handleError(error2);
|
|
14042
14139
|
}
|
|
14043
14140
|
});
|
|
@@ -14064,7 +14161,7 @@ Examples:
|
|
|
14064
14161
|
|
|
14065
14162
|
// src/cli.ts
|
|
14066
14163
|
var program2 = new Command();
|
|
14067
|
-
program2.name("kinosec").description("KinoSec CLI \u2014 run pentests from your terminal").version("0.11.
|
|
14164
|
+
program2.name("kinosec").description("KinoSec CLI \u2014 run pentests from your terminal").version("0.11.2", "-v, --version").option("--token <pat>", "API token (overrides KINOSEC_TOKEN)").option("--output <format>", "Output format: text or json", "text").option("--json", "Shorthand for --output json").option("--no-color", "Disable colors");
|
|
14068
14165
|
registerAuthCommand(program2);
|
|
14069
14166
|
registerMeCommand(program2);
|
|
14070
14167
|
registerCreditsCommand(program2);
|
|
@@ -14073,10 +14170,9 @@ registerAssetCommand(program2);
|
|
|
14073
14170
|
registerFindingCommand(program2);
|
|
14074
14171
|
registerReportCommand(program2);
|
|
14075
14172
|
registerTokenCommand(program2);
|
|
14076
|
-
program2.parseAsync(process.argv).then(() => checkForUpdate("0.11.
|
|
14173
|
+
program2.parseAsync(process.argv).then(() => checkForUpdate("0.11.2")).catch(handleError);
|
|
14077
14174
|
/*! Bundled license information:
|
|
14078
14175
|
|
|
14079
14176
|
ky/distribution/index.js:
|
|
14080
14177
|
(*! MIT License © Sindre Sorhus *)
|
|
14081
14178
|
*/
|
|
14082
|
-
//# sourceMappingURL=cli.js.map
|