@lievclouds/dsh-cortex 0.4.3 → 0.4.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.

Potentially problematic release.


This version of @lievclouds/dsh-cortex might be problematic. Click here for more details.

package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lievclouds/dsh-cortex",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "description": "Cortex workbench for DeepSeek Harness: the original Cortex UI (vulnerabilities, assets, internal operations, Memory Nebula, snapshots, retest) as a native DSH panel, plus 12 native agent tools so DSH conversations use the local Cortex SQLite without MCP.",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -24,6 +24,21 @@ interface ParsedRawRequest {
24
24
  body: string
25
25
  }
26
26
 
27
+ /**
28
+ * Protocol-level headers copied from a report are re-derived by the outbound
29
+ * request (Host from the URL, length/connection by the HTTP client). Dropping
30
+ * them here keeps raw requests sendable without a validation error.
31
+ */
32
+ const DERIVED_HEADERS = new Set([
33
+ 'host',
34
+ 'content-length',
35
+ 'connection',
36
+ 'transfer-encoding',
37
+ 'upgrade',
38
+ 'keep-alive',
39
+ 'proxy-connection'
40
+ ])
41
+
27
42
  /** Parse a Burp-like raw request into the typed repeater payload. */
28
43
  function parseRawRequest(text: string): ParsedRawRequest {
29
44
  const lines = text.replace(/\r\n/g, '\n').split('\n')
@@ -157,11 +172,14 @@ export function RepeaterPanel({ vuln, loading }: RepeaterPanelProps) {
157
172
  setError(null)
158
173
  try {
159
174
  const parsed = parseRawRequest(raw)
175
+ const headers = Object.fromEntries(
176
+ Object.entries(parsed.headers).filter(([name]) => !DERIVED_HEADERS.has(name.toLowerCase()))
177
+ )
160
178
  const response = await api.sendRepeaterRequest({
161
179
  vulnId: vuln.id,
162
180
  method: parsed.method,
163
181
  url: resolveRepeaterUrl(parsed.url, vuln.target_url),
164
- headers: parsed.headers,
182
+ headers,
165
183
  ...(parsed.body === '' ? {} : { body: parsed.body }),
166
184
  followRedirects
167
185
  })
@@ -29,7 +29,6 @@ export const MAX_HEADER_VALUE = 8000
29
29
 
30
30
  /** Headers a retest caller may never set (they are protocol-level). */
31
31
  const FORBIDDEN_HEADERS = new Set([
32
- 'host',
33
32
  'content-length',
34
33
  'connection',
35
34
  'transfer-encoding',
@@ -38,6 +37,14 @@ const FORBIDDEN_HEADERS = new Set([
38
37
  'proxy-connection',
39
38
  ])
40
39
 
40
+ /**
41
+ * Headers that are silently ignored instead of rejected: `Host` is derived
42
+ * from the already-validated request URL, so a raw request copied from a report
43
+ * (`Host: target`) must not fail validation. Letting callers override Host
44
+ * would allow vhost tricks outside the origin allowlist.
45
+ */
46
+ const IGNORED_HEADERS = new Set(['host'])
47
+
41
48
  const HEADER_NAME_RE = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/
42
49
 
43
50
  const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308])
@@ -152,6 +159,7 @@ export function normalizeHeaders(headers) {
152
159
  if (FORBIDDEN_HEADERS.has(name.toLowerCase())) {
153
160
  throw badRequest(`header ${name} is not allowed`)
154
161
  }
162
+ if (IGNORED_HEADERS.has(name.toLowerCase())) continue
155
163
  if (/[\r\n]/.test(value)) throw badRequest(`header ${name} has an invalid value`)
156
164
  if (value.length > MAX_HEADER_VALUE) throw badRequest(`header ${name} is too long`)
157
165
  out[name] = value