token-goat 2.6.34 → 2.6.35

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 (24) hide show
  1. package/SECURITY.md +11 -10
  2. package/dist/{token-goat-chunk-IYYQOPY4.mjs → token-goat-chunk-D5IZEGN2.mjs} +18 -4
  3. package/dist/{token-goat-chunk-WA2ER6TZ.mjs → token-goat-chunk-DQIT5JIF.mjs} +1 -1
  4. package/dist/{token-goat-chunk-L7QLEVO7.mjs → token-goat-chunk-DRAIYVUI.mjs} +16 -14
  5. package/dist/{token-goat-chunk-GXBPEQR2.mjs → token-goat-chunk-HW4VUKJ5.mjs} +14 -8
  6. package/dist/{token-goat-chunk-CN7GUPX6.mjs → token-goat-chunk-I2KCEGIP.mjs} +378 -54
  7. package/dist/{token-goat-chunk-7FWBSPCT.mjs → token-goat-chunk-K7W3P2TJ.mjs} +139 -6
  8. package/dist/{token-goat-chunk-OA3GFKP2.mjs → token-goat-chunk-SIHYQCTM.mjs} +2 -2
  9. package/dist/{token-goat-chunk-I6EQH27G.mjs → token-goat-chunk-UIZVX3HN.mjs} +2 -2
  10. package/dist/{token-goat-chunk-FRMEOIRU.mjs → token-goat-chunk-Y2NH6DGZ.mjs} +208 -13
  11. package/dist/{token-goat-chunk-CKRATWCJ.mjs → token-goat-chunk-YF67EWRH.mjs} +5 -5
  12. package/dist/{token-goat-hook-chunk-CNLMPHXT.mjs → token-goat-hook-chunk-2O7P4Z6Q.mjs} +139 -6
  13. package/dist/{token-goat-hook-chunk-I5VM5PO5.mjs → token-goat-hook-chunk-3AAH72SO.mjs} +14 -8
  14. package/dist/{token-goat-hook-chunk-BU5OFDGQ.mjs → token-goat-hook-chunk-4POU6OHK.mjs} +208 -13
  15. package/dist/{token-goat-hook-chunk-6C5RN3CM.mjs → token-goat-hook-chunk-CRBMPT74.mjs} +2 -2
  16. package/dist/{token-goat-hook-chunk-QTZ6YUMQ.mjs → token-goat-hook-chunk-D6UJEFHX.mjs} +2 -2
  17. package/dist/{token-goat-hook-chunk-ATEGFQAU.mjs → token-goat-hook-chunk-J4HKWUWZ.mjs} +5 -5
  18. package/dist/{token-goat-hook-chunk-2ISZ4AZR.mjs → token-goat-hook-chunk-NIPXIAPA.mjs} +1 -1
  19. package/dist/{token-goat-hook-chunk-KGLMNOGD.mjs → token-goat-hook-chunk-NXVT4F3S.mjs} +18 -4
  20. package/dist/{token-goat-hook-chunk-OQML5EMA.mjs → token-goat-hook-chunk-VU6VGZBM.mjs} +16 -14
  21. package/dist/{token-goat-hook-chunk-6QTWMSRO.mjs → token-goat-hook-chunk-XM4W3WCO.mjs} +378 -54
  22. package/dist/token-goat-hook.mjs +5 -5
  23. package/dist/token-goat.core.mjs +5 -5
  24. package/package.json +4 -3
package/SECURITY.md CHANGED
@@ -56,9 +56,10 @@ Without the overrides a consumer resolves `protobufjs` at 6.x, which carries mor
56
56
  | Package | Advisories it carries | Where it loads | Why the advisory does not reach you through Token-Goat |
57
57
  | --- | --- | --- | --- |
58
58
  | `@xenova/transformers` | [`protobufjs`](https://github.com/advisories/GHSA-xq3m-2v4x-88gg) (critical), `onnx-proto`, `onnxruntime-web`, and its own pinned `sharp` | optional; loaded only when semantic search builds or queries embeddings | not mitigated, so it is the one to weigh. Skip it with `npm install --omit=optional`, or leave `indexing.embeddings_enabled` off, and the code never loads |
59
- | `exceljs` | [`uuid`](https://github.com/advisories/GHSA-w5hq-g745-h8pq) | optional; loaded only when an `xlsx-*` command opens a workbook | the advisory is a missing bounds check on a caller-supplied `buf` argument; ExcelJS never passes one |
60
59
 
61
- `npm install --omit=optional` gives you an install without either of these, and `npm audit` reports it clean. Every command still starts; the ones that need a package you skipped say so. The `xlsx-*` commands report that ExcelJS is not installed rather than failing oddly, `zip-list`/`zip-read` do the same for fflate, and `semantic` keeps working on keyword search alone: it is the embedding half that goes away, not the command.
60
+ `npm install --omit=optional` gives you an install without it, and `npm audit` reports it clean. Every command still starts; the ones that need a package you skipped say so. The `xlsx-*`, `docx-*` and `pptx-*` commands report that fflate is not installed rather than failing oddly, `zip-list`/`zip-read` do the same, and `semantic` keeps working on keyword search alone: it is the embedding half that goes away, not the command.
61
+
62
+ `exceljs` used to appear in that table, carrying [`uuid`](https://github.com/advisories/GHSA-w5hq-g745-h8pq). It is now a development dependency instead. The `xlsx-*` commands read the workbook container directly with `fflate` and `fast-xml-parser`, the same two packages the `.docx` and `.pptx` readers already used, so `exceljs` is only a test fixture writer now. That removes 55 packages from a default install, including every deprecated one in the tree.
62
63
 
63
64
  `html-to-text` used to appear in that table, carrying [`deepmerge-ts`](https://github.com/advisories/GHSA-ggr8-5vv4-36mx). It is now a development dependency instead. esbuild inlines it into `dist/token-goat.mjs` at build time and nothing in the published bundle imports it, so it was a runtime dependency in name only: moving it removes `html-to-text`, `deepmerge-ts`, `htmlparser2`, `selderee`, and `dom-serializer` from an installed copy while the HTML-to-text output stays byte-for-byte identical. That is what takes the no-optional install to zero, and it is better than the alternative we had considered, rolling `html-to-text` back to 9.x: that version pins `htmlparser2` two majors lower, and `htmlparser2` is what parses fetched pages, so it would have traded an advisory in an options merger for an older parser on the one path that handles untrusted input.
64
65
 
@@ -89,8 +90,8 @@ Token-Goat is source-available under the PolyForm Noncommercial License 1.0.0. S
89
90
 
90
91
  Every production dependency is permissively licensed, but a scan does not read it that way on its
91
92
  own. Counted from `package-lock.json`, which lists the packages for every platform rather than only
92
- the ones this machine installed, 22 entries need a human answer: 7 declare a license a scanner
93
- cannot resolve, and 15 carry a copyleft term. All 22 arrive through optional dependencies. Install
93
+ the ones this machine installed, 21 entries need a human answer: 7 declare a license a scanner
94
+ cannot resolve, and 14 carry a copyleft term. All 21 arrive through optional dependencies. Install
94
95
  with `npm install --omit=optional token-goat` and not one of them is present.
95
96
 
96
97
  **Declarations a scanner cannot resolve.** Both are upstream mistakes, and both are the same
@@ -110,19 +111,19 @@ an unresolvable one.
110
111
  | --- | --- | --- |
111
112
  | `@img/sharp-libvips-<platform>` (10 packages) | `LGPL-3.0-or-later` | libvips, shipped as a prebuilt shared library and used unmodified. LGPL asks that the library stay replaceable, and it is: it is a separate package that `sharp` loads at runtime. |
112
113
  | `@img/sharp-<platform>` (4 packages) | `Apache-2.0 AND LGPL-3.0-or-later` | the Apache half is `sharp` itself, the LGPL half is the same libvips |
113
- | `jszip` | `(MIT OR GPL-3.0-or-later)` | a choice between the two, and the MIT half is taken |
114
114
 
115
- `sharp` and `jszip` are both optional: `sharp` powers image shrinking, `jszip` arrives through
116
- `exceljs` for the `xlsx-*` commands.
115
+ `sharp` is optional: it powers image shrinking. `jszip` used to be listed here too; it arrived
116
+ through `exceljs`, which is no longer a dependency a consumer installs.
117
117
 
118
118
  **Three packages with no license at all used to be here.** `buffers@0.1.1` and `chainsaw@0.1.0`
119
119
  shipped with neither a `license` field nor a license file, and `traverse@0.3.9` had the file but
120
120
  not the field. No grant at all is worse for a review than a copyleft grant, because there is
121
121
  nothing to apply policy to. They arrived through `exceljs`, which depends on `unzipper`, which
122
122
  depended on `binary`, which depended on all three. `unzipper` dropped `binary` in 0.11, so an
123
- override to `^0.12.5` removes the sub-chain, and the deprecated `fstream` with it. Token-goat reads
124
- workbooks through `wb.xlsx.readFile()`, which goes through `jszip`; `unzipper` is only reachable
125
- through the streaming reader in `exceljs`, which this code never calls.
123
+ override to `^0.12.5` removes the sub-chain, and the deprecated `fstream` with it. `exceljs` is now
124
+ a development dependency, so none of that chain reaches an installed copy either way; the override
125
+ stays because it is what keeps this repository's own `npm audit`, which includes development
126
+ dependencies, clean.
126
127
 
127
128
  Reproduce the whole picture:
128
129
 
@@ -50,7 +50,7 @@ import {
50
50
  walkProject,
51
51
  yamlLineClosesQuote,
52
52
  yamlOpenQuoteAfter
53
- } from "./token-goat-chunk-CN7GUPX6.mjs";
53
+ } from "./token-goat-chunk-I2KCEGIP.mjs";
54
54
  import {
55
55
  PER_FILE_COUNTERFACTUAL_CEILING,
56
56
  _detectOpenQuote,
@@ -100,7 +100,7 @@ import {
100
100
  unsupportedLanguageName,
101
101
  windowsCmdQuoteArg,
102
102
  withExtension
103
- } from "./token-goat-chunk-7FWBSPCT.mjs";
103
+ } from "./token-goat-chunk-K7W3P2TJ.mjs";
104
104
  import {
105
105
  registerReset
106
106
  } from "./token-goat-chunk-AO2QD2AG.mjs";
@@ -7644,10 +7644,16 @@ function buildChangedRefHint(cwd, ref) {
7644
7644
  const commitWord = commitCount === 1 ? "1 commit" : `${commitCount} commits`;
7645
7645
  return `Hint: this repo has only ${commitWord}; '${ref}' does not exist. Try: token-goat changed --since ${suggestedRef}`;
7646
7646
  }
7647
+ function refIsSafe(ref) {
7648
+ return !ref.startsWith("-");
7649
+ }
7650
+ function emitUnsafeRef(ref) {
7651
+ emitErr(`Refusing a git ref that starts with '-': ${ref}`);
7652
+ }
7647
7653
  function runChanged(opts = {}) {
7648
7654
  const ref = opts.ref ?? "HEAD~5";
7649
- if (ref.startsWith("-")) {
7650
- emitErr(`Refusing a git ref that starts with '-': ${ref}`);
7655
+ if (!refIsSafe(ref)) {
7656
+ emitUnsafeRef(ref);
7651
7657
  return 1;
7652
7658
  }
7653
7659
  const cwd = opts.projectRoot ?? process.cwd();
@@ -7824,6 +7830,10 @@ function resolveSymbolSpecOrEmitError(commandName, spec, projectRoot) {
7824
7830
  return resolution.entry;
7825
7831
  }
7826
7832
  function runDiff(opts) {
7833
+ if (opts.ref !== void 0 && !refIsSafe(opts.ref)) {
7834
+ emitUnsafeRef(opts.ref);
7835
+ return 1;
7836
+ }
7827
7837
  const match = resolveSymbolSpecOrEmitError("diff", opts.spec, opts.projectRoot);
7828
7838
  if (match === null) return 1;
7829
7839
  const cwd = opts.projectRoot ?? process.cwd();
@@ -7911,6 +7921,10 @@ function parseLogDashLOutput(stdout) {
7911
7921
  return entries;
7912
7922
  }
7913
7923
  function runLog(opts) {
7924
+ if (opts.ref !== void 0 && !refIsSafe(opts.ref)) {
7925
+ emitUnsafeRef(opts.ref);
7926
+ return 1;
7927
+ }
7914
7928
  const match = resolveSymbolSpecOrEmitError("log", opts.spec, opts.projectRoot);
7915
7929
  if (match === null) return 1;
7916
7930
  const cwd = opts.projectRoot ?? process.cwd();
@@ -4,7 +4,7 @@ import {
4
4
  loadConfig,
5
5
  redactSecrets,
6
6
  stripAnsiCodes
7
- } from "./token-goat-chunk-7FWBSPCT.mjs";
7
+ } from "./token-goat-chunk-K7W3P2TJ.mjs";
8
8
 
9
9
  // src/tool_filters/helpers.ts
10
10
  import * as fs from "node:fs";
@@ -25,7 +25,7 @@ import {
25
25
  runSkeleton,
26
26
  runSymbol,
27
27
  withPinnedReads
28
- } from "./token-goat-chunk-IYYQOPY4.mjs";
28
+ } from "./token-goat-chunk-D5IZEGN2.mjs";
29
29
  import {
30
30
  buildProjectMap,
31
31
  embeddingsDepsAvailable,
@@ -34,7 +34,7 @@ import {
34
34
  getProjectIndexCounts,
35
35
  isWorkerRunning,
36
36
  mapLookupBytesSaved
37
- } from "./token-goat-chunk-CN7GUPX6.mjs";
37
+ } from "./token-goat-chunk-I2KCEGIP.mjs";
38
38
  import {
39
39
  VERSION,
40
40
  dataDir,
@@ -45,7 +45,7 @@ import {
45
45
  normalizePath,
46
46
  recordStat,
47
47
  resolveProjectRoot
48
- } from "./token-goat-chunk-7FWBSPCT.mjs";
48
+ } from "./token-goat-chunk-K7W3P2TJ.mjs";
49
49
  import "./token-goat-chunk-AO2QD2AG.mjs";
50
50
  import "./token-goat-chunk-AEX54RUZ.mjs";
51
51
 
@@ -126,7 +126,19 @@ function forCompare(p) {
126
126
  return process.platform === "win32" ? p.toLowerCase() : p;
127
127
  }
128
128
  function resolveToolRoot(projectRoot) {
129
- return resolveProjectRoot(projectRoot !== void 0 ? { project: projectRoot } : {});
129
+ const resolved = resolveProjectRoot(projectRoot !== void 0 ? { project: projectRoot } : {});
130
+ assertRootAllowed(resolved);
131
+ return resolved;
132
+ }
133
+ var RootNotAllowedError = class extends Error {
134
+ };
135
+ function assertRootAllowed(resolvedRoot) {
136
+ const allowedRoots = loadConfig().mcp.allowed_roots;
137
+ if (allowedRoots.length === 0) return;
138
+ if (allowedRoots.some((allowed) => checkWithinProjectRoot(resolvedRoot, allowed).inside)) return;
139
+ throw new RootNotAllowedError(
140
+ `refused: "${resolvedRoot}" is not inside any root listed in mcp.allowed_roots. A caller-supplied projectRoot is untrusted input, so this deployment pins which roots may be named; add the root to mcp.allowed_roots (or TOKEN_GOAT_MCP_ALLOWED_ROOTS) to permit it.`
141
+ );
130
142
  }
131
143
  function checkWithinProjectRoot(target, resolvedRoot) {
132
144
  const root = forCompare(normalizePath(realPathOrSelf(resolvedRoot)));
@@ -150,16 +162,6 @@ function specFilePart(spec) {
150
162
  var NO_PINS = /* @__PURE__ */ new Map();
151
163
  function confineTargets(targets, resolvedRoot, splitCommas = true) {
152
164
  if (!loadConfig(resolvedRoot).mcp.confine_reads_to_project_root) return { ok: true, targets, pins: NO_PINS };
153
- const allowedRoots = loadConfig().mcp.allowed_roots;
154
- if (allowedRoots.length > 0 && !allowedRoots.some((allowed) => checkWithinProjectRoot(resolvedRoot, allowed).inside)) {
155
- return {
156
- ok: false,
157
- refusal: toCallToolResult({
158
- text: `refused: "${resolvedRoot}" is not inside any root listed in mcp.allowed_roots. A caller-supplied projectRoot is untrusted input, so this deployment pins which roots may be named; add the root to mcp.allowed_roots (or TOKEN_GOAT_MCP_ALLOWED_ROOTS) to permit it.`,
159
- code: 1
160
- })
161
- };
162
- }
163
165
  const checked = [];
164
166
  const pins = /* @__PURE__ */ new Map();
165
167
  for (const raw of targets) {
@@ -84,7 +84,7 @@ import {
84
84
  runZipRead,
85
85
  symbolNamesInFile,
86
86
  upsertNote
87
- } from "./token-goat-chunk-IYYQOPY4.mjs";
87
+ } from "./token-goat-chunk-D5IZEGN2.mjs";
88
88
  import {
89
89
  BASH_OUTPUT_SUBDIR,
90
90
  GEMINI_TOOL_NAME_MAP,
@@ -105,7 +105,7 @@ import {
105
105
  readStdinJson,
106
106
  searchRecall,
107
107
  storeWebOutput
108
- } from "./token-goat-chunk-OA3GFKP2.mjs";
108
+ } from "./token-goat-chunk-SIHYQCTM.mjs";
109
109
  import {
110
110
  AGENT_SALT_MARKER,
111
111
  CONTEXT_AUTOCOMPACT_TOKENS,
@@ -243,7 +243,7 @@ import {
243
243
  vscodeDecoderConfigured,
244
244
  walkProject,
245
245
  writeCompact
246
- } from "./token-goat-chunk-CN7GUPX6.mjs";
246
+ } from "./token-goat-chunk-I2KCEGIP.mjs";
247
247
  import {
248
248
  C,
249
249
  CONFIG_KEY_ENV_OVERRIDES,
@@ -322,7 +322,7 @@ import {
322
322
  withFileLock,
323
323
  withRetryOnLock,
324
324
  writeJsonSettings
325
- } from "./token-goat-chunk-7FWBSPCT.mjs";
325
+ } from "./token-goat-chunk-K7W3P2TJ.mjs";
326
326
  import {
327
327
  __export
328
328
  } from "./token-goat-chunk-AEX54RUZ.mjs";
@@ -13446,7 +13446,7 @@ async function cmdMcpServe() {
13446
13446
  let StdioServerTransport;
13447
13447
  try {
13448
13448
  ;
13449
- ({ createMcpServer } = await import("./token-goat-chunk-L7QLEVO7.mjs"));
13449
+ ({ createMcpServer } = await import("./token-goat-chunk-DRAIYVUI.mjs"));
13450
13450
  ({ StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js"));
13451
13451
  } catch (err2) {
13452
13452
  process.stderr.write(
@@ -13467,7 +13467,7 @@ async function cmdHook(event, opts) {
13467
13467
  if (typeof opts.harness === "string" && opts.harness.length > 0) {
13468
13468
  process.env[ENV_KEYS.HARNESS_OVERRIDE] = opts.harness;
13469
13469
  }
13470
- const { relay } = await import("./token-goat-chunk-FRMEOIRU.mjs");
13470
+ const { relay } = await import("./token-goat-chunk-Y2NH6DGZ.mjs");
13471
13471
  await relay(event);
13472
13472
  }
13473
13473
  async function cmdInstall(opts) {
@@ -14324,7 +14324,7 @@ function emitExtraFileArgsNote(command, first, extras, opts = {}) {
14324
14324
  }
14325
14325
  async function cmdCompress(opts) {
14326
14326
  try {
14327
- const bashRunner = await import("./token-goat-chunk-I6EQH27G.mjs");
14327
+ const bashRunner = await import("./token-goat-chunk-UIZVX3HN.mjs");
14328
14328
  if (opts.compress === false) {
14329
14329
  process.exitCode = bashRunner.runRaw(opts.cmd, parseTimeout(opts.timeout, bashRunner.DEFAULT_TIMEOUT_SECONDS));
14330
14330
  return;
@@ -15002,7 +15002,13 @@ function writeReplacedBuffer(file, replacedBuf, preWriteStat) {
15002
15002
  const testDelayMs = Number(process.env["TOKEN_GOAT_TEST_REPLACE_DELAY_MS"] ?? "");
15003
15003
  if (Number.isFinite(testDelayMs) && testDelayMs > 0) {
15004
15004
  process.stderr.write("TOKEN_GOAT_TEST_REPLACE_DELAY_READY\n");
15005
- sleepSync(testDelayMs);
15005
+ const until = process.env["TOKEN_GOAT_TEST_REPLACE_DELAY_UNTIL"];
15006
+ const deadline = Date.now() + testDelayMs;
15007
+ if (until !== void 0 && until !== "") {
15008
+ while (Date.now() < deadline && !fs26.existsSync(until)) sleepSync(5);
15009
+ } else {
15010
+ sleepSync(testDelayMs);
15011
+ }
15006
15012
  }
15007
15013
  let preRenameStat;
15008
15014
  try {