@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.

Files changed (58) hide show
  1. package/README.md +1 -1
  2. package/client.js +428 -406
  3. package/index.js +7 -0
  4. package/locale/en.json +6 -6
  5. package/locale/zh.json +6 -6
  6. package/package.json +115 -106
  7. package/src/cortex-ui/dsh/api.ts +5 -2
  8. package/src/cortex-ui/dsh/css-overrides.css +8 -0
  9. package/src/cortex-ui/renderer/App.tsx +39 -0
  10. package/src/cortex-ui/renderer/components/asset/AssetDetail.tsx +9 -1
  11. package/src/cortex-ui/renderer/components/miniapp/FileTree.tsx +161 -0
  12. package/src/cortex-ui/renderer/components/miniapp/MiniappCard.tsx +263 -0
  13. package/src/cortex-ui/renderer/components/miniapp/MiniappDetail.tsx +1493 -0
  14. package/src/cortex-ui/renderer/components/retest/CurlImportDialog.tsx +158 -0
  15. package/src/cortex-ui/renderer/components/retest/RepeaterCollectionsDialog.tsx +327 -0
  16. package/src/cortex-ui/renderer/components/retest/RepeaterHistoryDialog.tsx +242 -0
  17. package/src/cortex-ui/renderer/components/retest/RepeaterPanel.tsx +333 -148
  18. package/src/cortex-ui/renderer/components/retest/YakitSendPanel.tsx +411 -0
  19. package/src/cortex-ui/renderer/components/vuln/DirectoryPickerDialog.tsx +187 -0
  20. package/src/cortex-ui/renderer/components/vuln/ExportReportDialog.tsx +173 -59
  21. package/src/cortex-ui/renderer/components/vuln/VulnDetail.tsx +16 -4
  22. package/src/cortex-ui/renderer/i18n/messages/common.ts +2 -0
  23. package/src/cortex-ui/renderer/i18n/messages/fuzzer.ts +32 -0
  24. package/src/cortex-ui/renderer/i18n/messages/index.ts +5 -1
  25. package/src/cortex-ui/renderer/i18n/messages/miniapp.ts +392 -0
  26. package/src/cortex-ui/renderer/i18n/messages/retest.ts +146 -2
  27. package/src/cortex-ui/renderer/i18n/messages/vuln.ts +26 -6
  28. package/src/cortex-ui/renderer/lib/curl.ts +635 -0
  29. package/src/cortex-ui/renderer/lib/miniappApi.ts +459 -0
  30. package/src/cortex-ui/renderer/lib/navigation.ts +13 -1
  31. package/src/cortex-ui/renderer/lib/repeaterRaw.ts +102 -0
  32. package/src/cortex-ui/renderer/lib/repeaterStoreApi.ts +163 -0
  33. package/src/cortex-ui/renderer/lib/retestResponse.ts +64 -0
  34. package/src/cortex-ui/renderer/lib/transport/httpClient.ts +1 -1
  35. package/src/cortex-ui/renderer/pages/DashboardPage.tsx +3 -3
  36. package/src/cortex-ui/renderer/pages/FuzzerPage.tsx +212 -0
  37. package/src/cortex-ui/renderer/pages/MiniappPage.tsx +664 -0
  38. package/src/cortex-ui/shared/ipc.ts +3 -4
  39. package/src/cortex-ui/shared/types.ts +9 -0
  40. package/src/host/cortex/fs.js +72 -0
  41. package/src/host/cortex/index.js +49 -1
  42. package/src/host/cortex/repeater-store.js +411 -0
  43. package/src/host/cortex/repeater.js +15 -2
  44. package/src/host/cortex/settings.js +54 -0
  45. package/src/host/cortex/tools.js +2 -0
  46. package/src/host/cortex/vulns.js +36 -13
  47. package/src/host/miniapp/analyze.js +1078 -0
  48. package/src/host/miniapp/assets-import.js +294 -0
  49. package/src/host/miniapp/detect.js +426 -0
  50. package/src/host/miniapp/format.js +263 -0
  51. package/src/host/miniapp/roots.js +360 -0
  52. package/src/host/miniapp/routes.js +304 -0
  53. package/src/host/miniapp/service.js +559 -0
  54. package/src/host/miniapp/store.js +756 -0
  55. package/src/host/miniapp/tools.js +335 -0
  56. package/src/host/miniapp/unpack.js +1010 -0
  57. package/src/host/miniapp/wxapkg.js +416 -0
  58. package/src/host/reports-office.js +341 -0
@@ -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
- files.push({
546
- id,
547
- filename: reportFilename(row.vuln_name && /^[\x20-\x7e]+$/.test(String(row.vuln_name)) ? String(row.vuln_name) : id),
548
- content: buildVulnReport(detail, related),
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 Markdown reports to ~/.cortex/exports/<timestamp>/ and returns
553
- // the absolute paths. The renderer still attempts a normal download, but 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 baseName = safeName.endsWith('.md') ? safeName : `${safeName}.md`
570
- const target = join(exportDir, files.length > 1 ? `${String(index + 1).padStart(2, '0')}-${baseName}` : baseName)
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
- // files still let the browser download attempt proceed. A selected
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 }