@lievclouds/dsh-cortex 0.4.4 → 1.0.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.
Potentially problematic release.
This version of @lievclouds/dsh-cortex might be problematic. Click here for more details.
- package/README.md +1 -1
- package/client.js +428 -406
- package/index.js +7 -0
- package/locale/en.json +6 -6
- package/locale/zh.json +6 -6
- package/package.json +115 -106
- package/src/cortex-ui/dsh/api.ts +5 -2
- package/src/cortex-ui/dsh/css-overrides.css +8 -0
- package/src/cortex-ui/renderer/App.tsx +39 -0
- package/src/cortex-ui/renderer/components/asset/AssetDetail.tsx +9 -1
- package/src/cortex-ui/renderer/components/miniapp/FileTree.tsx +161 -0
- package/src/cortex-ui/renderer/components/miniapp/MiniappCard.tsx +263 -0
- package/src/cortex-ui/renderer/components/miniapp/MiniappDetail.tsx +1493 -0
- package/src/cortex-ui/renderer/components/retest/CurlImportDialog.tsx +158 -0
- package/src/cortex-ui/renderer/components/retest/RepeaterCollectionsDialog.tsx +327 -0
- package/src/cortex-ui/renderer/components/retest/RepeaterHistoryDialog.tsx +242 -0
- package/src/cortex-ui/renderer/components/retest/RepeaterPanel.tsx +333 -148
- package/src/cortex-ui/renderer/components/retest/YakitSendPanel.tsx +411 -0
- package/src/cortex-ui/renderer/components/vuln/DirectoryPickerDialog.tsx +187 -0
- package/src/cortex-ui/renderer/components/vuln/ExportReportDialog.tsx +173 -59
- package/src/cortex-ui/renderer/components/vuln/VulnDetail.tsx +16 -4
- package/src/cortex-ui/renderer/i18n/messages/common.ts +2 -0
- package/src/cortex-ui/renderer/i18n/messages/fuzzer.ts +32 -0
- package/src/cortex-ui/renderer/i18n/messages/index.ts +5 -1
- package/src/cortex-ui/renderer/i18n/messages/miniapp.ts +392 -0
- package/src/cortex-ui/renderer/i18n/messages/retest.ts +146 -2
- package/src/cortex-ui/renderer/i18n/messages/vuln.ts +26 -6
- package/src/cortex-ui/renderer/lib/curl.ts +635 -0
- package/src/cortex-ui/renderer/lib/miniappApi.ts +459 -0
- package/src/cortex-ui/renderer/lib/navigation.ts +13 -1
- package/src/cortex-ui/renderer/lib/repeaterRaw.ts +102 -0
- package/src/cortex-ui/renderer/lib/repeaterStoreApi.ts +163 -0
- package/src/cortex-ui/renderer/lib/retestResponse.ts +64 -0
- package/src/cortex-ui/renderer/lib/transport/httpClient.ts +1 -1
- package/src/cortex-ui/renderer/pages/DashboardPage.tsx +3 -3
- package/src/cortex-ui/renderer/pages/FuzzerPage.tsx +212 -0
- package/src/cortex-ui/renderer/pages/MiniappPage.tsx +664 -0
- package/src/cortex-ui/shared/ipc.ts +3 -4
- package/src/cortex-ui/shared/types.ts +9 -0
- package/src/host/cortex/fs.js +72 -0
- package/src/host/cortex/index.js +49 -1
- package/src/host/cortex/repeater-store.js +411 -0
- package/src/host/cortex/repeater.js +15 -2
- package/src/host/cortex/settings.js +54 -0
- package/src/host/cortex/tools.js +2 -0
- package/src/host/cortex/vulns.js +36 -13
- package/src/host/miniapp/analyze.js +1078 -0
- package/src/host/miniapp/assets-import.js +294 -0
- package/src/host/miniapp/detect.js +426 -0
- package/src/host/miniapp/format.js +263 -0
- package/src/host/miniapp/roots.js +360 -0
- package/src/host/miniapp/routes.js +304 -0
- package/src/host/miniapp/service.js +559 -0
- package/src/host/miniapp/store.js +756 -0
- package/src/host/miniapp/tools.js +335 -0
- package/src/host/miniapp/unpack.js +1010 -0
- package/src/host/miniapp/wxapkg.js +416 -0
- package/src/host/reports-office.js +341 -0
package/src/host/cortex/vulns.js
CHANGED
|
@@ -34,6 +34,8 @@ import {
|
|
|
34
34
|
} from '../http.js'
|
|
35
35
|
import * as dto from '../dto.js'
|
|
36
36
|
import { buildVulnReport, reportFilename } from '../reports.js'
|
|
37
|
+
import { renderDocxReport, renderPdfReport } from '../reports-office.js'
|
|
38
|
+
import { rememberExportDir } from './settings.js'
|
|
37
39
|
import { mkdirSync, writeFileSync } from 'node:fs'
|
|
38
40
|
import { homedir } from 'node:os'
|
|
39
41
|
import { isAbsolute, join, resolve } from 'node:path'
|
|
@@ -49,6 +51,7 @@ const MAX_ID_LENGTH = 100
|
|
|
49
51
|
const MAX_BULK_IDS = 500
|
|
50
52
|
const MAX_HOST_FILTER = 255
|
|
51
53
|
const MAX_EXPORT_IDS = 200
|
|
54
|
+
const EXPORT_FORMATS = ['md', 'docx', 'pdf']
|
|
52
55
|
|
|
53
56
|
const VULN_ORDER = 'ORDER BY created_at DESC, rowid DESC'
|
|
54
57
|
|
|
@@ -499,6 +502,11 @@ export async function handleDeleteMany({ req, res, holder, bumpRev }) {
|
|
|
499
502
|
export async function handleExport({ req, res, holder, bumpRev }) {
|
|
500
503
|
const body = await readJsonBody(req)
|
|
501
504
|
const ids = requireIdList(body, 'ids', MAX_EXPORT_IDS)
|
|
505
|
+
/** Report format: Markdown by default; Word/PDF are generated Host-side. */
|
|
506
|
+
const format = body.format === undefined ? 'md' : String(body.format).trim().toLowerCase()
|
|
507
|
+
if (!EXPORT_FORMATS.includes(format)) {
|
|
508
|
+
throw badRequest('format must be md, docx or pdf', { field: 'format' })
|
|
509
|
+
}
|
|
502
510
|
/** Optional user-selected output directory (absolute path, `~` allowed). */
|
|
503
511
|
let requestedDir
|
|
504
512
|
if (body.outputDir !== undefined) {
|
|
@@ -542,16 +550,24 @@ export async function handleExport({ req, res, holder, bumpRev }) {
|
|
|
542
550
|
targetUrl: item.target_url,
|
|
543
551
|
host: item.host,
|
|
544
552
|
}))
|
|
545
|
-
|
|
546
|
-
id,
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
553
|
+
const baseName = reportFilename(
|
|
554
|
+
row.vuln_name && /^[\x20-\x7e]+$/.test(String(row.vuln_name)) ? String(row.vuln_name) : id,
|
|
555
|
+
).replace(/\.md$/, '')
|
|
556
|
+
const markdown = buildVulnReport(detail, related)
|
|
557
|
+
const title = String(row.vuln_name || id)
|
|
558
|
+
if (format === 'md') {
|
|
559
|
+
files.push({ id, filename: `${baseName}.md`, content: markdown })
|
|
560
|
+
continue
|
|
561
|
+
}
|
|
562
|
+
const buffer =
|
|
563
|
+
format === 'docx'
|
|
564
|
+
? await renderDocxReport(markdown, { title })
|
|
565
|
+
: await renderPdfReport(markdown, { title })
|
|
566
|
+
files.push({ id, filename: `${baseName}.${format}`, format, buffer })
|
|
550
567
|
}
|
|
551
568
|
// The DSH desktop WebView may block browser downloads, so the Host also
|
|
552
|
-
// writes the
|
|
553
|
-
// the absolute paths. The
|
|
554
|
-
// toast can then point at a real file that always exists.
|
|
569
|
+
// writes the reports to the selected directory (or ~/.cortex/exports/<stamp>)
|
|
570
|
+
// and returns the absolute paths. The toast then points at a real file.
|
|
555
571
|
const savedPaths = []
|
|
556
572
|
if (files.length > 0) {
|
|
557
573
|
try {
|
|
@@ -566,14 +582,15 @@ export async function handleExport({ req, res, holder, bumpRev }) {
|
|
|
566
582
|
for (let index = 0; index < files.length; index += 1) {
|
|
567
583
|
const file = files[index]
|
|
568
584
|
const safeName = String(file.filename).replace(/[<>:"/\\|?*\u0000-\u001f]/g, '_').slice(0, 120) || file.id
|
|
569
|
-
const
|
|
570
|
-
|
|
571
|
-
writeFileSync(target, file.content, 'utf8')
|
|
585
|
+
const target = join(exportDir, files.length > 1 ? `${String(index + 1).padStart(2, '0')}-${safeName}` : safeName)
|
|
586
|
+
writeFileSync(target, file.buffer ?? file.content, file.buffer ? undefined : 'utf8')
|
|
572
587
|
savedPaths.push(target)
|
|
573
588
|
}
|
|
589
|
+
// Remember the directory the user explicitly chose for the next export.
|
|
590
|
+
if (requestedDir !== undefined) rememberExportDir(exportDir)
|
|
574
591
|
} catch (error) {
|
|
575
592
|
// Filesystem failure must not break the export response; the inline
|
|
576
|
-
//
|
|
593
|
+
// Markdown still lets the browser download attempt proceed. A selected
|
|
577
594
|
// directory failure is reported so the user can correct the path.
|
|
578
595
|
if (requestedDir !== undefined) {
|
|
579
596
|
throw badRequest(`cannot write to outputDir: ${error instanceof Error ? error.message : String(error)}`, {
|
|
@@ -582,9 +599,15 @@ export async function handleExport({ req, res, holder, bumpRev }) {
|
|
|
582
599
|
}
|
|
583
600
|
}
|
|
584
601
|
}
|
|
602
|
+
// Binary formats carry no inline body: the saved file is the deliverable.
|
|
603
|
+
const responseFiles = files.map((file) =>
|
|
604
|
+
file.buffer
|
|
605
|
+
? { id: file.id, filename: file.filename, format: file.format, size: file.buffer.length }
|
|
606
|
+
: { id: file.id, filename: file.filename, content: file.content },
|
|
607
|
+
)
|
|
585
608
|
// Export is a read-only projection: no revision bump.
|
|
586
609
|
void bumpRev
|
|
587
|
-
sendJson(res, 200, { cancelled: files.length === 0, files, savedPaths })
|
|
610
|
+
sendJson(res, 200, { cancelled: files.length === 0, files: responseFiles, savedPaths })
|
|
588
611
|
}
|
|
589
612
|
|
|
590
613
|
export { SEVERITIES, STATUSES, REALM_FILTERS, VULN_ORDER }
|