dsh-install-radar 1.0.0 → 1.0.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-install-radar",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Per-session install radar for DeepSeek Harness: what each conversation installed (Python / npm / git / winget), with size, path, created time, purpose, why it was installed and what removing it costs — plus a sidebar panel and process→disk causal audit.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -10,6 +10,17 @@ import { execFile } from 'node:child_process'
10
10
  import { appendFile, mkdir, readFile, writeFile } from 'node:fs/promises'
11
11
  import { join } from 'node:path'
12
12
 
13
+ /** 把命令行里的密钥类片段打码,避免审计日志变成泄密文件 */
14
+ export function redact(text) {
15
+ if (typeof text !== 'string' || text.length === 0) return ''
16
+ return text
17
+ .replace(/\b(ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{8,}\b/g, '$1_[REDACTED]')
18
+ .replace(/\bnpm_[A-Za-z0-9]{8,}\b/g, 'npm_[REDACTED]')
19
+ .replace(/\b(sk|pk|rk)-[A-Za-z0-9_-]{8,}\b/g, '$1-[REDACTED]')
20
+ .replace(/(_authToken=|_auth=|--otp=|token=)([^\s"'&]+)/gi, '$1[REDACTED]')
21
+ .replace(/\b(Bearer|Basic)\s+[A-Za-z0-9._~+/=-]{12,}/g, '$1 [REDACTED]')
22
+ }
23
+
13
24
  /** 类别 → 命令行特征 */
14
25
  const PATTERNS = [
15
26
  { key: 'cdp', re: /--remote-debugging-(port|pipe)/i, label: 'CDP 调试端口' },
@@ -106,7 +117,7 @@ export async function findWatchedProcesses() {
106
117
  const chain = []
107
118
  let cursor = byPid.get(proc.ppid)
108
119
  for (let depth = 0; cursor && depth < 4; depth++) {
109
- chain.push({ pid: cursor.pid, name: cursor.name, command: cursor.command.slice(0, 400) })
120
+ chain.push({ pid: cursor.pid, name: cursor.name, command: redact(cursor.command).slice(0, 400) })
110
121
  cursor = byPid.get(cursor.ppid)
111
122
  }
112
123
  const dataDir = /--user-data-dir=("[^"]+"|\S+)/i.exec(proc.command)
@@ -114,7 +125,7 @@ export async function findWatchedProcesses() {
114
125
  hits.push({
115
126
  pid: proc.pid,
116
127
  name: proc.name,
117
- command: proc.command.slice(0, 600),
128
+ command: redact(proc.command).slice(0, 600),
118
129
  categories,
119
130
  userDataDir: dataDir ? dataDir[1].replace(/^["']|["']*$/g, '') : '',
120
131
  port: port ? Number(port[1]) : null,
@@ -164,7 +175,7 @@ export async function sampleWatchedProcesses({ home }) {
164
175
  label: category.label,
165
176
  pid: hit.pid,
166
177
  name: hit.name,
167
- command: hit.command,
178
+ command: redact(hit.command),
168
179
  paths: hit.paths,
169
180
  userDataDir: hit.userDataDir,
170
181
  startedAt: hit.startedAt,
@@ -231,7 +242,7 @@ export async function readProcWatch({ home, limit = 200 }) {
231
242
  bucket.lastAt = Math.max(bucket.lastAt, record.at || 0)
232
243
  for (const path of item.paths || []) bucket.paths.add(path)
233
244
  if (item.userDataDir) bucket.paths.add(item.userDataDir)
234
- if (bucket.samples.length < 2) bucket.samples.push(item.command.slice(0, 160))
245
+ if (bucket.samples.length < 2) bucket.samples.push(redact(item.command).slice(0, 160))
235
246
  rows.set(key, bucket)
236
247
 
237
248
  const cat = byCategory.get(item.category) || { category: item.category, label: item.label, count: 0 }