@ts-graphviz/ast 3.0.5-next-dc3ef34316f5642c416711cb6a50704dbef7bb64 → 3.0.5-next-4296b4e0cf17f36cc385c2ce93ec7ec89bd4a73a

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 (3) hide show
  1. package/CHANGELOG.md +118 -2
  2. package/lib/ast.js +11 -2
  3. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,9 +1,71 @@
1
1
  # @ts-graphviz/ast
2
2
 
3
- ## 3.0.5-next-dc3ef34316f5642c416711cb6a50704dbef7bb64
3
+ ## 3.0.5-next-4296b4e0cf17f36cc385c2ce93ec7ec89bd4a73a
4
4
 
5
5
  ### Patch Changes
6
6
 
7
+ - [#1536](https://github.com/ts-graphviz/ts-graphviz/pull/1536) [`4296b4e`](https://github.com/ts-graphviz/ts-graphviz/commit/4296b4e0cf17f36cc385c2ce93ec7ec89bd4a73a) Thanks [@kamiazya](https://github.com/kamiazya)! - Add null byte sanitization and comprehensive security tests for DOT injection prevention
8
+
9
+ ## Security Fix
10
+
11
+ ### Null Byte Handling
12
+
13
+ Added null byte removal to the `escape()` function to prevent Graphviz parsing errors. Graphviz treats null bytes (`\0`) as string terminators, causing syntax errors when encountered in quoted strings. This is now consistent with the `escapeComment()` function which already strips null bytes.
14
+
15
+ **Why this matters:**
16
+
17
+ - Prevents "syntax error in line X scanning a quoted string" errors in Graphviz
18
+ - Removes potential attack vector for causing parser failures
19
+ - Aligns with existing comment sanitization behavior
20
+
21
+ ## Test Coverage Additions
22
+
23
+ ### Unit Tests (escape.test.ts)
24
+
25
+ Added 16 new test cases covering various DOT injection attack vectors:
26
+
27
+ - Semicolon-based statement injection
28
+ - Edge operator injection attempts
29
+ - Graph termination injection via quotes and newlines
30
+ - Closing brace injection
31
+ - Attribute injection with equals sign
32
+ - Multiple quote injection attempts
33
+ - Mixed newlines and quotes
34
+ - Subgraph injection attempts
35
+ - Edge chain injection
36
+ - HTML-like label injection with quotes
37
+ - Port injection
38
+ - Already-escaped string handling
39
+ - Null byte removal (2 tests)
40
+ - Unicode strings with quotes
41
+ - Strict keyword injection
42
+
43
+ ### Integration Tests (to-dot.test.ts)
44
+
45
+ Added 10 new end-to-end test cases:
46
+
47
+ - Statement injection in node IDs (semicolon)
48
+ - Edge operator injection in node IDs
49
+ - Graph termination injection via quotes and newlines
50
+ - Statement injection in subgraph IDs
51
+ - Attribute value injection prevention
52
+ - Edge ID injection prevention
53
+ - Multiple quotes in node ID
54
+ - Port specification injection
55
+ - Graph comment injection
56
+ - Node comment injection
57
+
58
+ ## Validation
59
+
60
+ All tests confirm that the existing escape implementation correctly prevents DOT language injection by:
61
+
62
+ - Escaping double quotes (`"` → `\"`)
63
+ - Escaping newlines (`\n` → `\n`)
64
+ - Escaping carriage returns (`\r` → `\r`)
65
+ - Ensuring malicious strings are treated as literal identifiers, not DOT syntax
66
+
67
+ Verified with actual Graphviz parser (version 13.1.1) that escaped output renders safely without executing injected DOT code.
68
+
7
69
  - [#1533](https://github.com/ts-graphviz/ts-graphviz/pull/1533) [`ed770be`](https://github.com/ts-graphviz/ts-graphviz/commit/ed770be7fffc93b9171198c9a84270df7477185d) Thanks [@kamiazya](https://github.com/kamiazya)! - Add memory exhaustion protection with input size and AST node count limits
8
70
 
9
71
  Addresses security vulnerability where extremely large inputs or inputs with excessive elements could cause memory exhaustion, leading to application crashes and potential DoS attacks.
@@ -63,8 +125,62 @@
63
125
 
64
126
  - [#1532](https://github.com/ts-graphviz/ts-graphviz/pull/1532) [`dc3ef34`](https://github.com/ts-graphviz/ts-graphviz/commit/dc3ef34316f5642c416711cb6a50704dbef7bb64) Thanks [@dependabot](https://github.com/apps/dependabot)! - build(deps-dev): bump vite from 7.0.2 to 7.0.8 in the npm_and_yarn group across 1 directory
65
127
 
128
+ - [#1535](https://github.com/ts-graphviz/ts-graphviz/pull/1535) [`11f7126`](https://github.com/ts-graphviz/ts-graphviz/commit/11f7126347816f64f7892c8608b5e3bf1a826670) Thanks [@kamiazya](https://github.com/kamiazya)! - Fix comment injection vulnerability in block comments
129
+
130
+ Addresses security vulnerability where malicious `*/` sequences in comment content could break out of block comment context and inject arbitrary DOT syntax.
131
+
132
+ ## Security Enhancement
133
+
134
+ ### Comment Content Escaping
135
+
136
+ - Added `escapeComment()` utility function to sanitize comment content
137
+ - Block comments: Breaks up `*/` sequences using zero-width space (U+200B) to prevent early comment termination
138
+ - All comment types: Removes null bytes that could cause parsing issues
139
+ - Follows C/C++ and DOT language specifications where block comments cannot be nested
140
+
141
+ ## Changes
142
+
143
+ ### New Utility Function
144
+
145
+ - `escapeComment()` in `packages/ast/src/dot-shim/printer/plugins/utils/escape-comment.ts`
146
+ - Prevents comment injection by inserting zero-width space between `*` and `/`
147
+ - Maintains visual appearance while preventing syntax injection
148
+ - Verified to work with Graphviz 13.1.1
149
+
150
+ ### Updated Components
151
+
152
+ - `CommentPrintPlugin` now applies escaping before outputting comment content
153
+ - All comment values are sanitized at print time, not at creation time
154
+ - Maintains backward compatibility with existing AST structures
155
+
156
+ ### Testing
157
+
158
+ - 11 unit tests for `escapeComment()` function covering:
159
+ - Block comment injection prevention
160
+ - Multiple `*/` sequence handling
161
+ - Null byte removal
162
+ - Normal content preservation
163
+ - Integration tests in `stringify.test.ts` for end-to-end verification
164
+ - All existing tests continue to pass
165
+
166
+ ## Security Impact
167
+
168
+ - Prevents DOT syntax injection via malicious comment content
169
+ - Blocks attempts to escape comment context and inject arbitrary graph definitions
170
+ - Protects against parser manipulation through crafted comment values
171
+ - Zero-width space approach is standards-compliant and validated with official Graphviz parser
172
+
173
+ ## Technical Details
174
+
175
+ According to C/C++ and DOT language specifications, block comments (`/* */`) cannot be nested and there is no escape sequence for the closing delimiter within comments. The standard workaround is to insert a zero-width space (U+200B) between `*` and `/`, which:
176
+
177
+ - Prevents early comment termination
178
+ - Preserves visual appearance (zero-width character is invisible)
179
+ - Is correctly handled by Graphviz parser (tested with version 13.1.1)
180
+ - Follows industry best practices for comment sanitization
181
+
66
182
  - Updated dependencies [[`dc3ef34`](https://github.com/ts-graphviz/ts-graphviz/commit/dc3ef34316f5642c416711cb6a50704dbef7bb64)]:
67
- - @ts-graphviz/common@3.0.4-next-dc3ef34316f5642c416711cb6a50704dbef7bb64
183
+ - @ts-graphviz/common@3.0.4-next-4296b4e0cf17f36cc385c2ce93ec7ec89bd4a73a
68
184
 
69
185
  ## 3.0.4
70
186
 
package/lib/ast.js CHANGED
@@ -2865,6 +2865,14 @@ const AttributePrintPlugin = {
2865
2865
  yield ";";
2866
2866
  }
2867
2867
  };
2868
+ const ZERO_WIDTH_SPACE = "​";
2869
+ function escapeComment(value, kind) {
2870
+ let escaped = value.replace(/\0/g, "");
2871
+ if (kind === "Block") {
2872
+ escaped = escaped.replace(/\*\//g, `*${ZERO_WIDTH_SPACE}/`);
2873
+ }
2874
+ return escaped;
2875
+ }
2868
2876
  const EOL_PATTERN = /\r?\n/;
2869
2877
  const paddingMap = {
2870
2878
  Block: " * ",
@@ -2880,7 +2888,8 @@ const CommentPrintPlugin = {
2880
2888
  if (ast.kind === "Block") {
2881
2889
  yield* ["/**", context.EOL];
2882
2890
  }
2883
- const lines = ast.value.split(EOL_PATTERN);
2891
+ const escapedValue = escapeComment(ast.value, ast.kind);
2892
+ const lines = escapedValue.split(EOL_PATTERN);
2884
2893
  const lineLength = lines.length;
2885
2894
  for (let i = 0; i < lineLength; i++) {
2886
2895
  yield padding;
@@ -2938,7 +2947,7 @@ const GraphPrintPlugin = {
2938
2947
  yield "}";
2939
2948
  }
2940
2949
  };
2941
- const escape = (value) => value.replace(/(?<!\\)"|[\r\n]/g, escapeReplacer);
2950
+ const escape = (value) => value.replace(/\0/g, "").replace(/(?<!\\)"|[\r\n]/g, escapeReplacer);
2942
2951
  const escapeMap = {
2943
2952
  "\r": String.raw`\r`,
2944
2953
  "\n": String.raw`\n`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ts-graphviz/ast",
3
- "version": "3.0.5-next-dc3ef34316f5642c416711cb6a50704dbef7bb64",
3
+ "version": "3.0.5-next-4296b4e0cf17f36cc385c2ce93ec7ec89bd4a73a",
4
4
  "description": "Graphviz AST(Abstract Syntax Tree) Utilities",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/ts-graphviz/ts-graphviz#readme",
@@ -33,7 +33,7 @@
33
33
  "./package.json": "./package.json"
34
34
  },
35
35
  "dependencies": {
36
- "@ts-graphviz/common": "^3.0.4-next-dc3ef34316f5642c416711cb6a50704dbef7bb64"
36
+ "@ts-graphviz/common": "^3.0.4-next-4296b4e0cf17f36cc385c2ce93ec7ec89bd4a73a"
37
37
  },
38
38
  "devDependencies": {
39
39
  "peggy": "^5.0.6",