weavatrix 0.3.6 → 0.3.7
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.
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Weavatrix 0.3.7
|
|
2
|
+
|
|
3
|
+
0.3.7 fixes three defects surfaced by cross-repository validation: a
|
|
4
|
+
reverse-shell detection gap, an unbounded ripgrep-path probe that could hang the
|
|
5
|
+
server, and a `search_code` path that excluded `node_modules` only through the
|
|
6
|
+
gitignore stack.
|
|
7
|
+
|
|
8
|
+
## Reverse-shell pre-filter now covers the confirming regex
|
|
9
|
+
|
|
10
|
+
The malware content sweep uses each rule's `pattern` as the ripgrep pre-filter
|
|
11
|
+
and only then applies the stricter `re` to confirm. The reverse-shell `pattern`
|
|
12
|
+
had drifted narrower than its `re`: it required `SOCK_STREAM` followed by
|
|
13
|
+
`/bin/sh` or `exec`, so socket-backed shells using `connect`, `subprocess`,
|
|
14
|
+
`pty.spawn` or `os.dup2` — and default `socket.socket()` calls with no
|
|
15
|
+
`SOCK_STREAM` literal — were dropped before they could be confirmed. The
|
|
16
|
+
pre-filter is now a superset of the confirming regex, and a new invariant test
|
|
17
|
+
asserts that every payload the confirming regex flags is also surfaced by the
|
|
18
|
+
pre-filter.
|
|
19
|
+
|
|
20
|
+
A separate, deeper case is deliberately left for a follow-up: multi-line reverse
|
|
21
|
+
shells, where ripgrep's per-line matching cannot span a `socket` call and the
|
|
22
|
+
shell invocation on different lines.
|
|
23
|
+
|
|
24
|
+
## Bounded ripgrep-path probe
|
|
25
|
+
|
|
26
|
+
The `where`/`which rg` fallback in the MCP ripgrep resolver ran `spawnSync`
|
|
27
|
+
without a timeout on the main thread, so a slow or unreachable PATH entry (for
|
|
28
|
+
example a disconnected network drive) could hang the server. The probe now runs
|
|
29
|
+
with a three-second timeout and `windowsHide`.
|
|
30
|
+
|
|
31
|
+
## search_code excludes node_modules explicitly
|
|
32
|
+
|
|
33
|
+
The `search_code` ripgrep invocation passed `--hidden` with only a `.git`
|
|
34
|
+
exclusion, leaving `node_modules` out of results solely through ripgrep's
|
|
35
|
+
implicit gitignore stack — which fails for repositories that commit their
|
|
36
|
+
dependency tree or lack a gitignore. An explicit `!node_modules` glob is now
|
|
37
|
+
applied; a caller-supplied glob is still appended afterward and wins.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "weavatrix",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Local repository intelligence MCP for AI coding agents: reusable architecture graph for fast application understanding, Health, dead code, clones, history, blast radius and architecture safeguards.",
|
|
6
6
|
"author": "Sergii Ziborov <sergii.ziborov@gmail.com>",
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"docs/releases/v0.3.4.md",
|
|
41
41
|
"docs/releases/v0.3.5.md",
|
|
42
42
|
"docs/releases/v0.3.6.md",
|
|
43
|
+
"docs/releases/v0.3.7.md",
|
|
43
44
|
"docs/releases/v0.2.19.md",
|
|
44
45
|
"README.md",
|
|
45
46
|
"SECURITY.md",
|
package/src/mcp-rg.mjs
CHANGED
|
@@ -43,7 +43,7 @@ export function createRgResolver(selfDir) {
|
|
|
43
43
|
} catch { /* optional packaged ripgrep path */ }
|
|
44
44
|
for (const c of editorRgCandidates()) if (existsSync(c)) return (rgPath = c)
|
|
45
45
|
try {
|
|
46
|
-
const probe = spawnSync(process.platform === 'win32' ? 'where' : 'which', ['rg'], {encoding: 'utf8', env: childProcessEnv()})
|
|
46
|
+
const probe = spawnSync(process.platform === 'win32' ? 'where' : 'which', ['rg'], {encoding: 'utf8', env: childProcessEnv(), timeout: 3000, windowsHide: true})
|
|
47
47
|
const p = probe.status === 0 ? probe.stdout.split(/\r?\n/)[0].trim() : ''
|
|
48
48
|
if (p && existsSync(p)) return (rgPath = p)
|
|
49
49
|
} catch { /* optional PATH probe */ }
|
package/src/mcp-source-tools.mjs
CHANGED
|
@@ -14,7 +14,10 @@ const MAX_SOURCE_CONTEXT_LINES = 1000
|
|
|
14
14
|
function rgSearch(repoRoot, resolveRg, query, { isRegex, glob, maxResults }, spawnRg = spawnSync) {
|
|
15
15
|
const rg = resolveRg()
|
|
16
16
|
if (!rg) return null
|
|
17
|
-
|
|
17
|
+
// Exclude node_modules explicitly: --hidden + the default gitignore stack is the only thing that
|
|
18
|
+
// keeps a dependency tree out, which fails for repos that commit node_modules or lack a gitignore.
|
|
19
|
+
// A caller-supplied glob is appended after this and still wins (rg: last matching glob decides).
|
|
20
|
+
const args = ['--line-number', '--no-heading', '--color', 'never', '--hidden', '-g', '!.git/**', '-g', '!node_modules', '-m', '100', '-i']
|
|
18
21
|
if (!isRegex) args.push('--fixed-strings')
|
|
19
22
|
if (glob) args.push('-g', glob)
|
|
20
23
|
// Run from the repository root and search `.` so path globs such as `src/**` are evaluated
|
|
@@ -35,7 +35,10 @@ export const CONTENT_RULES = [
|
|
|
35
35
|
nearZeroFp: true,
|
|
36
36
|
// canonical reverse/bind shells — a shell wired to a socket. Essentially never legitimate inside a
|
|
37
37
|
// published package: /dev/tcp redirection, netcat -e, interactive-shell redirect, mkfifo pipe shell.
|
|
38
|
-
|
|
38
|
+
// The rg pre-filter must stay a superset of `re` below: rg surfaces lines matching this string and
|
|
39
|
+
// only then is `re` applied to confirm, so a narrower pre-filter silently drops real reverse shells
|
|
40
|
+
// (e.g. socket + pty.spawn / os.dup2 / subprocess, or a default socket.socket() without SOCK_STREAM).
|
|
41
|
+
pattern: "/dev/tcp/[0-9]|\\bnc(at)?\\s+-e\\b|\\b(ba)?sh\\s+-i\\b\\s*(2)?>&|mkfifo\\b.{0,60}(ba)?sh\\b|0<&196|socket\\.socket\\(.{0,120}(connect|SOCK_STREAM).{0,180}(/bin/sh|subprocess|pty\\.spawn|os\\.dup2)",
|
|
39
42
|
re: /\/dev\/tcp\/[0-9]|\bnc(at)?\s+-e\b|\b(ba)?sh\s+-i\b\s*(2)?>&|mkfifo\b[\s\S]{0,60}?\b(ba)?sh\b|0<&196|socket\.socket\([\s\S]{0,120}?(connect|SOCK_STREAM)[\s\S]{0,180}?(\/bin\/sh|subprocess|pty\.spawn|os\.dup2)/i,
|
|
40
43
|
what: "reverse/bind-shell pattern (interactive shell wired to a socket)",
|
|
41
44
|
},
|