securewithtrace 0.42.0 → 0.43.0
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 +11 -0
- package/dist/index.js +252 -111
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -263,6 +263,9 @@ tracecli pentest findings list --pentest PT-3 --output tsv | cut -f1,4
|
|
|
263
263
|
# Open the pentest detail page in a browser
|
|
264
264
|
tracecli pentest findings list --pentest PT-3 --web
|
|
265
265
|
|
|
266
|
+
# One finding with its full write-up, as markdown for a coding agent
|
|
267
|
+
tracecli pentest findings get --pentest PT-3 --finding PTF-7
|
|
268
|
+
|
|
266
269
|
# Mark a finding in progress, then remediated when the fix is ready for retest
|
|
267
270
|
tracecli pentest findings status-update --pentest PT-3 --finding 7 --status IN_PROGRESS
|
|
268
271
|
tracecli pentest findings status-update --pentest PT-3 --finding 7 --status REMEDIATED
|
|
@@ -284,6 +287,14 @@ Flags for `pentest findings list`:
|
|
|
284
287
|
| `--output <format>` | `-o` | Output format: `table` (default), `json`, `tsv` |
|
|
285
288
|
| `--web` | `-w` | Open the pentest detail page in a browser |
|
|
286
289
|
|
|
290
|
+
Flags for `pentest findings get`:
|
|
291
|
+
|
|
292
|
+
| Flag | Shorthand | Description |
|
|
293
|
+
|------|-----------|-------------|
|
|
294
|
+
| `--pentest <id>` | | Pentest display ID (e.g. `PT-3`) or UUID (required) |
|
|
295
|
+
| `--finding <id>` | | Finding number (e.g. `PTF-7`) or UUID (required) |
|
|
296
|
+
| `--output <format>` | `-o` | Output format: `text` (markdown, default), `json` |
|
|
297
|
+
|
|
287
298
|
Flags for `pentest findings status-update`:
|
|
288
299
|
|
|
289
300
|
| Flag | Shorthand | Description |
|
package/dist/index.js
CHANGED
|
@@ -46485,117 +46485,6 @@ Examples:
|
|
|
46485
46485
|
});
|
|
46486
46486
|
}
|
|
46487
46487
|
|
|
46488
|
-
// src/pentest/questionnaire.ts
|
|
46489
|
-
function buildUpsertQuestionnaireBody(answers) {
|
|
46490
|
-
if (answers === null) {
|
|
46491
|
-
return { answers: null };
|
|
46492
|
-
}
|
|
46493
|
-
return { answers: normalizePentestCustomerIntakeAnswers(answers) };
|
|
46494
|
-
}
|
|
46495
|
-
function parseQuestionnaireAnswersFile(raw, sourceLabel = "file") {
|
|
46496
|
-
let parsed;
|
|
46497
|
-
try {
|
|
46498
|
-
parsed = JSON.parse(raw);
|
|
46499
|
-
} catch {
|
|
46500
|
-
return { error: `Invalid JSON in ${sourceLabel}.` };
|
|
46501
|
-
}
|
|
46502
|
-
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
46503
|
-
return {
|
|
46504
|
-
error: `${sourceLabel} must be a JSON object of questionnaire answers (not an array or null).`
|
|
46505
|
-
};
|
|
46506
|
-
}
|
|
46507
|
-
if ("answers" in parsed && Object.keys(parsed).length === 1) {
|
|
46508
|
-
return {
|
|
46509
|
-
error: `${sourceLabel} must contain the answers object directly, not an { answers } wrapper. The CLI wraps it for the API.`
|
|
46510
|
-
};
|
|
46511
|
-
}
|
|
46512
|
-
const result = PentestCustomerIntakeAnswersSchema.safeParse(parsed);
|
|
46513
|
-
if (!result.success) {
|
|
46514
|
-
const issue2 = result.error.issues[0];
|
|
46515
|
-
const path = issue2?.path.length ? issue2.path.join(".") : "answers";
|
|
46516
|
-
const message = issue2?.message ?? "invalid";
|
|
46517
|
-
return { error: `Invalid questionnaire answers in ${sourceLabel}: ${path} \u2014 ${message}` };
|
|
46518
|
-
}
|
|
46519
|
-
return { answers: normalizePentestCustomerIntakeAnswers(result.data) };
|
|
46520
|
-
}
|
|
46521
|
-
function applyTextIntakeAnswer(current, key, input) {
|
|
46522
|
-
const trimmed = input.trim();
|
|
46523
|
-
if (trimmed.length === 0) {
|
|
46524
|
-
return current;
|
|
46525
|
-
}
|
|
46526
|
-
return { ...current, [key]: trimmed };
|
|
46527
|
-
}
|
|
46528
|
-
function applyMultiSelectIntakeAnswer(current, key, selected) {
|
|
46529
|
-
if (selected.length === 0) {
|
|
46530
|
-
return current;
|
|
46531
|
-
}
|
|
46532
|
-
return {
|
|
46533
|
-
...current,
|
|
46534
|
-
[key]: Array.from(new Set(selected)).sort()
|
|
46535
|
-
};
|
|
46536
|
-
}
|
|
46537
|
-
function formatIssueClasses(values) {
|
|
46538
|
-
return values.map((v) => INTAKE_ISSUE_CLASS_LABELS[v]).join(", ");
|
|
46539
|
-
}
|
|
46540
|
-
function formatSurfaces(values) {
|
|
46541
|
-
return values.map((v) => INTAKE_SURFACE_LABELS[v]).join(", ");
|
|
46542
|
-
}
|
|
46543
|
-
function formatAnswerValue(key, answers) {
|
|
46544
|
-
switch (key) {
|
|
46545
|
-
case "issueClasses": {
|
|
46546
|
-
const values = answers.issueClasses;
|
|
46547
|
-
if (values === void 0 || values.length === 0) {
|
|
46548
|
-
return null;
|
|
46549
|
-
}
|
|
46550
|
-
return formatIssueClasses(values);
|
|
46551
|
-
}
|
|
46552
|
-
case "surfaces": {
|
|
46553
|
-
const values = answers.surfaces;
|
|
46554
|
-
if (values === void 0 || values.length === 0) {
|
|
46555
|
-
return null;
|
|
46556
|
-
}
|
|
46557
|
-
return formatSurfaces(values);
|
|
46558
|
-
}
|
|
46559
|
-
default: {
|
|
46560
|
-
const value = answers[key];
|
|
46561
|
-
if (value === void 0 || value.trim().length === 0) {
|
|
46562
|
-
return null;
|
|
46563
|
-
}
|
|
46564
|
-
return value;
|
|
46565
|
-
}
|
|
46566
|
-
}
|
|
46567
|
-
}
|
|
46568
|
-
function formatQuestionnaireShow(input) {
|
|
46569
|
-
const submitted = input.submitted === true;
|
|
46570
|
-
const editableLine = input.editable ? "yes (scoping window open)" : submitted ? "no (submitted)" : "no (editing closed after scoping)";
|
|
46571
|
-
const lines = [`Editable: ${editableLine}`, `Submitted: ${submitted ? "yes" : "no"}`];
|
|
46572
|
-
if (input.answers === null || Object.keys(input.answers).length === 0) {
|
|
46573
|
-
lines.push("Answers: (none)");
|
|
46574
|
-
return lines.join("\n");
|
|
46575
|
-
}
|
|
46576
|
-
lines.push("Answers:");
|
|
46577
|
-
for (const key of PENTEST_CUSTOMER_INTAKE_ANSWER_KEYS) {
|
|
46578
|
-
const value = formatAnswerValue(key, input.answers);
|
|
46579
|
-
if (value === null) {
|
|
46580
|
-
continue;
|
|
46581
|
-
}
|
|
46582
|
-
lines.push(`${PENTEST_CUSTOMER_INTAKE_LABELS[key]}: ${value}`);
|
|
46583
|
-
}
|
|
46584
|
-
return lines.join("\n");
|
|
46585
|
-
}
|
|
46586
|
-
function issueClassSelectOptions() {
|
|
46587
|
-
return CustomerPriorityCategoryValues.map((value) => ({
|
|
46588
|
-
value,
|
|
46589
|
-
label: INTAKE_ISSUE_CLASS_LABELS[value]
|
|
46590
|
-
}));
|
|
46591
|
-
}
|
|
46592
|
-
function surfaceSelectOptions() {
|
|
46593
|
-
return IntakeSurfaceValues.map((value) => ({
|
|
46594
|
-
value,
|
|
46595
|
-
label: INTAKE_SURFACE_LABELS[value]
|
|
46596
|
-
}));
|
|
46597
|
-
}
|
|
46598
|
-
|
|
46599
46488
|
// src/pentest/status-update.ts
|
|
46600
46489
|
var PENTEST_IDENTIFIER_PATTERN = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|pt-\d+|\d+)$/i;
|
|
46601
46490
|
var FINDING_IDENTIFIER_PATTERN = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|ptf-\d+|\d+)$/i;
|
|
@@ -46777,6 +46666,257 @@ Examples:
|
|
|
46777
46666
|
});
|
|
46778
46667
|
}
|
|
46779
46668
|
|
|
46669
|
+
// src/pentest/get-finding.ts
|
|
46670
|
+
var OUTPUT_FORMATS2 = ["text", "json"];
|
|
46671
|
+
function isOutputFormat2(value) {
|
|
46672
|
+
return OUTPUT_FORMATS2.includes(value);
|
|
46673
|
+
}
|
|
46674
|
+
var PROSE_SECTIONS = [
|
|
46675
|
+
{ key: "description", heading: "Description" },
|
|
46676
|
+
{ key: "impact", heading: "Impact" },
|
|
46677
|
+
{ key: "attackScenario", heading: "Attack Scenario" },
|
|
46678
|
+
{ key: "proofOfConcept", heading: "Proof of Concept" },
|
|
46679
|
+
{ key: "rootCauseAnalysis", heading: "Root Cause Analysis" },
|
|
46680
|
+
{ key: "remediation", heading: "Remediation" },
|
|
46681
|
+
{ key: "severityConsiderations", heading: "Severity Considerations" },
|
|
46682
|
+
{ key: "verification", heading: "Verification" }
|
|
46683
|
+
];
|
|
46684
|
+
function sanitizeMarkdown(value) {
|
|
46685
|
+
return value.split("\n").map(sanitizeDisplay).join("\n");
|
|
46686
|
+
}
|
|
46687
|
+
function formatFindingMarkdown(finding) {
|
|
46688
|
+
const lines = [];
|
|
46689
|
+
lines.push(`# PTF-${finding.displayId}: ${sanitizeDisplay(finding.title)}`);
|
|
46690
|
+
lines.push("");
|
|
46691
|
+
lines.push(`- Severity: ${sanitizeDisplay(finding.severity)}`);
|
|
46692
|
+
lines.push(`- Status: ${sanitizeDisplay(finding.status)}`);
|
|
46693
|
+
lines.push(`- Category: ${sanitizeDisplay(finding.category)}`);
|
|
46694
|
+
if (finding.cweIds.length > 0) {
|
|
46695
|
+
lines.push(`- CWE: ${finding.cweIds.map(sanitizeDisplay).join(", ")}`);
|
|
46696
|
+
}
|
|
46697
|
+
if (finding.owaspCategory) {
|
|
46698
|
+
lines.push(`- OWASP: ${sanitizeDisplay(finding.owaspCategory)}`);
|
|
46699
|
+
}
|
|
46700
|
+
if (finding.cvssScore !== null || finding.cvssVector) {
|
|
46701
|
+
const parts = [
|
|
46702
|
+
finding.cvssScore !== null ? String(finding.cvssScore) : null,
|
|
46703
|
+
finding.cvssVector === null ? null : sanitizeDisplay(finding.cvssVector)
|
|
46704
|
+
].filter((part) => part !== null);
|
|
46705
|
+
lines.push(`- CVSS: ${parts.join(" ")}`);
|
|
46706
|
+
}
|
|
46707
|
+
if (finding.repositories.length > 0) {
|
|
46708
|
+
lines.push("");
|
|
46709
|
+
lines.push("## Affected Code");
|
|
46710
|
+
lines.push("");
|
|
46711
|
+
for (const repository of finding.repositories) {
|
|
46712
|
+
const repositoryName = sanitizeDisplay(repository.repositoryName);
|
|
46713
|
+
const filePath = repository.filePath === null ? null : sanitizeDisplay(repository.filePath);
|
|
46714
|
+
const location = filePath === null ? repositoryName : `${repositoryName}: ${filePath}${repository.startLine === null ? "" : `:${repository.startLine}${repository.endLine !== null && repository.endLine !== repository.startLine ? `-${repository.endLine}` : ""}`}`;
|
|
46715
|
+
const commitSha = repository.commitSha === null ? null : sanitizeDisplay(repository.commitSha).slice(0, 12);
|
|
46716
|
+
lines.push(`- ${location}${commitSha ? ` (commit ${commitSha})` : ""}`);
|
|
46717
|
+
}
|
|
46718
|
+
}
|
|
46719
|
+
for (const section of PROSE_SECTIONS) {
|
|
46720
|
+
const body = finding[section.key];
|
|
46721
|
+
if (!body) continue;
|
|
46722
|
+
lines.push("");
|
|
46723
|
+
lines.push(`## ${section.heading}`);
|
|
46724
|
+
lines.push("");
|
|
46725
|
+
lines.push(sanitizeMarkdown(body.trim()));
|
|
46726
|
+
}
|
|
46727
|
+
lines.push("");
|
|
46728
|
+
return lines.join("\n");
|
|
46729
|
+
}
|
|
46730
|
+
function failGetFinding(status, body) {
|
|
46731
|
+
const { message } = readErrorFields(body);
|
|
46732
|
+
if (status === UNAUTHORIZED_STATUS2) {
|
|
46733
|
+
exitAuthFailed();
|
|
46734
|
+
}
|
|
46735
|
+
if (status === 404) {
|
|
46736
|
+
console.error(colorError(message ?? "Pentest or finding not found."));
|
|
46737
|
+
process.exit(1);
|
|
46738
|
+
}
|
|
46739
|
+
if (status === 403) {
|
|
46740
|
+
console.error(colorError(message ?? "You do not have access to this finding (status 403)."));
|
|
46741
|
+
process.exit(1);
|
|
46742
|
+
}
|
|
46743
|
+
console.error(
|
|
46744
|
+
colorError(`Failed to fetch finding (status ${status})${message ? `: ${message}` : "."}`)
|
|
46745
|
+
);
|
|
46746
|
+
process.exit(1);
|
|
46747
|
+
}
|
|
46748
|
+
async function runGetFinding(options) {
|
|
46749
|
+
if (!isOutputFormat2(options.output)) {
|
|
46750
|
+
console.error(
|
|
46751
|
+
colorError(`Invalid --output '${sanitizeDisplay(options.output)}'. Use text or json.`)
|
|
46752
|
+
);
|
|
46753
|
+
process.exit(1);
|
|
46754
|
+
}
|
|
46755
|
+
if (!isPentestIdentifier(options.pentest)) {
|
|
46756
|
+
console.error(
|
|
46757
|
+
colorError(
|
|
46758
|
+
`Invalid pentest identifier '${sanitizeDisplay(options.pentest)}'. Use a display ID (e.g. PT-3) or UUID.`
|
|
46759
|
+
)
|
|
46760
|
+
);
|
|
46761
|
+
process.exit(1);
|
|
46762
|
+
}
|
|
46763
|
+
if (!isFindingIdentifier(options.finding)) {
|
|
46764
|
+
console.error(
|
|
46765
|
+
colorError(
|
|
46766
|
+
`Invalid finding identifier '${sanitizeDisplay(options.finding)}'. Use a finding number (e.g. PTF-7) or UUID.`
|
|
46767
|
+
)
|
|
46768
|
+
);
|
|
46769
|
+
process.exit(1);
|
|
46770
|
+
}
|
|
46771
|
+
const organizationId = await resolveOrganizationId();
|
|
46772
|
+
const result = await authenticatedRequest(
|
|
46773
|
+
(client) => client.pentestFinding.getCustomerFinding({
|
|
46774
|
+
params: {
|
|
46775
|
+
organizationId,
|
|
46776
|
+
pentestId: options.pentest,
|
|
46777
|
+
pentestFindingId: options.finding
|
|
46778
|
+
}
|
|
46779
|
+
})
|
|
46780
|
+
);
|
|
46781
|
+
if (result.status !== 200) {
|
|
46782
|
+
failGetFinding(result.status, result.body);
|
|
46783
|
+
}
|
|
46784
|
+
if (options.output === "json") {
|
|
46785
|
+
console.log(JSON.stringify(result.body, null, 2));
|
|
46786
|
+
return;
|
|
46787
|
+
}
|
|
46788
|
+
process.stdout.write(formatFindingMarkdown(result.body));
|
|
46789
|
+
}
|
|
46790
|
+
function createGetFindingCommand() {
|
|
46791
|
+
return new Command("get").description("Fetch one pentest finding with its full write-up").requiredOption("--pentest <id>", "Pentest display ID (e.g. PT-3) or UUID").requiredOption("--finding <id>", "Finding number (e.g. PTF-7) or UUID").option("-o, --output <format>", "Output format: text (markdown), json (default: text)", "text").addHelpText(
|
|
46792
|
+
"after",
|
|
46793
|
+
`
|
|
46794
|
+
One finding, every section: description, impact, attack scenario, proof of
|
|
46795
|
+
concept, root cause, remediation, severity considerations, and verification,
|
|
46796
|
+
plus the affected repositories and lines. The default output is markdown, ready
|
|
46797
|
+
to paste into a coding agent; --output json returns the API response.
|
|
46798
|
+
|
|
46799
|
+
Examples:
|
|
46800
|
+
tracecli pentest findings get --pentest PT-3 --finding PTF-7
|
|
46801
|
+
tracecli pentest findings get --pentest PT-3 --finding 7 --output json
|
|
46802
|
+
tracecli pentest findings get --pentest PT-3 --finding PTF-7 > finding.md
|
|
46803
|
+
`
|
|
46804
|
+
).action(async (options) => {
|
|
46805
|
+
await runGetFinding(options);
|
|
46806
|
+
});
|
|
46807
|
+
}
|
|
46808
|
+
|
|
46809
|
+
// src/pentest/questionnaire.ts
|
|
46810
|
+
function buildUpsertQuestionnaireBody(answers) {
|
|
46811
|
+
if (answers === null) {
|
|
46812
|
+
return { answers: null };
|
|
46813
|
+
}
|
|
46814
|
+
return { answers: normalizePentestCustomerIntakeAnswers(answers) };
|
|
46815
|
+
}
|
|
46816
|
+
function parseQuestionnaireAnswersFile(raw, sourceLabel = "file") {
|
|
46817
|
+
let parsed;
|
|
46818
|
+
try {
|
|
46819
|
+
parsed = JSON.parse(raw);
|
|
46820
|
+
} catch {
|
|
46821
|
+
return { error: `Invalid JSON in ${sourceLabel}.` };
|
|
46822
|
+
}
|
|
46823
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
46824
|
+
return {
|
|
46825
|
+
error: `${sourceLabel} must be a JSON object of questionnaire answers (not an array or null).`
|
|
46826
|
+
};
|
|
46827
|
+
}
|
|
46828
|
+
if ("answers" in parsed && Object.keys(parsed).length === 1) {
|
|
46829
|
+
return {
|
|
46830
|
+
error: `${sourceLabel} must contain the answers object directly, not an { answers } wrapper. The CLI wraps it for the API.`
|
|
46831
|
+
};
|
|
46832
|
+
}
|
|
46833
|
+
const result = PentestCustomerIntakeAnswersSchema.safeParse(parsed);
|
|
46834
|
+
if (!result.success) {
|
|
46835
|
+
const issue2 = result.error.issues[0];
|
|
46836
|
+
const path = issue2?.path.length ? issue2.path.join(".") : "answers";
|
|
46837
|
+
const message = issue2?.message ?? "invalid";
|
|
46838
|
+
return { error: `Invalid questionnaire answers in ${sourceLabel}: ${path} \u2014 ${message}` };
|
|
46839
|
+
}
|
|
46840
|
+
return { answers: normalizePentestCustomerIntakeAnswers(result.data) };
|
|
46841
|
+
}
|
|
46842
|
+
function applyTextIntakeAnswer(current, key, input) {
|
|
46843
|
+
const trimmed = input.trim();
|
|
46844
|
+
if (trimmed.length === 0) {
|
|
46845
|
+
return current;
|
|
46846
|
+
}
|
|
46847
|
+
return { ...current, [key]: trimmed };
|
|
46848
|
+
}
|
|
46849
|
+
function applyMultiSelectIntakeAnswer(current, key, selected) {
|
|
46850
|
+
if (selected.length === 0) {
|
|
46851
|
+
return current;
|
|
46852
|
+
}
|
|
46853
|
+
return {
|
|
46854
|
+
...current,
|
|
46855
|
+
[key]: Array.from(new Set(selected)).sort()
|
|
46856
|
+
};
|
|
46857
|
+
}
|
|
46858
|
+
function formatIssueClasses(values) {
|
|
46859
|
+
return values.map((v) => INTAKE_ISSUE_CLASS_LABELS[v]).join(", ");
|
|
46860
|
+
}
|
|
46861
|
+
function formatSurfaces(values) {
|
|
46862
|
+
return values.map((v) => INTAKE_SURFACE_LABELS[v]).join(", ");
|
|
46863
|
+
}
|
|
46864
|
+
function formatAnswerValue(key, answers) {
|
|
46865
|
+
switch (key) {
|
|
46866
|
+
case "issueClasses": {
|
|
46867
|
+
const values = answers.issueClasses;
|
|
46868
|
+
if (values === void 0 || values.length === 0) {
|
|
46869
|
+
return null;
|
|
46870
|
+
}
|
|
46871
|
+
return formatIssueClasses(values);
|
|
46872
|
+
}
|
|
46873
|
+
case "surfaces": {
|
|
46874
|
+
const values = answers.surfaces;
|
|
46875
|
+
if (values === void 0 || values.length === 0) {
|
|
46876
|
+
return null;
|
|
46877
|
+
}
|
|
46878
|
+
return formatSurfaces(values);
|
|
46879
|
+
}
|
|
46880
|
+
default: {
|
|
46881
|
+
const value = answers[key];
|
|
46882
|
+
if (value === void 0 || value.trim().length === 0) {
|
|
46883
|
+
return null;
|
|
46884
|
+
}
|
|
46885
|
+
return value;
|
|
46886
|
+
}
|
|
46887
|
+
}
|
|
46888
|
+
}
|
|
46889
|
+
function formatQuestionnaireShow(input) {
|
|
46890
|
+
const submitted = input.submitted === true;
|
|
46891
|
+
const editableLine = input.editable ? "yes (scoping window open)" : submitted ? "no (submitted)" : "no (editing closed after scoping)";
|
|
46892
|
+
const lines = [`Editable: ${editableLine}`, `Submitted: ${submitted ? "yes" : "no"}`];
|
|
46893
|
+
if (input.answers === null || Object.keys(input.answers).length === 0) {
|
|
46894
|
+
lines.push("Answers: (none)");
|
|
46895
|
+
return lines.join("\n");
|
|
46896
|
+
}
|
|
46897
|
+
lines.push("Answers:");
|
|
46898
|
+
for (const key of PENTEST_CUSTOMER_INTAKE_ANSWER_KEYS) {
|
|
46899
|
+
const value = formatAnswerValue(key, input.answers);
|
|
46900
|
+
if (value === null) {
|
|
46901
|
+
continue;
|
|
46902
|
+
}
|
|
46903
|
+
lines.push(`${PENTEST_CUSTOMER_INTAKE_LABELS[key]}: ${value}`);
|
|
46904
|
+
}
|
|
46905
|
+
return lines.join("\n");
|
|
46906
|
+
}
|
|
46907
|
+
function issueClassSelectOptions() {
|
|
46908
|
+
return CustomerPriorityCategoryValues.map((value) => ({
|
|
46909
|
+
value,
|
|
46910
|
+
label: INTAKE_ISSUE_CLASS_LABELS[value]
|
|
46911
|
+
}));
|
|
46912
|
+
}
|
|
46913
|
+
function surfaceSelectOptions() {
|
|
46914
|
+
return IntakeSurfaceValues.map((value) => ({
|
|
46915
|
+
value,
|
|
46916
|
+
label: INTAKE_SURFACE_LABELS[value]
|
|
46917
|
+
}));
|
|
46918
|
+
}
|
|
46919
|
+
|
|
46780
46920
|
// src/pentest/commands.ts
|
|
46781
46921
|
var DEFAULT_LIMIT2 = 30;
|
|
46782
46922
|
var MAX_LIMIT2 = 100;
|
|
@@ -47147,6 +47287,7 @@ function renderPentestFindingLines(finding) {
|
|
|
47147
47287
|
function createFindingsCommand() {
|
|
47148
47288
|
const findings = new Command("findings").description("Manage pentest findings");
|
|
47149
47289
|
findings.addCommand(createFindingsListCommand());
|
|
47290
|
+
findings.addCommand(createGetFindingCommand());
|
|
47150
47291
|
findings.addCommand(createStatusUpdateCommand());
|
|
47151
47292
|
findings.addCommand(createAttachEvidenceCommand());
|
|
47152
47293
|
findings.addCommand(createCreateFindingCommand(), { hidden: true });
|