@kinosec/cli 0.1.2 → 0.1.4
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 +19 -19
- package/dist/cli.js +62 -62
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -25,22 +25,22 @@ See [docs/install.md](docs/install.md) for all installation methods.
|
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
27
|
# Authenticate with a Personal Access Token
|
|
28
|
-
|
|
28
|
+
kinosec auth login
|
|
29
29
|
|
|
30
30
|
# List your assets
|
|
31
|
-
|
|
31
|
+
kinosec asset list
|
|
32
32
|
|
|
33
33
|
# Run a quick pentest
|
|
34
|
-
|
|
34
|
+
kinosec scan create --asset <id> --mode quick
|
|
35
35
|
|
|
36
36
|
# Watch progress in real-time
|
|
37
|
-
|
|
37
|
+
kinosec scan watch <scan-id>
|
|
38
38
|
|
|
39
39
|
# View findings
|
|
40
|
-
|
|
40
|
+
kinosec finding list --scan <scan-id>
|
|
41
41
|
|
|
42
42
|
# Export a report
|
|
43
|
-
|
|
43
|
+
kinosec report export --scan <report-id> --format markdown > report.md
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
See [docs/quickstart.md](docs/quickstart.md) for a full walkthrough.
|
|
@@ -48,15 +48,15 @@ See [docs/quickstart.md](docs/quickstart.md) for a full walkthrough.
|
|
|
48
48
|
## Commands
|
|
49
49
|
|
|
50
50
|
```
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
51
|
+
kinosec auth login|status|logout Manage authentication
|
|
52
|
+
kinosec config set|get|list Manage CLI configuration
|
|
53
|
+
kinosec me Show authenticated user info
|
|
54
|
+
|
|
55
|
+
kinosec asset list|get|create|delete|verify Manage assets
|
|
56
|
+
kinosec scan list|get|create|cancel|watch Manage security scans
|
|
57
|
+
kinosec finding list|get|update|retest Manage findings
|
|
58
|
+
kinosec report list|get|export Manage reports
|
|
59
|
+
kinosec token list|create|revoke Manage API tokens
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
Every command supports `--json` for machine-readable output and `--help` for usage details.
|
|
@@ -69,24 +69,24 @@ The CLI authenticates via Personal Access Tokens (PATs). Tokens are resolved in
|
|
|
69
69
|
|
|
70
70
|
1. `--token` flag
|
|
71
71
|
2. `KINOSEC_TOKEN` environment variable
|
|
72
|
-
3. `~/.config/kinosec/credentials.json` (saved by `
|
|
72
|
+
3. `~/.config/kinosec/credentials.json` (saved by `kinosec auth login`)
|
|
73
73
|
|
|
74
74
|
See [docs/authentication.md](docs/authentication.md) for details.
|
|
75
75
|
|
|
76
76
|
## Example
|
|
77
77
|
|
|
78
78
|
```bash
|
|
79
|
-
$
|
|
79
|
+
$ kinosec auth login
|
|
80
80
|
Paste your API token: ****
|
|
81
81
|
✓ Authenticated as you@example.com
|
|
82
82
|
Plan: security_pro (pro)
|
|
83
83
|
Org: Acme Inc
|
|
84
84
|
|
|
85
|
-
$
|
|
85
|
+
$ kinosec scan list
|
|
86
86
|
ID Target Mode Status Created
|
|
87
87
|
bc6b13bc-1234-5678-9abc-def012345678 example.com quick Completed 5/1/2026
|
|
88
88
|
|
|
89
|
-
$
|
|
89
|
+
$ kinosec finding list --scan bc6b13bc-1234-5678-9abc-def012345678
|
|
90
90
|
ID Name Severity Status Phase
|
|
91
91
|
f1a2b3c4-... SQL Injection Critical open active_scan
|
|
92
92
|
```
|
package/dist/cli.js
CHANGED
|
@@ -7781,7 +7781,7 @@ var KinoSecClient = class {
|
|
|
7781
7781
|
this.api = distribution_default.create({
|
|
7782
7782
|
prefixUrl: config.apiUrl,
|
|
7783
7783
|
headers: {
|
|
7784
|
-
"user-agent": config.userAgent ?? `
|
|
7784
|
+
"user-agent": config.userAgent ?? `kinosec/0.1.0 (${process.platform})`
|
|
7785
7785
|
},
|
|
7786
7786
|
hooks: {
|
|
7787
7787
|
beforeRequest: [
|
|
@@ -8102,12 +8102,12 @@ var DEFAULT_API_URL = "https://api.kinosec.ai/v1";
|
|
|
8102
8102
|
function resolveToken(options) {
|
|
8103
8103
|
const token = options.token ?? process.env.KINOSEC_TOKEN ?? readCredentials()?.token;
|
|
8104
8104
|
if (!token) {
|
|
8105
|
-
console.error('Not authenticated. Run "
|
|
8105
|
+
console.error('Not authenticated. Run "kinosec auth login" or set KINOSEC_TOKEN.');
|
|
8106
8106
|
process.exit(77);
|
|
8107
8107
|
}
|
|
8108
8108
|
if (options.token) {
|
|
8109
8109
|
console.error(
|
|
8110
|
-
"Warning: passing a token via --token exposes it in shell history. Prefer:
|
|
8110
|
+
"Warning: passing a token via --token exposes it in shell history. Prefer: kinosec auth login (interactive), KINOSEC_TOKEN env var, or stdin pipe."
|
|
8111
8111
|
);
|
|
8112
8112
|
}
|
|
8113
8113
|
const apiUrl = options.apiUrl ?? process.env.KINOSEC_API_URL ?? getConfigValue("api_url") ?? DEFAULT_API_URL;
|
|
@@ -8132,14 +8132,14 @@ function registerAuthCommand(program3) {
|
|
|
8132
8132
|
const auth = program3.command("auth").description("Manage authentication");
|
|
8133
8133
|
auth.command("login").description("Authenticate with a KinoSec API token").addHelpText("after", `
|
|
8134
8134
|
Examples:
|
|
8135
|
-
$
|
|
8136
|
-
$
|
|
8137
|
-
$ echo $TOKEN |
|
|
8135
|
+
$ kinosec auth login # interactive prompt
|
|
8136
|
+
$ kinosec auth login --token kns_live_pat_...
|
|
8137
|
+
$ echo $TOKEN | kinosec auth login # pipe from stdin`).action(async () => {
|
|
8138
8138
|
try {
|
|
8139
8139
|
let token = program3.opts().token;
|
|
8140
8140
|
if (token) {
|
|
8141
8141
|
console.error(
|
|
8142
|
-
"Warning: passing a token via --token exposes it in shell history. Prefer:
|
|
8142
|
+
"Warning: passing a token via --token exposes it in shell history. Prefer: kinosec auth login (interactive), KINOSEC_TOKEN env var, or stdin pipe."
|
|
8143
8143
|
);
|
|
8144
8144
|
}
|
|
8145
8145
|
if (!token) {
|
|
@@ -8178,11 +8178,11 @@ Examples:
|
|
|
8178
8178
|
});
|
|
8179
8179
|
auth.command("status").description("Show current authentication status").addHelpText("after", `
|
|
8180
8180
|
Examples:
|
|
8181
|
-
$
|
|
8181
|
+
$ kinosec auth status`).action(async () => {
|
|
8182
8182
|
try {
|
|
8183
8183
|
const creds = readCredentials();
|
|
8184
8184
|
if (!creds) {
|
|
8185
|
-
console.error('Not authenticated. Run "
|
|
8185
|
+
console.error('Not authenticated. Run "kinosec auth login" or set KINOSEC_TOKEN.');
|
|
8186
8186
|
process.exit(77);
|
|
8187
8187
|
}
|
|
8188
8188
|
const apiUrl = program3.opts().apiUrl ?? getConfigValue("api_url") ?? DEFAULT_API_URL;
|
|
@@ -8211,7 +8211,7 @@ Examples:
|
|
|
8211
8211
|
});
|
|
8212
8212
|
auth.command("logout").description("Remove stored credentials").addHelpText("after", `
|
|
8213
8213
|
Examples:
|
|
8214
|
-
$
|
|
8214
|
+
$ kinosec auth logout`).action(() => {
|
|
8215
8215
|
deleteCredentials();
|
|
8216
8216
|
printSuccess("Logged out. Credentials removed.");
|
|
8217
8217
|
});
|
|
@@ -8223,8 +8223,8 @@ function registerConfigCommand(program3) {
|
|
|
8223
8223
|
const config = program3.command("config").description("Manage CLI configuration");
|
|
8224
8224
|
config.command("set").description("Set a config value").argument("<key>", `Config key (${VALID_KEYS.join(", ")})`).argument("<value>", "Config value").addHelpText("after", `
|
|
8225
8225
|
Examples:
|
|
8226
|
-
$
|
|
8227
|
-
$
|
|
8226
|
+
$ kinosec config set api_url https://custom.api.url/v1
|
|
8227
|
+
$ kinosec config set output json`).action((key, value) => {
|
|
8228
8228
|
if (!VALID_KEYS.includes(key)) {
|
|
8229
8229
|
console.error(`Invalid config key "${key}". Valid keys: ${VALID_KEYS.join(", ")}`);
|
|
8230
8230
|
process.exit(2);
|
|
@@ -8234,7 +8234,7 @@ Examples:
|
|
|
8234
8234
|
});
|
|
8235
8235
|
config.command("get").description("Get a config value").argument("<key>", "Config key").addHelpText("after", `
|
|
8236
8236
|
Examples:
|
|
8237
|
-
$
|
|
8237
|
+
$ kinosec config get api_url`).action((key) => {
|
|
8238
8238
|
const value = getConfigValue(key);
|
|
8239
8239
|
if (value === void 0) {
|
|
8240
8240
|
console.error(`Config key "${key}" is not set.`);
|
|
@@ -8244,7 +8244,7 @@ Examples:
|
|
|
8244
8244
|
});
|
|
8245
8245
|
config.command("list").description("List all config values").addHelpText("after", `
|
|
8246
8246
|
Examples:
|
|
8247
|
-
$
|
|
8247
|
+
$ kinosec config list`).action(() => {
|
|
8248
8248
|
const cfg = readConfig();
|
|
8249
8249
|
const opts = program3.opts();
|
|
8250
8250
|
if (opts.json || opts.output === "json") {
|
|
@@ -8265,8 +8265,8 @@ Examples:
|
|
|
8265
8265
|
function registerMeCommand(program3) {
|
|
8266
8266
|
program3.command("me").description("Show authenticated user info").addHelpText("after", `
|
|
8267
8267
|
Examples:
|
|
8268
|
-
$
|
|
8269
|
-
$
|
|
8268
|
+
$ kinosec me
|
|
8269
|
+
$ kinosec me --json`).action(async () => {
|
|
8270
8270
|
try {
|
|
8271
8271
|
const opts = program3.opts();
|
|
8272
8272
|
const { token, apiUrl } = resolveToken(opts);
|
|
@@ -9718,8 +9718,8 @@ function registerScanCommand(program3) {
|
|
|
9718
9718
|
const scan = program3.command("scan").description("Manage security scans");
|
|
9719
9719
|
scan.command("list").description("List scans").option("--limit <n>", "Max results per page", "20").option("--cursor <cursor>", "Pagination cursor").addHelpText("after", `
|
|
9720
9720
|
Examples:
|
|
9721
|
-
$
|
|
9722
|
-
$
|
|
9721
|
+
$ kinosec scan list
|
|
9722
|
+
$ kinosec scan list --limit 5 --json`).action(async (options) => {
|
|
9723
9723
|
try {
|
|
9724
9724
|
const opts = program3.opts();
|
|
9725
9725
|
const { token, apiUrl } = resolveToken(opts);
|
|
@@ -9756,8 +9756,8 @@ More results available. Use --cursor ${result.next_cursor}`));
|
|
|
9756
9756
|
});
|
|
9757
9757
|
scan.command("get").description("Get scan details").argument("<id>", "Scan profile ID").addHelpText("after", `
|
|
9758
9758
|
Examples:
|
|
9759
|
-
$
|
|
9760
|
-
$
|
|
9759
|
+
$ kinosec scan get abc123
|
|
9760
|
+
$ kinosec scan get abc123 --json`).action(async (id) => {
|
|
9761
9761
|
try {
|
|
9762
9762
|
const opts = program3.opts();
|
|
9763
9763
|
const { token, apiUrl } = resolveToken(opts);
|
|
@@ -9786,8 +9786,8 @@ Examples:
|
|
|
9786
9786
|
});
|
|
9787
9787
|
scan.command("create").description("Start a new scan").option("--asset <id>", "Asset ID to scan").option("--profile <id>", "Scan profile ID (alternative to --asset)").option("--mode <mode>", "Scan mode: quick or full", "quick").addHelpText("after", `
|
|
9788
9788
|
Examples:
|
|
9789
|
-
$
|
|
9790
|
-
$
|
|
9789
|
+
$ kinosec scan create --asset abc123 --mode quick
|
|
9790
|
+
$ kinosec scan create --profile def456`).action(async (options) => {
|
|
9791
9791
|
if (!options.asset && !options.profile) {
|
|
9792
9792
|
console.error("Provide --asset <id> or --profile <id>.");
|
|
9793
9793
|
process.exit(2);
|
|
@@ -9797,7 +9797,7 @@ Examples:
|
|
|
9797
9797
|
if (!uuidRe.test(idValue)) {
|
|
9798
9798
|
console.error(`Invalid ID format: "${idValue}"`);
|
|
9799
9799
|
console.error("IDs are UUIDs (e.g. 550e8400-e29b-41d4-a716-446655440000).");
|
|
9800
|
-
console.error("Run
|
|
9800
|
+
console.error("Run kinosec asset list to find your asset ID.");
|
|
9801
9801
|
process.exit(2);
|
|
9802
9802
|
}
|
|
9803
9803
|
try {
|
|
@@ -9815,14 +9815,14 @@ Examples:
|
|
|
9815
9815
|
console.log(` Mode: ${result.scan_mode}`);
|
|
9816
9816
|
console.log(` Status: ${result.scan_status}`);
|
|
9817
9817
|
console.log(`
|
|
9818
|
-
Watch progress:
|
|
9818
|
+
Watch progress: kinosec scan watch ${result.scan_profile_id}`);
|
|
9819
9819
|
} catch (error) {
|
|
9820
9820
|
handleError(error);
|
|
9821
9821
|
}
|
|
9822
9822
|
});
|
|
9823
9823
|
scan.command("cancel").description("Cancel a running scan").argument("<id>", "Scan profile ID").addHelpText("after", `
|
|
9824
9824
|
Examples:
|
|
9825
|
-
$
|
|
9825
|
+
$ kinosec scan cancel abc123`).action(async (id) => {
|
|
9826
9826
|
try {
|
|
9827
9827
|
const opts = program3.opts();
|
|
9828
9828
|
const { token, apiUrl } = resolveToken(opts);
|
|
@@ -9839,9 +9839,9 @@ Examples:
|
|
|
9839
9839
|
});
|
|
9840
9840
|
scan.command("watch").description("Watch scan progress in real-time").argument("<id>", "Scan profile ID").option("--timeout <seconds>", "Max time to watch", "1800").option("--interval <seconds>", "Poll interval", "5").addHelpText("after", `
|
|
9841
9841
|
Examples:
|
|
9842
|
-
$
|
|
9843
|
-
$
|
|
9844
|
-
$
|
|
9842
|
+
$ kinosec scan watch abc123
|
|
9843
|
+
$ kinosec scan watch abc123 --timeout 600
|
|
9844
|
+
$ kinosec scan watch abc123 --json`).action(async (id, options) => {
|
|
9845
9845
|
try {
|
|
9846
9846
|
const opts = program3.opts();
|
|
9847
9847
|
const { token, apiUrl } = resolveToken(opts);
|
|
@@ -9895,14 +9895,14 @@ Scan failed: ${scanDetail.failure_reason || "unknown reason"}`));
|
|
|
9895
9895
|
}
|
|
9896
9896
|
console.log(import_picocolors3.default.green(`
|
|
9897
9897
|
Scan completed: ${scanDetail.domain_or_ip}`));
|
|
9898
|
-
console.log(` View findings:
|
|
9898
|
+
console.log(` View findings: kinosec finding list --scan ${id}`);
|
|
9899
9899
|
break;
|
|
9900
9900
|
}
|
|
9901
9901
|
if (Date.now() - startTime > timeoutMs) {
|
|
9902
9902
|
cleanup();
|
|
9903
9903
|
console.error(`
|
|
9904
9904
|
Timeout: scan still running after ${options.timeout}s.`);
|
|
9905
|
-
console.error(`Check status:
|
|
9905
|
+
console.error(`Check status: kinosec scan get ${id}`);
|
|
9906
9906
|
process.exit(3);
|
|
9907
9907
|
}
|
|
9908
9908
|
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
@@ -9940,8 +9940,8 @@ function registerAssetCommand(program3) {
|
|
|
9940
9940
|
const asset = program3.command("asset").description("Manage assets");
|
|
9941
9941
|
asset.command("list").description("List assets").option("--limit <n>", "Max results per page", "20").option("--cursor <cursor>", "Pagination cursor").addHelpText("after", `
|
|
9942
9942
|
Examples:
|
|
9943
|
-
$
|
|
9944
|
-
$
|
|
9943
|
+
$ kinosec asset list
|
|
9944
|
+
$ kinosec asset list --limit 50 --json`).action(async (options) => {
|
|
9945
9945
|
try {
|
|
9946
9946
|
const opts = program3.opts();
|
|
9947
9947
|
const { token, apiUrl } = resolveToken(opts);
|
|
@@ -9978,8 +9978,8 @@ More results available. Use --cursor ${result.next_cursor}`));
|
|
|
9978
9978
|
});
|
|
9979
9979
|
asset.command("get").description("Get asset details").argument("<id>", "Asset ID").addHelpText("after", `
|
|
9980
9980
|
Examples:
|
|
9981
|
-
$
|
|
9982
|
-
$
|
|
9981
|
+
$ kinosec asset get abc123
|
|
9982
|
+
$ kinosec asset get abc123 --json`).action(async (id) => {
|
|
9983
9983
|
try {
|
|
9984
9984
|
const opts = program3.opts();
|
|
9985
9985
|
const { token, apiUrl } = resolveToken(opts);
|
|
@@ -10007,8 +10007,8 @@ Examples:
|
|
|
10007
10007
|
});
|
|
10008
10008
|
asset.command("create").description("Create a new asset").requiredOption("--type <type>", "Asset type (domain, subdomain, ip)").requiredOption("--value <value>", "Asset value (e.g. example.com)").requiredOption("--verify-method <method>", "Verification method: dns or file").option("--parent <domain>", "Parent domain (for subdomains)").addHelpText("after", `
|
|
10009
10009
|
Examples:
|
|
10010
|
-
$
|
|
10011
|
-
$
|
|
10010
|
+
$ kinosec asset create --type domain --value example.com --verify-method dns
|
|
10011
|
+
$ kinosec asset create --type subdomain --value api.example.com --verify-method file --parent example.com`).action(async (options) => {
|
|
10012
10012
|
try {
|
|
10013
10013
|
const opts = program3.opts();
|
|
10014
10014
|
const { token, apiUrl } = resolveToken(opts);
|
|
@@ -10028,15 +10028,15 @@ Examples:
|
|
|
10028
10028
|
console.log(` Type: ${result.asset_type}`);
|
|
10029
10029
|
console.log(` Status: ${result.verification_status}`);
|
|
10030
10030
|
console.log(`
|
|
10031
|
-
Verify:
|
|
10031
|
+
Verify: kinosec asset verify ${result.id}`);
|
|
10032
10032
|
} catch (error) {
|
|
10033
10033
|
handleError(error);
|
|
10034
10034
|
}
|
|
10035
10035
|
});
|
|
10036
10036
|
asset.command("delete").description("Delete an asset").argument("<id>", "Asset ID").option("-y, --yes", "Skip confirmation prompt").addHelpText("after", `
|
|
10037
10037
|
Examples:
|
|
10038
|
-
$
|
|
10039
|
-
$
|
|
10038
|
+
$ kinosec asset delete abc123
|
|
10039
|
+
$ kinosec asset delete abc123 --yes`).action(async (id, options) => {
|
|
10040
10040
|
try {
|
|
10041
10041
|
await confirmDestructive(`Delete asset ${id}?`, Boolean(options.yes));
|
|
10042
10042
|
const opts = program3.opts();
|
|
@@ -10054,8 +10054,8 @@ Examples:
|
|
|
10054
10054
|
});
|
|
10055
10055
|
asset.command("verify").description("Trigger asset verification").argument("<id>", "Asset ID").addHelpText("after", `
|
|
10056
10056
|
Examples:
|
|
10057
|
-
$
|
|
10058
|
-
$
|
|
10057
|
+
$ kinosec asset verify abc123
|
|
10058
|
+
$ kinosec asset verify abc123 --json`).action(async (id) => {
|
|
10059
10059
|
try {
|
|
10060
10060
|
const opts = program3.opts();
|
|
10061
10061
|
const { token, apiUrl } = resolveToken(opts);
|
|
@@ -10103,8 +10103,8 @@ function registerFindingCommand(program3) {
|
|
|
10103
10103
|
const finding = program3.command("finding").description("Manage findings");
|
|
10104
10104
|
finding.command("list").description("List findings").option("--scan <id>", "Filter by scan profile ID").option("--limit <n>", "Max results per page", "20").option("--cursor <cursor>", "Pagination cursor").addHelpText("after", `
|
|
10105
10105
|
Examples:
|
|
10106
|
-
$
|
|
10107
|
-
$
|
|
10106
|
+
$ kinosec finding list --scan abc123
|
|
10107
|
+
$ kinosec finding list --limit 50 --json`).action(async (options) => {
|
|
10108
10108
|
try {
|
|
10109
10109
|
const opts = program3.opts();
|
|
10110
10110
|
const { token, apiUrl } = resolveToken(opts);
|
|
@@ -10142,8 +10142,8 @@ More results available. Use --cursor ${result.next_cursor}`));
|
|
|
10142
10142
|
});
|
|
10143
10143
|
finding.command("get").description("Get finding details").argument("<id>", "Finding ID").addHelpText("after", `
|
|
10144
10144
|
Examples:
|
|
10145
|
-
$
|
|
10146
|
-
$
|
|
10145
|
+
$ kinosec finding get abc123
|
|
10146
|
+
$ kinosec finding get abc123 --json`).action(async (id) => {
|
|
10147
10147
|
try {
|
|
10148
10148
|
const opts = program3.opts();
|
|
10149
10149
|
const { token, apiUrl } = resolveToken(opts);
|
|
@@ -10173,8 +10173,8 @@ Examples:
|
|
|
10173
10173
|
});
|
|
10174
10174
|
finding.command("update").description("Update finding status").argument("<id>", "Finding ID").requiredOption("--status <status>", "New status: open, fixed, false_positive, investigating, wont_fix").addHelpText("after", `
|
|
10175
10175
|
Examples:
|
|
10176
|
-
$
|
|
10177
|
-
$
|
|
10176
|
+
$ kinosec finding update abc123 --status false_positive
|
|
10177
|
+
$ kinosec finding update abc123 --status fixed`).action(async (id, options) => {
|
|
10178
10178
|
if (!VALID_STATUSES.includes(options.status)) {
|
|
10179
10179
|
console.error(`Invalid status "${options.status}". Valid: ${VALID_STATUSES.join(", ")}`);
|
|
10180
10180
|
process.exit(2);
|
|
@@ -10197,8 +10197,8 @@ Examples:
|
|
|
10197
10197
|
});
|
|
10198
10198
|
finding.command("retest").description("Trigger a retest for a finding").argument("<id>", "Finding ID").addHelpText("after", `
|
|
10199
10199
|
Examples:
|
|
10200
|
-
$
|
|
10201
|
-
$
|
|
10200
|
+
$ kinosec finding retest abc123
|
|
10201
|
+
$ kinosec finding retest abc123 --json`).action(async (id) => {
|
|
10202
10202
|
try {
|
|
10203
10203
|
const opts = program3.opts();
|
|
10204
10204
|
const { token, apiUrl } = resolveToken(opts);
|
|
@@ -10266,8 +10266,8 @@ function registerReportCommand(program3) {
|
|
|
10266
10266
|
const report = program3.command("report").description("Manage reports");
|
|
10267
10267
|
report.command("list").description("List reports").option("--limit <n>", "Max results per page", "20").option("--cursor <cursor>", "Pagination cursor").addHelpText("after", `
|
|
10268
10268
|
Examples:
|
|
10269
|
-
$
|
|
10270
|
-
$
|
|
10269
|
+
$ kinosec report list
|
|
10270
|
+
$ kinosec report list --limit 10 --json`).action(async (options) => {
|
|
10271
10271
|
try {
|
|
10272
10272
|
const opts = program3.opts();
|
|
10273
10273
|
const { token, apiUrl } = resolveToken(opts);
|
|
@@ -10306,8 +10306,8 @@ More results available. Use --cursor ${result.next_cursor}`));
|
|
|
10306
10306
|
});
|
|
10307
10307
|
report.command("get").description("Get report details").argument("<id>", "Report ID").addHelpText("after", `
|
|
10308
10308
|
Examples:
|
|
10309
|
-
$
|
|
10310
|
-
$
|
|
10309
|
+
$ kinosec report get abc123
|
|
10310
|
+
$ kinosec report get abc123 --json`).action(async (id) => {
|
|
10311
10311
|
try {
|
|
10312
10312
|
const opts = program3.opts();
|
|
10313
10313
|
const { token, apiUrl } = resolveToken(opts);
|
|
@@ -10341,8 +10341,8 @@ Examples:
|
|
|
10341
10341
|
});
|
|
10342
10342
|
report.command("export").description("Export a scan report").requiredOption("--scan <id>", "Scan report ID").option("--format <format>", "Export format: json or markdown", "json").addHelpText("after", `
|
|
10343
10343
|
Examples:
|
|
10344
|
-
$
|
|
10345
|
-
$
|
|
10344
|
+
$ kinosec report export --scan abc123 --format json > report.json
|
|
10345
|
+
$ kinosec report export --scan abc123 --format markdown > report.md`).action(async (options) => {
|
|
10346
10346
|
const validFormats = ["json", "markdown"];
|
|
10347
10347
|
if (!validFormats.includes(options.format)) {
|
|
10348
10348
|
console.error(`Invalid format "${options.format}". Valid: ${validFormats.join(", ")}`);
|
|
@@ -10373,8 +10373,8 @@ function registerTokenCommand(program3) {
|
|
|
10373
10373
|
const token = program3.command("token").description("Manage API tokens");
|
|
10374
10374
|
token.command("list").description("List API tokens").option("--limit <n>", "Max results per page", "20").option("--cursor <cursor>", "Pagination cursor").addHelpText("after", `
|
|
10375
10375
|
Examples:
|
|
10376
|
-
$
|
|
10377
|
-
$
|
|
10376
|
+
$ kinosec token list
|
|
10377
|
+
$ kinosec token list --json`).action(async (options) => {
|
|
10378
10378
|
try {
|
|
10379
10379
|
const opts = program3.opts();
|
|
10380
10380
|
const { token: authToken, apiUrl } = resolveToken(opts);
|
|
@@ -10412,8 +10412,8 @@ More results available. Use --cursor ${result.next_cursor}`));
|
|
|
10412
10412
|
});
|
|
10413
10413
|
token.command("create").description("Create a new API token").requiredOption("--name <name>", "Token name").requiredOption("--scopes <scopes>", "Comma-separated scopes (e.g. assets:read,scans:create)").option("--expires <days>", "Days until expiry", "90").addHelpText("after", `
|
|
10414
10414
|
Examples:
|
|
10415
|
-
$
|
|
10416
|
-
$
|
|
10415
|
+
$ kinosec token create --name "CI" --scopes assets:read,scans:create
|
|
10416
|
+
$ kinosec token create --name "Full" --scopes assets:read,scans:read --expires 30`).action(async (options) => {
|
|
10417
10417
|
try {
|
|
10418
10418
|
const opts = program3.opts();
|
|
10419
10419
|
const { token: authToken, apiUrl } = resolveToken(opts);
|
|
@@ -10442,8 +10442,8 @@ Examples:
|
|
|
10442
10442
|
});
|
|
10443
10443
|
token.command("revoke").description("Revoke an API token").argument("<id>", "Token ID").option("-y, --yes", "Skip confirmation prompt").addHelpText("after", `
|
|
10444
10444
|
Examples:
|
|
10445
|
-
$
|
|
10446
|
-
$
|
|
10445
|
+
$ kinosec token revoke abc123
|
|
10446
|
+
$ kinosec token revoke abc123 --yes`).action(async (id, options) => {
|
|
10447
10447
|
try {
|
|
10448
10448
|
await confirmDestructive(`Revoke token ${id}?`, Boolean(options.yes));
|
|
10449
10449
|
const opts = program3.opts();
|
|
@@ -10464,7 +10464,7 @@ Examples:
|
|
|
10464
10464
|
// src/cli.ts
|
|
10465
10465
|
var VERSION = "0.1.0";
|
|
10466
10466
|
var program2 = new Command();
|
|
10467
|
-
program2.name("
|
|
10467
|
+
program2.name("kinosec").description("KinoSec CLI \u2014 run pentests from your terminal").version(VERSION, "-v, --version").option("--token <pat>", "API token (overrides KINOSEC_TOKEN and config)").option("--api-url <url>", "API base URL (overrides config)").option("--output <format>", "Output format: text or json", "text").option("--json", "Shorthand for --output json").option("--no-color", "Disable colors");
|
|
10468
10468
|
registerAuthCommand(program2);
|
|
10469
10469
|
registerConfigCommand(program2);
|
|
10470
10470
|
registerMeCommand(program2);
|