dravix-agent 0.1.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.
Files changed (208) hide show
  1. package/.claude/settings.example.json +30 -0
  2. package/ARCHITECTURE.md +410 -0
  3. package/LICENSE +21 -0
  4. package/README.md +153 -0
  5. package/ROADMAP.md +117 -0
  6. package/data/vulnkb.json +666 -0
  7. package/dist/bin/aegis.d.ts +3 -0
  8. package/dist/bin/aegis.d.ts.map +1 -0
  9. package/dist/bin/aegis.js +489 -0
  10. package/dist/bin/aegis.js.map +1 -0
  11. package/dist/cache.d.ts +9 -0
  12. package/dist/cache.d.ts.map +1 -0
  13. package/dist/cache.js +146 -0
  14. package/dist/cache.js.map +1 -0
  15. package/dist/engines/ai-sinks.d.ts +52 -0
  16. package/dist/engines/ai-sinks.d.ts.map +1 -0
  17. package/dist/engines/ai-sinks.js +204 -0
  18. package/dist/engines/ai-sinks.js.map +1 -0
  19. package/dist/engines/eslint.d.ts +9 -0
  20. package/dist/engines/eslint.d.ts.map +1 -0
  21. package/dist/engines/eslint.js +245 -0
  22. package/dist/engines/eslint.js.map +1 -0
  23. package/dist/engines/joern.d.ts +3 -0
  24. package/dist/engines/joern.d.ts.map +1 -0
  25. package/dist/engines/joern.js +98 -0
  26. package/dist/engines/joern.js.map +1 -0
  27. package/dist/engines/js-sinks.d.ts +70 -0
  28. package/dist/engines/js-sinks.d.ts.map +1 -0
  29. package/dist/engines/js-sinks.js +370 -0
  30. package/dist/engines/js-sinks.js.map +1 -0
  31. package/dist/engines/llm-critic.d.ts +130 -0
  32. package/dist/engines/llm-critic.d.ts.map +1 -0
  33. package/dist/engines/llm-critic.js +551 -0
  34. package/dist/engines/llm-critic.js.map +1 -0
  35. package/dist/engines/pragma.d.ts +20 -0
  36. package/dist/engines/pragma.d.ts.map +1 -0
  37. package/dist/engines/pragma.js +83 -0
  38. package/dist/engines/pragma.js.map +1 -0
  39. package/dist/engines/property-test.d.ts +3 -0
  40. package/dist/engines/property-test.d.ts.map +1 -0
  41. package/dist/engines/property-test.js +134 -0
  42. package/dist/engines/property-test.js.map +1 -0
  43. package/dist/engines/pyright.d.ts +10 -0
  44. package/dist/engines/pyright.d.ts.map +1 -0
  45. package/dist/engines/pyright.js +143 -0
  46. package/dist/engines/pyright.js.map +1 -0
  47. package/dist/engines/pysa.d.ts +3 -0
  48. package/dist/engines/pysa.d.ts.map +1 -0
  49. package/dist/engines/pysa.js +83 -0
  50. package/dist/engines/pysa.js.map +1 -0
  51. package/dist/engines/python-sinks.d.ts +82 -0
  52. package/dist/engines/python-sinks.d.ts.map +1 -0
  53. package/dist/engines/python-sinks.js +459 -0
  54. package/dist/engines/python-sinks.js.map +1 -0
  55. package/dist/engines/registry.d.ts +26 -0
  56. package/dist/engines/registry.d.ts.map +1 -0
  57. package/dist/engines/registry.js +70 -0
  58. package/dist/engines/registry.js.map +1 -0
  59. package/dist/engines/secret-scan.d.ts +22 -0
  60. package/dist/engines/secret-scan.d.ts.map +1 -0
  61. package/dist/engines/secret-scan.js +179 -0
  62. package/dist/engines/secret-scan.js.map +1 -0
  63. package/dist/engines/semgrep.d.ts +10 -0
  64. package/dist/engines/semgrep.d.ts.map +1 -0
  65. package/dist/engines/semgrep.js +200 -0
  66. package/dist/engines/semgrep.js.map +1 -0
  67. package/dist/engines/treesitter.d.ts +18 -0
  68. package/dist/engines/treesitter.d.ts.map +1 -0
  69. package/dist/engines/treesitter.js +135 -0
  70. package/dist/engines/treesitter.js.map +1 -0
  71. package/dist/engines/tsc.d.ts +10 -0
  72. package/dist/engines/tsc.d.ts.map +1 -0
  73. package/dist/engines/tsc.js +142 -0
  74. package/dist/engines/tsc.js.map +1 -0
  75. package/dist/engines/types.d.ts +47 -0
  76. package/dist/engines/types.d.ts.map +1 -0
  77. package/dist/engines/types.js +27 -0
  78. package/dist/engines/types.js.map +1 -0
  79. package/dist/findings.d.ts +121 -0
  80. package/dist/findings.d.ts.map +1 -0
  81. package/dist/findings.js +98 -0
  82. package/dist/findings.js.map +1 -0
  83. package/dist/hooks/claude-code.d.ts +3 -0
  84. package/dist/hooks/claude-code.d.ts.map +1 -0
  85. package/dist/hooks/claude-code.js +187 -0
  86. package/dist/hooks/claude-code.js.map +1 -0
  87. package/dist/index/context.d.ts +127 -0
  88. package/dist/index/context.d.ts.map +1 -0
  89. package/dist/index/context.js +267 -0
  90. package/dist/index/context.js.map +1 -0
  91. package/dist/index/embeddings.d.ts +68 -0
  92. package/dist/index/embeddings.d.ts.map +1 -0
  93. package/dist/index/embeddings.js +570 -0
  94. package/dist/index/embeddings.js.map +1 -0
  95. package/dist/index/graph_routing.d.ts +36 -0
  96. package/dist/index/graph_routing.d.ts.map +1 -0
  97. package/dist/index/graph_routing.js +170 -0
  98. package/dist/index/graph_routing.js.map +1 -0
  99. package/dist/index/joern.d.ts +76 -0
  100. package/dist/index/joern.d.ts.map +1 -0
  101. package/dist/index/joern.js +782 -0
  102. package/dist/index/joern.js.map +1 -0
  103. package/dist/index/property-test.d.ts +88 -0
  104. package/dist/index/property-test.d.ts.map +1 -0
  105. package/dist/index/property-test.js +466 -0
  106. package/dist/index/property-test.js.map +1 -0
  107. package/dist/index/proto/scip.proto +897 -0
  108. package/dist/index/pysa.d.ts +91 -0
  109. package/dist/index/pysa.d.ts.map +1 -0
  110. package/dist/index/pysa.js +617 -0
  111. package/dist/index/pysa.js.map +1 -0
  112. package/dist/index/scip.d.ts +76 -0
  113. package/dist/index/scip.d.ts.map +1 -0
  114. package/dist/index/scip.js +541 -0
  115. package/dist/index/scip.js.map +1 -0
  116. package/dist/index/vulrag.d.ts +86 -0
  117. package/dist/index/vulrag.d.ts.map +1 -0
  118. package/dist/index/vulrag.js +242 -0
  119. package/dist/index/vulrag.js.map +1 -0
  120. package/dist/index.d.ts +9 -0
  121. package/dist/index.d.ts.map +1 -0
  122. package/dist/index.js +8 -0
  123. package/dist/index.js.map +1 -0
  124. package/dist/install/claude-code.d.ts +31 -0
  125. package/dist/install/claude-code.d.ts.map +1 -0
  126. package/dist/install/claude-code.js +447 -0
  127. package/dist/install/claude-code.js.map +1 -0
  128. package/dist/lang.d.ts +5 -0
  129. package/dist/lang.d.ts.map +1 -0
  130. package/dist/lang.js +52 -0
  131. package/dist/lang.js.map +1 -0
  132. package/dist/learning/suppressions.d.ts +70 -0
  133. package/dist/learning/suppressions.d.ts.map +1 -0
  134. package/dist/learning/suppressions.js +179 -0
  135. package/dist/learning/suppressions.js.map +1 -0
  136. package/dist/mcp/server.d.ts +2 -0
  137. package/dist/mcp/server.d.ts.map +1 -0
  138. package/dist/mcp/server.js +187 -0
  139. package/dist/mcp/server.js.map +1 -0
  140. package/dist/mcp/tools/explain.d.ts +58 -0
  141. package/dist/mcp/tools/explain.d.ts.map +1 -0
  142. package/dist/mcp/tools/explain.js +60 -0
  143. package/dist/mcp/tools/explain.js.map +1 -0
  144. package/dist/mcp/tools/precheck.d.ts +29 -0
  145. package/dist/mcp/tools/precheck.d.ts.map +1 -0
  146. package/dist/mcp/tools/precheck.js +42 -0
  147. package/dist/mcp/tools/precheck.js.map +1 -0
  148. package/dist/mcp/tools/validate.d.ts +73 -0
  149. package/dist/mcp/tools/validate.d.ts.map +1 -0
  150. package/dist/mcp/tools/validate.js +66 -0
  151. package/dist/mcp/tools/validate.js.map +1 -0
  152. package/dist/mcp/warm.d.ts +88 -0
  153. package/dist/mcp/warm.d.ts.map +1 -0
  154. package/dist/mcp/warm.js +331 -0
  155. package/dist/mcp/warm.js.map +1 -0
  156. package/dist/orchestrator.d.ts +46 -0
  157. package/dist/orchestrator.d.ts.map +1 -0
  158. package/dist/orchestrator.js +596 -0
  159. package/dist/orchestrator.js.map +1 -0
  160. package/dist/policy.d.ts +51 -0
  161. package/dist/policy.d.ts.map +1 -0
  162. package/dist/policy.js +201 -0
  163. package/dist/policy.js.map +1 -0
  164. package/dist/risk.d.ts +31 -0
  165. package/dist/risk.d.ts.map +1 -0
  166. package/dist/risk.js +92 -0
  167. package/dist/risk.js.map +1 -0
  168. package/dist/stats.d.ts +72 -0
  169. package/dist/stats.d.ts.map +1 -0
  170. package/dist/stats.js +217 -0
  171. package/dist/stats.js.map +1 -0
  172. package/dist/telemetry/collector.d.ts +10 -0
  173. package/dist/telemetry/collector.d.ts.map +1 -0
  174. package/dist/telemetry/collector.js +75 -0
  175. package/dist/telemetry/collector.js.map +1 -0
  176. package/dist/telemetry/consent.d.ts +9 -0
  177. package/dist/telemetry/consent.d.ts.map +1 -0
  178. package/dist/telemetry/consent.js +42 -0
  179. package/dist/telemetry/consent.js.map +1 -0
  180. package/dist/telemetry/installation.d.ts +2 -0
  181. package/dist/telemetry/installation.d.ts.map +1 -0
  182. package/dist/telemetry/installation.js +32 -0
  183. package/dist/telemetry/installation.js.map +1 -0
  184. package/dist/telemetry/sanitizer.d.ts +5 -0
  185. package/dist/telemetry/sanitizer.d.ts.map +1 -0
  186. package/dist/telemetry/sanitizer.js +60 -0
  187. package/dist/telemetry/sanitizer.js.map +1 -0
  188. package/dist/telemetry/types.d.ts +39 -0
  189. package/dist/telemetry/types.d.ts.map +1 -0
  190. package/dist/telemetry/types.js +4 -0
  191. package/dist/telemetry/types.js.map +1 -0
  192. package/dist/telemetry/uploader.d.ts +12 -0
  193. package/dist/telemetry/uploader.d.ts.map +1 -0
  194. package/dist/telemetry/uploader.js +92 -0
  195. package/dist/telemetry/uploader.js.map +1 -0
  196. package/dist/util/logger.d.ts +19 -0
  197. package/dist/util/logger.d.ts.map +1 -0
  198. package/dist/util/logger.js +58 -0
  199. package/dist/util/logger.js.map +1 -0
  200. package/dist/util/safe-paths.d.ts +8 -0
  201. package/dist/util/safe-paths.d.ts.map +1 -0
  202. package/dist/util/safe-paths.js +102 -0
  203. package/dist/util/safe-paths.js.map +1 -0
  204. package/dist/util/subprocess.d.ts +32 -0
  205. package/dist/util/subprocess.d.ts.map +1 -0
  206. package/dist/util/subprocess.js +137 -0
  207. package/dist/util/subprocess.js.map +1 -0
  208. package/package.json +93 -0
@@ -0,0 +1,617 @@
1
+ /**
2
+ * Pysa (Pyre Security Analyzer) — Python taint analysis via WSL.
3
+ *
4
+ * Pysa is Meta's interprocedural data-flow / taint analyzer for Python.
5
+ * Per the research (Du 2024 Vul-RAG, Macroscope 2026) it's the best-in-class
6
+ * OSS path to PROVING CWE-89 / 78 / 79 / 918 etc. via source→sink reachability —
7
+ * not heuristic pattern matching but actual dataflow.
8
+ *
9
+ * **Why this module exists on Windows:**
10
+ * Pyre is OCaml-based; the official wheels are Linux + macOS only. Per the
11
+ * Pyre docs: *"On Windows we have successfully gotten pyre to work through
12
+ * WSL, but do not officially support it."* So we bridge: aegis-v2 runs on
13
+ * Windows, Pyre runs inside WSL Ubuntu, paths are translated `C:\foo` →
14
+ * `/mnt/c/foo`. On Linux/macOS hosts the bridge layer is bypassed and we
15
+ * call Pyre directly.
16
+ *
17
+ * **Architecture: batch + cache.**
18
+ * Mirrors `src/index/joern.ts`. `aegis index --pysa` builds taint summaries
19
+ * (slow, 30s-2min depending on project size) + writes `findings.jsonl` to
20
+ * `~/.aegis/pysa/<sha256(root)[:16]>/`. The `PysaEngine` reads that cache
21
+ * at gate-time in milliseconds. Re-run `aegis index --pysa` after big
22
+ * changes; small per-file edits don't require a rebuild.
23
+ *
24
+ * **Auto-bootstrap.**
25
+ * Pysa needs a `.pyre_configuration` file in the project root (Pyre's
26
+ * config) AND a `taint.config` file with source/sink/sanitizer definitions.
27
+ * If absent we write a minimal default `.pyre_configuration` to a SCRATCH
28
+ * directory under the cache (NEVER into the user's project — that would
29
+ * silently mutate their repo). We point Pyre at the project via that
30
+ * scratch dir's `source_directories` list.
31
+ *
32
+ * **Env overrides:**
33
+ * AEGIS_PYSA_WSL_DISTRO — defaults to "Ubuntu"
34
+ * AEGIS_PYSA_PYRE_BIN — explicit path to pyre inside WSL
35
+ * (default: ~/pyre-venv/bin/pyre)
36
+ * AEGIS_PYSA_TIMEOUT_MS — analyze timeout (default 600_000 = 10 min)
37
+ * AEGIS_PYSA_FORCE_LINUX — set when running on Linux/macOS to skip the
38
+ * WSL bridge entirely
39
+ */
40
+ import { createHash } from "node:crypto";
41
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
42
+ import { homedir } from "node:os";
43
+ import { join, resolve as resolvePath } from "node:path";
44
+ import { FindingSchema, makeFindingId } from "../findings.js";
45
+ import { getLogger } from "../util/logger.js";
46
+ import { run as spawnRun } from "../util/subprocess.js";
47
+ const log = getLogger("aegis.pysa");
48
+ // Bump on any taint.config / output-shape change to invalidate cached findings.
49
+ const PYSA_TAINT_CONFIG_VERSION = "v1";
50
+ const DEFAULT_PYSA_TIMEOUT_MS = 10 * 60 * 1000;
51
+ const DEFAULT_WSL_DISTRO = "Ubuntu";
52
+ const DEFAULT_PYRE_BIN = "~/pyre-venv/bin/pyre";
53
+ // ── Discovery: WSL and Pyre ──────────────────────────────────────────────
54
+ function expandHome(p) {
55
+ if (!p.startsWith("~"))
56
+ return p;
57
+ return resolvePath(homedir(), p.slice(2));
58
+ }
59
+ /** Locate wsl.exe on Windows. Returns null on non-Windows OR when WSL
60
+ * is not installed. Does NOT validate that a distro is present — that
61
+ * check belongs to ``probePyreInWsl``. */
62
+ export function findWsl() {
63
+ if (process.platform !== "win32")
64
+ return null;
65
+ if (process.env.AEGIS_PYSA_FORCE_LINUX === "1")
66
+ return null;
67
+ const candidates = [
68
+ process.env.AEGIS_PYSA_WSL_PATH,
69
+ `${process.env.SystemRoot ?? "C:\\Windows"}\\System32\\wsl.exe`,
70
+ "C:\\Windows\\System32\\wsl.exe",
71
+ ].filter((p) => typeof p === "string" && p.length > 0);
72
+ for (const c of candidates) {
73
+ if (existsSync(c)) {
74
+ return { wslExe: c, distro: process.env.AEGIS_PYSA_WSL_DISTRO ?? DEFAULT_WSL_DISTRO };
75
+ }
76
+ }
77
+ return null;
78
+ }
79
+ /** Best-effort probe: does pyre exist + run? Cached per-process to avoid
80
+ * paying the ~1-2 s wsl-roundtrip on every engine.available() call. */
81
+ let _pyreProbeCache;
82
+ const PYRE_PROBE_TTL_MS = 60_000;
83
+ let _pyreProbeAt = 0;
84
+ export async function probePyre() {
85
+ const now = Date.now();
86
+ if (_pyreProbeCache !== undefined && now - _pyreProbeAt < PYRE_PROBE_TTL_MS) {
87
+ return _pyreProbeCache;
88
+ }
89
+ _pyreProbeAt = now;
90
+ const pyreBin = process.env.AEGIS_PYSA_PYRE_BIN ?? DEFAULT_PYRE_BIN;
91
+ if (process.platform === "win32" && process.env.AEGIS_PYSA_FORCE_LINUX !== "1") {
92
+ const wsl = findWsl();
93
+ if (!wsl) {
94
+ _pyreProbeCache = null;
95
+ return null;
96
+ }
97
+ const cmd = `${pyreBin} --version 2>/dev/null || echo NOT_FOUND`;
98
+ const res = await spawnRun(wsl.wslExe, {
99
+ args: ["-d", wsl.distro, "--", "bash", "-c", cmd],
100
+ timeoutMs: 15_000,
101
+ });
102
+ if (res.exitCode !== 0) {
103
+ log.debug("WSL pyre probe failed", { rc: res.exitCode, stderr: res.stderr.slice(0, 200) });
104
+ _pyreProbeCache = null;
105
+ return null;
106
+ }
107
+ // Pyre's --version prints e.g. "Client version: 0.9.25" — does NOT
108
+ // contain the word "pyre" and doesn't start with a digit. Match
109
+ // anything that has "version" + a semver-shaped token, OR a bare
110
+ // semver line, OR a line containing "pyre".
111
+ const versionLine = res.stdout.split(/\r?\n/).find((l) => {
112
+ const t = l.trim();
113
+ if (!t)
114
+ return false;
115
+ if (t.includes("NOT_FOUND"))
116
+ return false;
117
+ if (t.toLowerCase().includes("pyre"))
118
+ return true;
119
+ if (/^\d+\.\d+/.test(t))
120
+ return true;
121
+ if (/version[:\s]+\d+\.\d+/i.test(t))
122
+ return true;
123
+ return false;
124
+ });
125
+ if (!versionLine || versionLine.includes("NOT_FOUND")) {
126
+ _pyreProbeCache = null;
127
+ return null;
128
+ }
129
+ const probe = {
130
+ ok: true,
131
+ pyreBin,
132
+ version: versionLine.trim(),
133
+ usesWsl: true,
134
+ };
135
+ _pyreProbeCache = probe;
136
+ return probe;
137
+ }
138
+ // Linux/macOS native — invoke pyre directly.
139
+ const expanded = expandHome(pyreBin);
140
+ const res = await spawnRun(expanded, { args: ["--version"], timeoutMs: 8_000 });
141
+ if (res.exitCode !== 0) {
142
+ _pyreProbeCache = null;
143
+ return null;
144
+ }
145
+ _pyreProbeCache = {
146
+ ok: true,
147
+ pyreBin: expanded,
148
+ version: res.stdout.trim() || res.stderr.trim() || "unknown",
149
+ usesWsl: false,
150
+ };
151
+ return _pyreProbeCache;
152
+ }
153
+ /** Test-only probe-cache reset. */
154
+ export function _resetPyreProbeCacheForTests() {
155
+ _pyreProbeCache = undefined;
156
+ _pyreProbeAt = 0;
157
+ }
158
+ // ── Cache paths ──────────────────────────────────────────────────────────
159
+ function aegisHome() {
160
+ return process.env.AEGIS_HOME ?? resolvePath(homedir(), ".aegis");
161
+ }
162
+ function cacheDirFor(projectRoot) {
163
+ const h = createHash("sha256").update(resolvePath(projectRoot)).digest("hex").slice(0, 16);
164
+ return join(aegisHome(), "pysa", h);
165
+ }
166
+ export function pysaFindingsPath(projectRoot) {
167
+ return join(cacheDirFor(projectRoot), "findings.jsonl");
168
+ }
169
+ export function pysaInfoPath(projectRoot) {
170
+ return join(cacheDirFor(projectRoot), "info.json");
171
+ }
172
+ /** Read cached findings. Used by ``PysaEngine.run``. */
173
+ export function readPysaFindings(projectRoot) {
174
+ const p = pysaFindingsPath(projectRoot);
175
+ if (!existsSync(p))
176
+ return [];
177
+ try {
178
+ const out = [];
179
+ for (const line of readFileSync(p, "utf8").split(/\r?\n/)) {
180
+ if (!line.trim())
181
+ continue;
182
+ const parsed = FindingSchema.safeParse(JSON.parse(line));
183
+ if (parsed.success)
184
+ out.push(parsed.data);
185
+ }
186
+ return out;
187
+ }
188
+ catch (err) {
189
+ log.warn("pysa findings cache unreadable", { err: String(err) });
190
+ return [];
191
+ }
192
+ }
193
+ // ── Path translation: Win → WSL ──────────────────────────────────────────
194
+ /** Convert a Windows path (``C:\Users\foo``) to a WSL POSIX path
195
+ * (``/mnt/c/Users/foo``). Idempotent on already-POSIX paths. */
196
+ export function winToWslPath(p) {
197
+ if (p.startsWith("/"))
198
+ return p; // already POSIX
199
+ // C:\Users\foo → /mnt/c/Users/foo
200
+ const m = p.match(/^([A-Za-z]):[\\/](.*)$/);
201
+ if (!m)
202
+ return p.replace(/\\/g, "/");
203
+ const drive = m[1].toLowerCase();
204
+ const rest = m[2].replace(/\\/g, "/");
205
+ return `/mnt/${drive}/${rest}`;
206
+ }
207
+ // ── Bootstrap config ─────────────────────────────────────────────────────
208
+ /** Minimal Pyre configuration. We write it to a SCRATCH directory inside
209
+ * the cache (never into the user's repo) and point ``source_directories``
210
+ * at the actual project.
211
+ *
212
+ * ``excludes`` is a list of regex patterns Pyre uses to skip files. We
213
+ * exclude the obvious noise (node_modules/, .venv, __pycache__, dist/,
214
+ * build/, .git/, .aegis/) so Pysa focuses on the user's source. Without
215
+ * this, Pyre defaults to walking everything and the scan either takes
216
+ * 10x longer OR produces only findings from third-party packages. */
217
+ function bootstrapPyreConfig(projectRootWsl) {
218
+ return JSON.stringify({
219
+ source_directories: [projectRootWsl],
220
+ strict: false,
221
+ taint_models_path: ["taint_models"],
222
+ excludes: [
223
+ ".*/node_modules/.*",
224
+ ".*/\\.venv/.*",
225
+ ".*/venv/.*",
226
+ ".*/__pycache__/.*",
227
+ ".*/\\.git/.*",
228
+ ".*/\\.aegis/.*",
229
+ ".*/dist/.*",
230
+ ".*/build/.*",
231
+ ".*/\\.pyre/.*",
232
+ ".*/\\.next/.*",
233
+ ],
234
+ }, null, 2);
235
+ }
236
+ /** Minimal Pysa taint config. Defines a small but useful set of sources
237
+ * (Flask/Django/FastAPI request inputs, env vars, file reads) and sinks
238
+ * (SQL execute, OS command, eval/exec, file write, HTTP outbound). Real
239
+ * production configs are much richer — this is the seed that catches the
240
+ * most common CWE-78/89/79/918 patterns Pysa is famous for. */
241
+ function bootstrapTaintConfig() {
242
+ return JSON.stringify({
243
+ sources: [
244
+ { name: "UserControlled", comment: "Direct user-controllable input." },
245
+ { name: "Cookies", comment: "HTTP cookie value." },
246
+ { name: "Headers", comment: "HTTP header value." },
247
+ ],
248
+ sinks: [
249
+ { name: "SQL", comment: "Executed as SQL." },
250
+ { name: "RemoteCodeExecution", comment: "Eval/exec/etc." },
251
+ { name: "Command", comment: "Shell command." },
252
+ { name: "FileWrite", comment: "Filesystem write." },
253
+ { name: "RequestSend", comment: "Outbound HTTP." },
254
+ ],
255
+ features: [],
256
+ rules: [
257
+ {
258
+ name: "UserControlled to SQL",
259
+ code: 5001,
260
+ sources: ["UserControlled", "Cookies", "Headers"],
261
+ sinks: ["SQL"],
262
+ message_format: "User-controlled data flows into SQL query (CWE-89).",
263
+ },
264
+ {
265
+ name: "UserControlled to RCE",
266
+ code: 5002,
267
+ sources: ["UserControlled", "Cookies", "Headers"],
268
+ sinks: ["RemoteCodeExecution"],
269
+ message_format: "User-controlled data reaches eval/exec (CWE-94/95).",
270
+ },
271
+ {
272
+ name: "UserControlled to Command",
273
+ code: 5003,
274
+ sources: ["UserControlled", "Cookies", "Headers"],
275
+ sinks: ["Command"],
276
+ message_format: "User-controlled data reaches OS command (CWE-78).",
277
+ },
278
+ {
279
+ name: "UserControlled to RequestSend",
280
+ code: 5004,
281
+ sources: ["UserControlled", "Cookies", "Headers"],
282
+ sinks: ["RequestSend"],
283
+ message_format: "User-controlled data flows into outbound HTTP (CWE-918 SSRF).",
284
+ },
285
+ ],
286
+ }, null, 2);
287
+ }
288
+ /** Minimal stub models — Pysa needs explicit source/sink annotations on
289
+ * common library calls. This is a tiny seed (Flask/FastAPI/sqlite3/os) —
290
+ * real configs ship hundreds. Enough to make the rules above fire on
291
+ * canonical patterns. */
292
+ function bootstrapTaintModels() {
293
+ // CRITICAL: Pysa model signatures must EXACTLY match the implementation
294
+ // signature in typeshed. The `__` prefix marks positional-only — required
295
+ // when typeshed declares the parameter as nameless. Without this, every
296
+ // model fails verification and Pysa silently emits zero issues.
297
+ //
298
+ // Verified against pyre-check 0.9.25 / Python 3.12 typeshed. If you bump
299
+ // the Pyre version and these stop matching, run `pyre analyze` WITHOUT
300
+ // ``--no-verify`` and read the error message — Pyre prints the exact
301
+ // implementation signature you need to match.
302
+ return [
303
+ "# Auto-generated by aegis-v2 — stdlib-only taint stubs.",
304
+ "# Extend by adding more .pysa files to <project>/taint_models if your",
305
+ "# project uses framework sources (Flask request, FastAPI Body, etc.) —",
306
+ "# those models only verify when the framework is importable.",
307
+ "",
308
+ "# === Built-in stdlib sources ===",
309
+ "def input(__prompt = ...) -> TaintSource[UserControlled]: ...",
310
+ "",
311
+ "# os.getenv is a free function — straightforward shape.",
312
+ "def os.getenv(key, default = ...) -> TaintSource[UserControlled]: ...",
313
+ "",
314
+ "# === sqlite3 sinks (stdlib) ===",
315
+ "# Cursor.execute signature in typeshed:",
316
+ "# (_Self_sqlite3_Cursor__, str, SupportsLenAndGetItem[Any] | Mapping[str, Any]=...) -> _Self_sqlite3_Cursor__",
317
+ "# All 3 args positional-only. We name the SQL arg to mark it as the sink.",
318
+ "def sqlite3.Cursor.execute(__self, __sql: TaintSink[SQL], __parameters = ...): ...",
319
+ "def sqlite3.Cursor.executemany(__self, __sql: TaintSink[SQL], __parameters): ...",
320
+ "def sqlite3.Cursor.executescript(__self, __sql_script: TaintSink[SQL]): ...",
321
+ "def sqlite3.Connection.execute(__self, __sql: TaintSink[SQL], __parameters = ...): ...",
322
+ "def sqlite3.Connection.executemany(__self, __sql: TaintSink[SQL], __parameters): ...",
323
+ "def sqlite3.Connection.executescript(__self, __sql_script: TaintSink[SQL]): ...",
324
+ "",
325
+ "# === OS command sinks (stdlib) ===",
326
+ "# os.system and os.popen take named params in typeshed — drop the __ prefix.",
327
+ "def os.system(command: TaintSink[Command]): ...",
328
+ "def os.popen(cmd: TaintSink[Command], mode = ..., buffering = ...): ...",
329
+ "",
330
+ "# === Eval / exec sinks (stdlib) — first arg is positional-only ===",
331
+ "def eval(__source: TaintSink[RemoteCodeExecution], __globals = ..., __locals = ...): ...",
332
+ "def exec(__source: TaintSink[RemoteCodeExecution], __globals = ..., __locals = ...): ...",
333
+ "",
334
+ ].join("\n");
335
+ }
336
+ const CODE_TO_CWE = {
337
+ 5001: { cwe: "CWE-89", title: "Pysa taint: User input flows into SQL execute" },
338
+ 5002: { cwe: "CWE-94", title: "Pysa taint: User input flows into eval/exec" },
339
+ 5003: { cwe: "CWE-78", title: "Pysa taint: User input flows into OS command" },
340
+ 5004: { cwe: "CWE-918", title: "Pysa taint: User input flows into outbound HTTP (SSRF)" },
341
+ };
342
+ /** Convert a Pysa qualified callable name (``tests.fixtures.foo.bar``) to
343
+ * a project-relative POSIX path (``tests/fixtures/foo.py``).
344
+ *
345
+ * We do NOT know which dot is a module separator and which is a method
346
+ * accessor (``mod.Class.method``), so the heuristic is: take the FIRST
347
+ * existing prefix as the module path, treat the remainder as in-file
348
+ * symbols. Worst case we strip too much (one ".py" file per symbol) —
349
+ * still better than emitting "*" which is meaningless. */
350
+ function callableToPath(callable, projectRoot) {
351
+ if (!callable)
352
+ return "(unknown)";
353
+ const parts = callable.split(".");
354
+ // Try progressively shorter prefixes until we find one that exists as
355
+ // a .py file on disk.
356
+ for (let i = parts.length; i >= 1; i--) {
357
+ const candidate = parts.slice(0, i).join("/") + ".py";
358
+ const abs = resolvePath(projectRoot, candidate);
359
+ if (existsSync(abs))
360
+ return candidate;
361
+ }
362
+ // Fallback: assume first 3 segments are dirs + last is file.
363
+ if (parts.length >= 2) {
364
+ return parts.slice(0, parts.length - 1).join("/") + ".py";
365
+ }
366
+ return callable;
367
+ }
368
+ function parsePysaOutput(rawJson, projectRoot) {
369
+ const out = [];
370
+ const seen = new Set();
371
+ for (const rawLine of rawJson.split(/\r?\n/)) {
372
+ const line = rawLine.trim();
373
+ if (!line)
374
+ continue;
375
+ let env;
376
+ try {
377
+ env = JSON.parse(line);
378
+ }
379
+ catch {
380
+ // skip non-JSON lines (Pyre sometimes emits banner text before JSON)
381
+ continue;
382
+ }
383
+ if (env.kind !== "issue" || !env.data)
384
+ continue;
385
+ const issue = env.data;
386
+ const code = issue.code ?? 0;
387
+ const cweInfo = CODE_TO_CWE[code];
388
+ if (!cweInfo)
389
+ continue;
390
+ const rawFilename = (issue.filename ?? "").replace(/\\/g, "/");
391
+ // Pysa sometimes uses "*" for "any file containing this callable" when
392
+ // the callable has been inlined / proxied. Recover via the callable.
393
+ const rel = rawFilename === "*" || !rawFilename
394
+ ? callableToPath(issue.callable ?? "", projectRoot)
395
+ : toRelPosix(rawFilename, projectRoot);
396
+ const lineNo = typeof issue.line === "number" && issue.line > 0 ? issue.line : undefined;
397
+ const dedup = `${rel}::${lineNo ?? "?"}::${cweInfo.cwe}::${code}`;
398
+ if (seen.has(dedup))
399
+ continue;
400
+ seen.add(dedup);
401
+ const ruleId = `pysa.${code}`;
402
+ const finding = {
403
+ id: makeFindingId({
404
+ engine: "pysa",
405
+ file: rel,
406
+ ...(lineNo !== undefined ? { line: lineNo } : {}),
407
+ rule_id: ruleId,
408
+ }),
409
+ engine: "pysa",
410
+ file: rel,
411
+ ...(lineNo !== undefined ? { line: lineNo } : {}),
412
+ rule_id: ruleId,
413
+ cwe: cweInfo.cwe,
414
+ severity: "high",
415
+ // Taint reachability is real proof of a path — higher than Joern's
416
+ // pattern-match confidence but still LLM-critic should refine before
417
+ // we BLOCK on it alone. (SourceKindEnum doesn't have a separate
418
+ // "taint" tag yet; "dataflow" is the closest semantic match — both
419
+ // are reachability-based vs the syntactic "pattern".)
420
+ confidence: 0.8,
421
+ source: "dataflow",
422
+ message: `${cweInfo.title}. ${String(issue.message ?? "").slice(0, 300)}`,
423
+ evidence: {
424
+ snippet: String(issue.callable ?? "").slice(0, 200) || undefined,
425
+ },
426
+ };
427
+ const parsed = FindingSchema.safeParse(finding);
428
+ if (parsed.success)
429
+ out.push(parsed.data);
430
+ }
431
+ return out;
432
+ }
433
+ function toRelPosix(filePath, projectRoot) {
434
+ const fp = filePath.replace(/\\/g, "/");
435
+ const root = projectRoot.replace(/\\/g, "/").replace(/\/+$/, "");
436
+ // Match either Windows path under root OR a /mnt/c/-translated path (Pysa
437
+ // sees the WSL path; we map back).
438
+ const rootWsl = winToWslPath(projectRoot).replace(/\/+$/, "");
439
+ if (fp.toLowerCase().startsWith(root.toLowerCase() + "/"))
440
+ return fp.slice(root.length + 1);
441
+ if (fp.toLowerCase().startsWith(rootWsl.toLowerCase() + "/"))
442
+ return fp.slice(rootWsl.length + 1);
443
+ return fp;
444
+ }
445
+ // ── Build entry point ────────────────────────────────────────────────────
446
+ /** Run Pysa on the project. Builds the bootstrap config in a SCRATCH dir
447
+ * (NEVER touches the user's repo), invokes ``pyre analyze``, parses the
448
+ * resulting taint-output.json, writes findings.jsonl into the per-project
449
+ * cache. Returns a structured report. Never throws — failures produce
450
+ * ``{ok:false, reason}``. */
451
+ export async function buildPysaTaint(projectRoot, opts) {
452
+ const t0 = Date.now();
453
+ const dir = cacheDirFor(projectRoot);
454
+ const findingsPath = pysaFindingsPath(projectRoot);
455
+ const infoPath = pysaInfoPath(projectRoot);
456
+ const force = opts?.force ?? false;
457
+ const probe = await probePyre();
458
+ if (!probe) {
459
+ return {
460
+ ok: false,
461
+ cacheDir: dir,
462
+ findingsPath,
463
+ findingsCount: 0,
464
+ durationMs: Date.now() - t0,
465
+ reason: process.platform === "win32"
466
+ ? "Pyre/Pysa not available — WSL or pyre-check inside WSL missing. Install: wsl --install, then in Ubuntu: python3 -m venv ~/pyre-venv && source ~/pyre-venv/bin/activate && pip install pyre-check"
467
+ : "pyre not found on PATH. Install: pip install pyre-check (or set AEGIS_PYSA_PYRE_BIN).",
468
+ };
469
+ }
470
+ // Cache freshness
471
+ if (!force && existsSync(infoPath) && existsSync(findingsPath)) {
472
+ try {
473
+ const info = JSON.parse(readFileSync(infoPath, "utf8"));
474
+ if (info.config_version === PYSA_TAINT_CONFIG_VERSION) {
475
+ const n = (readFileSync(findingsPath, "utf8").match(/\n/g) ?? []).length;
476
+ log.info("pysa cache hit", { dir, age_ms: Date.now() - info.built_at, n });
477
+ return {
478
+ ok: true,
479
+ cacheDir: dir,
480
+ findingsPath,
481
+ findingsCount: n,
482
+ durationMs: Date.now() - t0,
483
+ };
484
+ }
485
+ }
486
+ catch {
487
+ // fall through to rebuild
488
+ }
489
+ }
490
+ // Build scratch config directory under the cache.
491
+ // CRITICAL: Pysa expects the ``taint.config`` file to live INSIDE the
492
+ // ``--taint-models-path`` directory alongside the .pysa stub files —
493
+ // not at the project / scratch root. Per Pysa's source, it scans the
494
+ // models dir for any ``.config`` file and rejects the run if none is
495
+ // present (error: "No `.config` was found in the taint directories").
496
+ const scratch = join(dir, "scratch");
497
+ const taintModelsDir = join(scratch, "taint_models");
498
+ mkdirSync(scratch, { recursive: true });
499
+ mkdirSync(taintModelsDir, { recursive: true });
500
+ // The Pyre config's `source_directories` MUST be expressed in whatever
501
+ // path style Pyre will see — if we go through WSL it must be /mnt/c/...,
502
+ // on Linux native it's the absolute path verbatim.
503
+ const projectRootForPyre = probe.usesWsl ? winToWslPath(projectRoot) : resolvePath(projectRoot);
504
+ writeFileSync(join(scratch, ".pyre_configuration"), bootstrapPyreConfig(projectRootForPyre), "utf8");
505
+ writeFileSync(join(taintModelsDir, "taint.config"), bootstrapTaintConfig(), "utf8");
506
+ writeFileSync(join(taintModelsDir, "general.pysa"), bootstrapTaintModels(), "utf8");
507
+ // The scratch dir we'll cd into inside WSL.
508
+ const scratchForPyre = probe.usesWsl ? winToWslPath(scratch) : scratch;
509
+ const outDir = join(scratch, "pysa-output");
510
+ mkdirSync(outDir, { recursive: true });
511
+ const outDirForPyre = probe.usesWsl ? winToWslPath(outDir) : outDir;
512
+ const wsl = probe.usesWsl ? findWsl() : null;
513
+ // Compose the analyze command. ``--save-results-to <dir>`` writes
514
+ // ``taint-output.json`` (the JSON we parse) and a metadata file. We
515
+ // intentionally do NOT pass ``--rule`` flags — Pysa runs all rules
516
+ // defined in our scratch ``taint.config`` automatically, which is
517
+ // exactly the four we want (5001..5004). Pysa's ``--rule`` accepts
518
+ // ONE integer at a time and the only way to limit to a subset is to
519
+ // repeat the flag; not worth it when the config already enumerates
520
+ // the rules we care about.
521
+ // No --no-verify: we want Pysa to FAIL LOUD if a model stops matching
522
+ // typeshed after a Pyre upgrade. Silent verification dropping is exactly
523
+ // the failure mode we hit while debugging V2-11.
524
+ const pyreCommand = [
525
+ probe.pyreBin,
526
+ "--noninteractive",
527
+ "analyze",
528
+ "--save-results-to",
529
+ `"${outDirForPyre}"`,
530
+ "--taint-models-path",
531
+ `"${winToWslPath(taintModelsDir)}"`,
532
+ ].join(" ");
533
+ const remoteScript = `cd "${scratchForPyre}" && ${pyreCommand}`;
534
+ log.info("pysa: invoking analyze", { usesWsl: probe.usesWsl, distro: wsl?.distro });
535
+ const t1 = Date.now();
536
+ const res = probe.usesWsl && wsl
537
+ ? await spawnRun(wsl.wslExe, {
538
+ args: ["-d", wsl.distro, "--", "bash", "-c", remoteScript],
539
+ timeoutMs: opts?.timeoutMs ?? DEFAULT_PYSA_TIMEOUT_MS,
540
+ maxBufferBytes: 50 * 1024 * 1024,
541
+ })
542
+ : await spawnRun("bash", {
543
+ args: ["-c", remoteScript],
544
+ timeoutMs: opts?.timeoutMs ?? DEFAULT_PYSA_TIMEOUT_MS,
545
+ maxBufferBytes: 50 * 1024 * 1024,
546
+ });
547
+ if (res.timedOut) {
548
+ return {
549
+ ok: false,
550
+ cacheDir: dir,
551
+ findingsPath,
552
+ findingsCount: 0,
553
+ durationMs: Date.now() - t0,
554
+ reason: `pyre analyze timed out after ${opts?.timeoutMs ?? DEFAULT_PYSA_TIMEOUT_MS}ms`,
555
+ };
556
+ }
557
+ // Pyre returns rc=0 even when issues are found. Non-zero means the
558
+ // analysis itself failed (bad config, syntax error in the project,
559
+ // missing taint stubs, etc).
560
+ if (res.exitCode !== 0) {
561
+ return {
562
+ ok: false,
563
+ cacheDir: dir,
564
+ findingsPath,
565
+ findingsCount: 0,
566
+ durationMs: Date.now() - t0,
567
+ reason: `pyre analyze failed (rc=${res.exitCode}): ${res.stderr.slice(-500) || res.stdout.slice(-500)}`,
568
+ };
569
+ }
570
+ // Read taint-output.json
571
+ const taintOutputPath = join(outDir, "taint-output.json");
572
+ if (!existsSync(taintOutputPath)) {
573
+ return {
574
+ ok: false,
575
+ cacheDir: dir,
576
+ findingsPath,
577
+ findingsCount: 0,
578
+ durationMs: Date.now() - t0,
579
+ reason: `pyre analyze finished but ${taintOutputPath} not produced`,
580
+ };
581
+ }
582
+ const findings = parsePysaOutput(readFileSync(taintOutputPath, "utf8"), projectRoot);
583
+ writeFileSync(findingsPath, findings.map((f) => JSON.stringify(f)).join("\n") + (findings.length ? "\n" : ""), "utf8");
584
+ const info = {
585
+ built_at: Date.now(),
586
+ config_version: PYSA_TAINT_CONFIG_VERSION,
587
+ pyre_version: probe.version,
588
+ ...(probe.usesWsl && wsl ? { wsl_distro: wsl.distro } : {}),
589
+ n_findings: findings.length,
590
+ files_analyzed: new Set(findings.map((f) => f.file)).size,
591
+ };
592
+ writeFileSync(infoPath, JSON.stringify(info, null, 2), "utf8");
593
+ log.info("pysa: analyze done", {
594
+ findings: findings.length,
595
+ analyze_ms: Date.now() - t1,
596
+ total_ms: Date.now() - t0,
597
+ });
598
+ return {
599
+ ok: true,
600
+ cacheDir: dir,
601
+ findingsPath,
602
+ findingsCount: findings.length,
603
+ durationMs: Date.now() - t0,
604
+ };
605
+ }
606
+ // Test-friendly exports
607
+ export const _testing = {
608
+ winToWslPath,
609
+ parsePysaOutput,
610
+ toRelPosix,
611
+ bootstrapPyreConfig,
612
+ bootstrapTaintConfig,
613
+ bootstrapTaintModels,
614
+ CODE_TO_CWE,
615
+ PYSA_TAINT_CONFIG_VERSION,
616
+ };
617
+ //# sourceMappingURL=pysa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pysa.js","sourceRoot":"","sources":["../../src/index/pysa.ts"],"names":[],"mappings":"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"}