@extenshi/cli 0.8.0 → 0.8.1

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.
package/dist/icon.d.ts CHANGED
@@ -11,6 +11,7 @@
11
11
  * command only renders the verification page. The paid, server-side
12
12
  * generation path lives in dojo and is metered separately.
13
13
  */
14
+ import { scrubSvgMarkup } from './svg-scrub.js';
14
15
  export interface IconPreviewCmdOptions {
15
16
  /** Extension display name shown in the mockups (default: derived from the file name). */
16
17
  name?: string;
@@ -23,10 +24,10 @@ export interface IconPreviewCmdOptions {
23
24
  * Strip scripting constructs from untrusted SVG source. The preview page only
24
25
  * ever embeds the icon through <img src="data:..."> (where scripts never run),
25
26
  * but the raw source is also shipped inside the export ZIP — so it must not
26
- * carry executable payloads either. Regex-based because the CLI runs in Node
27
- * (no DOMParser); patterns intentionally over-remove rather than under-remove.
27
+ * carry executable payloads either. The scrubber itself lives in svg-scrub.ts
28
+ * (shared byte-identical with dojo); re-exported here under its historical name.
28
29
  */
29
- export declare function sanitizeSvgSource(svg: string): string;
30
+ export declare const sanitizeSvgSource: typeof scrubSvgMarkup;
30
31
  /** Human-ish display name from a file name: "my-cool_icon.svg" → "My Cool Icon". */
31
32
  export declare function displayNameFromFile(filePath: string): string;
32
33
  /** Resolve the HTML destination: explicit --output wins, else auto-named in cwd. */
@@ -1 +1 @@
1
- {"version":3,"file":"icon.d.ts","sourceRoot":"","sources":["../src/icon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAWH,MAAM,WAAW,qBAAqB;IACrC,yFAAyF;IACzF,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,qFAAqF;IACrF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oFAAoF;IACpF,IAAI,CAAC,EAAE,OAAO,CAAA;CACd;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAiBrD;AAED,oFAAoF;AACpF,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAK5D;AAED,oFAAoF;AACpF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIvF;AAmBD;;;GAGG;AACH,wBAAsB,cAAc,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,qBAAqB,EAC3B,UAAU,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAkDf"}
1
+ {"version":3,"file":"icon.d.ts","sourceRoot":"","sources":["../src/icon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAM/C,MAAM,WAAW,qBAAqB;IACrC,yFAAyF;IACzF,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,qFAAqF;IACrF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oFAAoF;IACpF,IAAI,CAAC,EAAE,OAAO,CAAA;CACd;AAED;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,uBAAiB,CAAA;AAE/C,oFAAoF;AACpF,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAK5D;AAED,oFAAoF;AACpF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIvF;AAmBD;;;GAGG;AACH,wBAAsB,cAAc,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,qBAAqB,EAC3B,UAAU,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAkDf"}
package/dist/icon.js CHANGED
@@ -15,6 +15,7 @@ import { spawn } from 'node:child_process';
15
15
  import * as fs from 'node:fs';
16
16
  import * as path from 'node:path';
17
17
  import { renderIconPreviewHtml } from './icon-preview.js';
18
+ import { scrubSvgMarkup } from './svg-scrub.js';
18
19
  const MAX_SVG_BYTES = 512 * 1024;
19
20
  const MAX_PNG_BYTES = 2 * 1024 * 1024;
20
21
  const PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
@@ -22,25 +23,10 @@ const PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0
22
23
  * Strip scripting constructs from untrusted SVG source. The preview page only
23
24
  * ever embeds the icon through <img src="data:..."> (where scripts never run),
24
25
  * but the raw source is also shipped inside the export ZIP — so it must not
25
- * carry executable payloads either. Regex-based because the CLI runs in Node
26
- * (no DOMParser); patterns intentionally over-remove rather than under-remove.
26
+ * carry executable payloads either. The scrubber itself lives in svg-scrub.ts
27
+ * (shared byte-identical with dojo); re-exported here under its historical name.
27
28
  */
28
- export function sanitizeSvgSource(svg) {
29
- return (svg
30
- // XML prolog junk that has no place in an icon
31
- .replace(/<!DOCTYPE[\s\S]*?>/gi, '')
32
- .replace(/<!ENTITY[\s\S]*?>/gi, '')
33
- // executable containers, paired or self-closing
34
- .replace(/<\s*(script|foreignObject|iframe|object|embed)\b[\s\S]*?<\s*\/\s*\1\s*>/gi, '')
35
- .replace(/<\s*(script|foreignObject|iframe|object|embed)\b[^>]*\/?>/gi, '')
36
- // inline event handlers: onload="..." / onclick='...' / onerror=x
37
- .replace(/\son[a-z]+\s*=\s*"[^"]*"/gi, '')
38
- .replace(/\son[a-z]+\s*=\s*'[^']*'/gi, '')
39
- .replace(/\son[a-z]+\s*=\s*[^\s>]+/gi, '')
40
- // javascript:/data: link targets
41
- .replace(/\s(href|xlink:href)\s*=\s*"(\s*(javascript|data):)[^"]*"/gi, '')
42
- .replace(/\s(href|xlink:href)\s*=\s*'(\s*(javascript|data):)[^']*'/gi, ''));
43
- }
29
+ export const sanitizeSvgSource = scrubSvgMarkup;
44
30
  /** Human-ish display name from a file name: "my-cool_icon.svg" → "My Cool Icon". */
45
31
  export function displayNameFromFile(filePath) {
46
32
  const base = path.basename(filePath).replace(/\.(svg|png)$/i, '');
package/dist/icon.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"icon.js","sourceRoot":"","sources":["../src/icon.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"icon.js","sourceRoot":"","sources":["../src/icon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Canonical regex-based SVG scrubber, shared by the offline CLI preview and the
3
+ * hosted dojo generator so both strip the exact same constructs.
4
+ *
5
+ * Regex-based (not DOM-based) on purpose: it must run in Node with no DOMParser
6
+ * — the CLI runs offline in a terminal, and the dojo API route runs server-side.
7
+ * Patterns intentionally over-remove rather than under-remove: an icon has no
8
+ * legitimate use for scripts, styles, animation, or external references.
9
+ *
10
+ * SINGLE SOURCE, TWO COPIES: this file exists byte-identical at
11
+ * tools/extenshi-cli/src/svg-scrub.ts (canonical — edit here)
12
+ * dojo/src/lib/tools/svg-scrub.ts (synced copy for the dojo build)
13
+ * because the published @extenshi/cli npm package cannot depend on unpublished
14
+ * workspace packages, and dojo's Docker build does not build the CLI package.
15
+ * A test in tools/extenshi-cli/src/icon.test.ts fails CI when the copies drift;
16
+ * after editing, run: cp tools/extenshi-cli/src/svg-scrub.ts dojo/src/lib/tools/svg-scrub.ts
17
+ *
18
+ * This is the same rationale as icon-preview.ts (see the note there).
19
+ */
20
+ export declare const SVG_DANGEROUS_TAGS: readonly ["script", "style", "foreignObject", "iframe", "object", "embed", "applet", "form", "input", "textarea", "select", "button", "animate", "animateTransform", "animateMotion", "set"];
21
+ /**
22
+ * Strip scripting / active constructs from untrusted SVG source. Safe to run on
23
+ * anything: LLM output (dojo), a developer's own file (CLI). The result is only
24
+ * ever consumed as image data (rendered through `<img src="data:…">`, where
25
+ * scripts never execute, and rasterized on a canvas), but we scrub anyway so the
26
+ * raw string is also safe if written to a file or opened directly.
27
+ */
28
+ export declare function scrubSvgMarkup(svg: string): string;
29
+ //# sourceMappingURL=svg-scrub.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svg-scrub.d.ts","sourceRoot":"","sources":["../src/svg-scrub.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,eAAO,MAAM,kBAAkB,8LAiBrB,CAAA;AAIV;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA0BlD"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Canonical regex-based SVG scrubber, shared by the offline CLI preview and the
3
+ * hosted dojo generator so both strip the exact same constructs.
4
+ *
5
+ * Regex-based (not DOM-based) on purpose: it must run in Node with no DOMParser
6
+ * — the CLI runs offline in a terminal, and the dojo API route runs server-side.
7
+ * Patterns intentionally over-remove rather than under-remove: an icon has no
8
+ * legitimate use for scripts, styles, animation, or external references.
9
+ *
10
+ * SINGLE SOURCE, TWO COPIES: this file exists byte-identical at
11
+ * tools/extenshi-cli/src/svg-scrub.ts (canonical — edit here)
12
+ * dojo/src/lib/tools/svg-scrub.ts (synced copy for the dojo build)
13
+ * because the published @extenshi/cli npm package cannot depend on unpublished
14
+ * workspace packages, and dojo's Docker build does not build the CLI package.
15
+ * A test in tools/extenshi-cli/src/icon.test.ts fails CI when the copies drift;
16
+ * after editing, run: cp tools/extenshi-cli/src/svg-scrub.ts dojo/src/lib/tools/svg-scrub.ts
17
+ *
18
+ * This is the same rationale as icon-preview.ts (see the note there).
19
+ */
20
+ // Executable / interactive / animated containers that have no place in a flat
21
+ // icon. The DOM-based sanitizer in dojo (svg-sanitize.ts → DANGEROUS_ELEMENTS)
22
+ // derives its element set from this list, so the two sanitizers can never
23
+ // disagree on which elements are dangerous.
24
+ export const SVG_DANGEROUS_TAGS = [
25
+ 'script',
26
+ 'style',
27
+ 'foreignObject',
28
+ 'iframe',
29
+ 'object',
30
+ 'embed',
31
+ 'applet',
32
+ 'form',
33
+ 'input',
34
+ 'textarea',
35
+ 'select',
36
+ 'button',
37
+ 'animate',
38
+ 'animateTransform',
39
+ 'animateMotion',
40
+ 'set',
41
+ ];
42
+ const TAGS_ALT = SVG_DANGEROUS_TAGS.join('|');
43
+ /**
44
+ * Strip scripting / active constructs from untrusted SVG source. Safe to run on
45
+ * anything: LLM output (dojo), a developer's own file (CLI). The result is only
46
+ * ever consumed as image data (rendered through `<img src="data:…">`, where
47
+ * scripts never execute, and rasterized on a canvas), but we scrub anyway so the
48
+ * raw string is also safe if written to a file or opened directly.
49
+ */
50
+ export function scrubSvgMarkup(svg) {
51
+ return (svg
52
+ // XML prolog junk (DOCTYPE/ENTITY → billion-laughs / XXE vectors).
53
+ // Handle the internal-subset form `<!DOCTYPE x [ … ]>` first (a
54
+ // non-greedy `<!DOCTYPE …?>` would stop at the first `>` inside the
55
+ // brackets and leave `]>` behind), then the simple form and entities.
56
+ .replace(/<!DOCTYPE[^>[]*\[[\s\S]*?\]\s*>/gi, '')
57
+ .replace(/<!DOCTYPE[^>]*>/gi, '')
58
+ .replace(/<!ENTITY[\s\S]*?>/gi, '')
59
+ // executable / interactive / animation containers, paired or self-closing.
60
+ // One pass, non-greedy: multiply-nested tags of the SAME type (e.g.
61
+ // `<script>a<script>b</script>c</script>`) are not fully unwrapped, but
62
+ // the leftover text is inert and the render context (<img src="data:…">)
63
+ // never executes it — the self-closing sweep below catches stray opens.
64
+ .replace(new RegExp(`<\\s*(${TAGS_ALT})\\b[\\s\\S]*?<\\s*/\\s*\\1\\s*>`, 'gi'), '')
65
+ .replace(new RegExp(`<\\s*(${TAGS_ALT})\\b[^>]*/?>`, 'gi'), '')
66
+ // inline event handlers: onload="…" / onclick='…' / onerror=x
67
+ .replace(/\son[a-z]+\s*=\s*"[^"]*"/gi, '')
68
+ .replace(/\son[a-z]+\s*=\s*'[^']*'/gi, '')
69
+ .replace(/\son[a-z]+\s*=\s*[^\s>]+/gi, '')
70
+ // javascript:/data: link targets on href / xlink:href
71
+ .replace(/\s(href|xlink:href)\s*=\s*"(\s*(javascript|data):)[^"]*"/gi, '')
72
+ .replace(/\s(href|xlink:href)\s*=\s*'(\s*(javascript|data):)[^']*'/gi, '')
73
+ .trim());
74
+ }
75
+ //# sourceMappingURL=svg-scrub.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svg-scrub.js","sourceRoot":"","sources":["../src/svg-scrub.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,8EAA8E;AAC9E,+EAA+E;AAC/E,0EAA0E;AAC1E,4CAA4C;AAC5C,MAAM,CAAC,MAAM,kBAAkB,GAAG;IACjC,QAAQ;IACR,OAAO;IACP,eAAe;IACf,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,MAAM;IACN,OAAO;IACP,UAAU;IACV,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,kBAAkB;IAClB,eAAe;IACf,KAAK;CACI,CAAA;AAEV,MAAM,QAAQ,GAAG,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAE7C;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACzC,OAAO,CACN,GAAG;QACF,mEAAmE;QACnE,gEAAgE;QAChE,oEAAoE;QACpE,sEAAsE;SACrE,OAAO,CAAC,mCAAmC,EAAE,EAAE,CAAC;SAChD,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC;SAChC,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC;QACnC,2EAA2E;QAC3E,oEAAoE;QACpE,wEAAwE;QACxE,yEAAyE;QACzE,wEAAwE;SACvE,OAAO,CAAC,IAAI,MAAM,CAAC,SAAS,QAAQ,kCAAkC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;SAClF,OAAO,CAAC,IAAI,MAAM,CAAC,SAAS,QAAQ,cAAc,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;QAC/D,8DAA8D;SAC7D,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC;SACzC,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC;SACzC,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC;QAC1C,sDAAsD;SACrD,OAAO,CAAC,4DAA4D,EAAE,EAAE,CAAC;SACzE,OAAO,CAAC,4DAA4D,EAAE,EAAE,CAAC;SACzE,IAAI,EAAE,CACR,CAAA;AACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@extenshi/cli",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "Pre-publish security scanner for browser extensions",
5
5
  "type": "module",
6
6
  "publishConfig": {