@danielsimonjr/mathts-workbook 0.3.22 → 0.3.24

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.
@@ -4,6 +4,11 @@ var POLLUTION_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "proto
4
4
  function parseYamlHardened(content) {
5
5
  return parseYaml(content, { schema: "core", merge: false, logLevel: "silent" });
6
6
  }
7
+ function parseYamlSafe(content) {
8
+ const value = parseYamlHardened(content);
9
+ assertNoPollution(value);
10
+ return value;
11
+ }
7
12
  function isPlainObject(value) {
8
13
  return typeof value === "object" && value !== null && !Array.isArray(value);
9
14
  }
@@ -15,6 +20,10 @@ function findPollutionKeys(value, seen = /* @__PURE__ */ new WeakSet(), found =
15
20
  for (const item of value) findPollutionKeys(item, seen, found);
16
21
  return found;
17
22
  }
23
+ const proto = Object.getPrototypeOf(value);
24
+ if (proto !== Object.prototype && proto !== null) {
25
+ found.push("__proto__");
26
+ }
18
27
  for (const key of Object.getOwnPropertyNames(value)) {
19
28
  if (POLLUTION_KEYS.has(key)) {
20
29
  found.push(key);
@@ -172,7 +181,14 @@ var IDENTIFIER_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
172
181
  function isValidIdentifier(id) {
173
182
  return typeof id === "string" && IDENTIFIER_RE.test(id);
174
183
  }
175
- var SUPPORTED_CELL_TYPES = ["code", "markdown", "data", "test", "equation", "visualization"];
184
+ var SUPPORTED_CELL_TYPES = [
185
+ "code",
186
+ "markdown",
187
+ "data",
188
+ "test",
189
+ "equation",
190
+ "visualization"
191
+ ];
176
192
  var EXECUTION_MODES = ["reactive", "sequential", "manual"];
177
193
  function detectCellType(cell) {
178
194
  for (const key of CELL_TYPE_KEYS) {
@@ -210,9 +226,7 @@ function mapCell(raw, index, errors) {
210
226
  errors.push(`Cell at index ${index}: missing "id"`);
211
227
  id = `#${index}`;
212
228
  } else if (typeof rawId !== "string" || !IDENTIFIER_RE.test(rawId)) {
213
- errors.push(
214
- `Cell "${String(rawId)}": id must be a valid identifier ([A-Za-z_][A-Za-z0-9_]*)`
215
- );
229
+ errors.push(`Cell "${String(rawId)}": id must be a valid identifier ([A-Za-z_][A-Za-z0-9_]*)`);
216
230
  id = String(rawId);
217
231
  } else {
218
232
  id = rawId;
@@ -360,11 +374,18 @@ function importWorkbook(input) {
360
374
  try {
361
375
  obj = parseYamlHardened(input);
362
376
  } catch (error) {
363
- return { success: false, errors: [`Invalid JSON/YAML: ${error instanceof Error ? error.message : String(error)}`] };
377
+ return {
378
+ success: false,
379
+ errors: [`Invalid JSON/YAML: ${error instanceof Error ? error.message : String(error)}`]
380
+ };
364
381
  }
365
382
  if (!obj || typeof obj !== "object" || Array.isArray(obj)) {
366
383
  return { success: false, errors: ['Input must be an object with a "cells" array'] };
367
384
  }
385
+ const pollution = findPollutionKeys(obj);
386
+ if (pollution.length > 0) {
387
+ return { success: false, errors: [`Disallowed key "${pollution[0]}" (prototype pollution)`] };
388
+ }
368
389
  const root = obj;
369
390
  if (!Array.isArray(root.cells)) {
370
391
  return { success: false, errors: ['Input must have a "cells" array'] };
@@ -556,8 +577,7 @@ var WorkbookExecutor = class {
556
577
  * parser, so both YAML entry points are consistent.
557
578
  */
558
579
  async executeData(cell) {
559
- const value = parseYamlHardened(cell.content);
560
- assertNoPollution(value);
580
+ const value = parseYamlSafe(cell.content);
561
581
  return value;
562
582
  }
563
583
  /**
@@ -699,7 +719,7 @@ function formatResult(value) {
699
719
  }
700
720
 
701
721
  export {
702
- parseYamlHardened,
722
+ parseYamlSafe,
703
723
  buildDependencyGraph,
704
724
  topologicalSort,
705
725
  getDependents,
@@ -8,7 +8,7 @@ import {
8
8
  isValidIdentifier,
9
9
  parseWorkbook,
10
10
  serializeWorkbook
11
- } from "./chunk-3KTM2DZC.js";
11
+ } from "./chunk-M2K7SQG2.js";
12
12
 
13
13
  // src/fs-atomic.ts
14
14
  import { writeFileSync, renameSync, unlinkSync } from "fs";
@@ -321,7 +321,7 @@ var Session = class {
321
321
 
322
322
  // src/contract.ts
323
323
  var SCHEMA_VERSION = { major: 1, minor: 0 };
324
- var VERSION = "0.3.18";
324
+ var VERSION = "0.3.24";
325
325
  var COMMAND_NAMES = [
326
326
  "run",
327
327
  "describe",
package/dist/cli.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  runWorkbookWithTimeout,
16
16
  setMetadata,
17
17
  writeFileAtomic
18
- } from "./chunk-57X3SQL6.js";
18
+ } from "./chunk-RKUVI3F6.js";
19
19
  import {
20
20
  buildDependencyGraph,
21
21
  createExecutor,
@@ -23,12 +23,12 @@ import {
23
23
  formatResult,
24
24
  importWorkbook,
25
25
  parseWorkbook,
26
- parseYamlHardened,
26
+ parseYamlSafe,
27
27
  serializeWorkbook,
28
28
  stripOutputs,
29
29
  toDOT,
30
30
  toMermaid
31
- } from "./chunk-3KTM2DZC.js";
31
+ } from "./chunk-M2K7SQG2.js";
32
32
 
33
33
  // src/cli.ts
34
34
  import { readFileSync, writeFileSync, lstatSync, realpathSync } from "fs";
@@ -51,14 +51,19 @@ function sanitizeHrefRaw(href) {
51
51
  probe = decodeURIComponent(probe);
52
52
  } catch {
53
53
  }
54
- probe = probe.trim().toLowerCase();
55
54
  if (probe.startsWith("//")) return null;
56
- if (probe.startsWith("http://") || probe.startsWith("https://") || probe.startsWith("mailto:"))
57
- return h;
58
- if (probe.startsWith("/") || probe.startsWith("./") || probe.startsWith("../") || probe.startsWith("#"))
59
- return h;
60
- if (/^[a-z][a-z0-9+.-]*:/.test(probe)) return null;
61
- return null;
55
+ try {
56
+ const url = new URL(probe);
57
+ if (url.protocol === "http:" || url.protocol === "https:" || url.protocol === "mailto:") {
58
+ return h;
59
+ }
60
+ return null;
61
+ } catch {
62
+ if (probe.startsWith("/") || probe.startsWith("./") || probe.startsWith("../") || probe.startsWith("#")) {
63
+ return h;
64
+ }
65
+ return null;
66
+ }
62
67
  }
63
68
  function sanitizeHref(href) {
64
69
  const raw = sanitizeHrefRaw(href);
@@ -872,7 +877,7 @@ function validateChartSpecs(workbook) {
872
877
  if (cell.type !== "visualization") continue;
873
878
  let spec;
874
879
  try {
875
- spec = parseYamlHardened(cell.content);
880
+ spec = parseYamlSafe(cell.content);
876
881
  } catch (error) {
877
882
  problems.push(`Cell "${cell.id}": invalid chart spec (${errMessage(error)})`);
878
883
  continue;
@@ -1082,7 +1087,7 @@ function buildRenderDoc(workbook, byId, format = "svg") {
1082
1087
  if (c.type === "visualization") {
1083
1088
  rc.type = "chart";
1084
1089
  try {
1085
- const spec = parseYamlHardened(c.content);
1090
+ const spec = parseYamlSafe(c.content);
1086
1091
  const rendered = renderChart(
1087
1092
  { type: spec?.type, title: spec?.title, xLabel: spec?.x?.label, yLabel: spec?.y?.label },
1088
1093
  lookup(spec?.x?.data),
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  renameCell,
12
12
  runWorkbookWithTimeout,
13
13
  setMetadata
14
- } from "./chunk-57X3SQL6.js";
14
+ } from "./chunk-RKUVI3F6.js";
15
15
  import {
16
16
  WorkbookExecutor,
17
17
  buildDependencyGraph,
@@ -26,7 +26,7 @@ import {
26
26
  stripOutputs,
27
27
  toMermaid,
28
28
  topologicalSort
29
- } from "./chunk-3KTM2DZC.js";
29
+ } from "./chunk-M2K7SQG2.js";
30
30
  export {
31
31
  SCHEMA_VERSION,
32
32
  Session,
@@ -2,7 +2,7 @@ import {
2
2
  createExecutor,
3
3
  formatResult,
4
4
  parseWorkbook
5
- } from "./chunk-3KTM2DZC.js";
5
+ } from "./chunk-M2K7SQG2.js";
6
6
 
7
7
  // src/run-worker.ts
8
8
  import { parentPort, workerData } from "worker_threads";
package/package.json CHANGED
@@ -1,64 +1,64 @@
1
- {
2
- "name": "@danielsimonjr/mathts-workbook",
3
- "version": "0.3.22",
4
- "description": "Scientific workbook runtime for MathTS (.mtsw format)",
5
- "author": "Daniel Simon Jr.",
6
- "license": "MIT",
7
- "type": "module",
8
- "main": "./dist/index.js",
9
- "module": "./dist/index.js",
10
- "types": "./dist/index.d.ts",
11
- "bin": {
12
- "mtsw": "./dist/cli.js"
13
- },
14
- "exports": {
15
- ".": {
16
- "import": "./dist/index.js",
17
- "types": "./dist/index.d.ts"
18
- }
19
- },
20
- "files": [
21
- "dist",
22
- "README.md"
23
- ],
24
- "scripts": {
25
- "build": "tsup",
26
- "dev": "tsup --watch",
27
- "test": "vitest run",
28
- "test:watch": "vitest",
29
- "test:coverage": "vitest run --coverage",
30
- "typecheck": "tsc --noEmit",
31
- "lint": "eslint src --ext .ts",
32
- "lint:fix": "eslint src --ext .ts --fix",
33
- "clean": "rm -rf dist",
34
- "build:prod": "tsup --minify --treeshake"
35
- },
36
- "dependencies": {
37
- "@danielsimonjr/mathts-core": "^0.13.1",
38
- "@danielsimonjr/mathts-expression": "^0.6.7",
39
- "@danielsimonjr/mathts-functions": "^0.61.0",
40
- "@danielsimonjr/mathts-plot": "^0.3.48",
41
- "yaml": "^2.3.0"
42
- },
43
- "devDependencies": {
44
- "@types/node": "^25.5.2",
45
- "tsup": "^8.0.0",
46
- "typescript": "^5.3.0",
47
- "vitest": "^4.1.5"
48
- },
49
- "publishConfig": {
50
- "access": "public"
51
- },
52
- "repository": {
53
- "type": "git",
54
- "url": "https://github.com/danielsimonjr/mathts",
55
- "directory": "workbook"
56
- },
57
- "keywords": [
58
- "notebook",
59
- "workbook",
60
- "scientific-computing",
61
- "reactive",
62
- "yaml"
63
- ]
64
- }
1
+ {
2
+ "name": "@danielsimonjr/mathts-workbook",
3
+ "version": "0.3.24",
4
+ "description": "Scientific workbook runtime for MathTS (.mtsw format)",
5
+ "author": "Daniel Simon Jr.",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "main": "./dist/index.js",
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "bin": {
12
+ "mtsw": "dist/cli.js"
13
+ },
14
+ "exports": {
15
+ ".": {
16
+ "import": "./dist/index.js",
17
+ "types": "./dist/index.d.ts"
18
+ }
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "README.md"
23
+ ],
24
+ "scripts": {
25
+ "build": "tsup",
26
+ "dev": "tsup --watch",
27
+ "test": "vitest run",
28
+ "test:watch": "vitest",
29
+ "test:coverage": "vitest run --coverage",
30
+ "typecheck": "tsc --noEmit",
31
+ "lint": "eslint src --ext .ts",
32
+ "lint:fix": "eslint src --ext .ts --fix",
33
+ "clean": "rm -rf dist",
34
+ "build:prod": "tsup --minify --treeshake"
35
+ },
36
+ "dependencies": {
37
+ "@danielsimonjr/mathts-core": "^0.14.1",
38
+ "@danielsimonjr/mathts-expression": "^0.7.1",
39
+ "@danielsimonjr/mathts-functions": "^0.63.0",
40
+ "@danielsimonjr/mathts-plot": "^0.4.1",
41
+ "yaml": "^2.3.0"
42
+ },
43
+ "devDependencies": {
44
+ "@types/node": "^25.5.2",
45
+ "tsup": "^8.0.0",
46
+ "typescript": "^5.3.0",
47
+ "vitest": "^4.1.10"
48
+ },
49
+ "publishConfig": {
50
+ "access": "public"
51
+ },
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "git+https://github.com/danielsimonjr/MathTS.git",
55
+ "directory": "workbook"
56
+ },
57
+ "keywords": [
58
+ "notebook",
59
+ "workbook",
60
+ "scientific-computing",
61
+ "reactive",
62
+ "yaml"
63
+ ]
64
+ }