cbrowser 19.2.0 → 19.2.2

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 (70) hide show
  1. package/README.md +2 -2
  2. package/dist/analysis/accessibility-empathy.d.ts +6 -0
  3. package/dist/analysis/accessibility-empathy.d.ts.map +1 -1
  4. package/dist/analysis/accessibility-empathy.js +28 -77
  5. package/dist/analysis/accessibility-empathy.js.map +1 -1
  6. package/dist/analysis/competitive-benchmark.js +2 -2
  7. package/dist/analysis/competitive-benchmark.js.map +1 -1
  8. package/dist/analysis/persona-comparison.d.ts.map +1 -1
  9. package/dist/analysis/persona-comparison.js +5 -1
  10. package/dist/analysis/persona-comparison.js.map +1 -1
  11. package/dist/browser.js +2 -2
  12. package/dist/browser.js.map +1 -1
  13. package/dist/cli.js +44 -7
  14. package/dist/cli.js.map +1 -1
  15. package/dist/daemon.d.ts +2 -0
  16. package/dist/daemon.d.ts.map +1 -1
  17. package/dist/daemon.js +8 -1
  18. package/dist/daemon.js.map +1 -1
  19. package/dist/mcp-server-remote.d.ts +3 -0
  20. package/dist/mcp-server-remote.d.ts.map +1 -1
  21. package/dist/mcp-server-remote.js +12 -1
  22. package/dist/mcp-server-remote.js.map +1 -1
  23. package/dist/mcp-tools/account-personas.d.ts +3 -2
  24. package/dist/mcp-tools/account-personas.d.ts.map +1 -1
  25. package/dist/mcp-tools/account-personas.js +13 -4
  26. package/dist/mcp-tools/account-personas.js.map +1 -1
  27. package/dist/mcp-tools/base/advanced-interaction-tools.js +1 -1
  28. package/dist/mcp-tools/base/advanced-interaction-tools.js.map +1 -1
  29. package/dist/mcp-tools/base/audit-tools.d.ts.map +1 -1
  30. package/dist/mcp-tools/base/audit-tools.js +49 -15
  31. package/dist/mcp-tools/base/audit-tools.js.map +1 -1
  32. package/dist/mcp-tools/base/browser-state-tools.d.ts.map +1 -1
  33. package/dist/mcp-tools/base/browser-state-tools.js +25 -4
  34. package/dist/mcp-tools/base/browser-state-tools.js.map +1 -1
  35. package/dist/mcp-tools/base/cognitive-tools.d.ts.map +1 -1
  36. package/dist/mcp-tools/base/cognitive-tools.js +14 -2
  37. package/dist/mcp-tools/base/cognitive-tools.js.map +1 -1
  38. package/dist/mcp-tools/base/gif-tools.d.ts +19 -0
  39. package/dist/mcp-tools/base/gif-tools.d.ts.map +1 -1
  40. package/dist/mcp-tools/base/gif-tools.js +53 -24
  41. package/dist/mcp-tools/base/gif-tools.js.map +1 -1
  42. package/dist/mcp-tools/base/persona-comparison-tools.d.ts.map +1 -1
  43. package/dist/mcp-tools/base/persona-comparison-tools.js +44 -28
  44. package/dist/mcp-tools/base/persona-comparison-tools.js.map +1 -1
  45. package/dist/mcp-tools/base/values-tools.d.ts.map +1 -1
  46. package/dist/mcp-tools/base/values-tools.js +12 -0
  47. package/dist/mcp-tools/base/values-tools.js.map +1 -1
  48. package/dist/mcp-tools/base/visual-testing-tools.d.ts +17 -0
  49. package/dist/mcp-tools/base/visual-testing-tools.d.ts.map +1 -1
  50. package/dist/mcp-tools/base/visual-testing-tools.js +184 -148
  51. package/dist/mcp-tools/base/visual-testing-tools.js.map +1 -1
  52. package/dist/mcp-tools/inline-image.d.ts +82 -0
  53. package/dist/mcp-tools/inline-image.d.ts.map +1 -0
  54. package/dist/mcp-tools/inline-image.js +163 -0
  55. package/dist/mcp-tools/inline-image.js.map +1 -0
  56. package/dist/personas.d.ts +37 -0
  57. package/dist/personas.d.ts.map +1 -1
  58. package/dist/personas.js +137 -3
  59. package/dist/personas.js.map +1 -1
  60. package/dist/security/audit-wrapper.d.ts.map +1 -1
  61. package/dist/security/audit-wrapper.js +1 -0
  62. package/dist/security/audit-wrapper.js.map +1 -1
  63. package/dist/security/script-gate.d.ts +33 -0
  64. package/dist/security/script-gate.d.ts.map +1 -0
  65. package/dist/security/script-gate.js +37 -0
  66. package/dist/security/script-gate.js.map +1 -0
  67. package/dist/security/tool-permissions.d.ts.map +1 -1
  68. package/dist/security/tool-permissions.js +4 -0
  69. package/dist/security/tool-permissions.js.map +1 -1
  70. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -24,6 +24,7 @@ import { DEVICE_PRESETS, LOCATION_PRESETS } from "./types.js";
24
24
  import { startMcpServer } from "./mcp-server.js";
25
25
  import { startRemoteMcpServer } from "./mcp-server-remote.js";
26
26
  import { startDaemon, stopDaemon, getDaemonStatus, isDaemonRunning, sendToDaemon, runDaemonServer } from "./daemon.js";
27
+ import { evaluateScriptRefusal } from "./security/script-gate.js";
27
28
  import { getStatusInfo, formatStatus, getDataDir, getPaths } from "./config.js";
28
29
  import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
29
30
  import { resolveCookieDomain, hostFromUrl } from "./utils.js";
@@ -105,6 +106,9 @@ EXTRACTION
105
106
 
106
107
  SCRIPTING
107
108
  evaluate "<js>" Run JavaScript in the page and print the result
109
+ --force Required: page script is red zone (it can click,
110
+ submit or delete without the element gate), so
111
+ evaluate refuses and runs nothing without it
108
112
  --file <path> Read the script from a file instead of argv
109
113
  --arg <json> Argument for the script (repeatable, JSON-typed)
110
114
  --json Always print JSON
@@ -112,9 +116,9 @@ SCRIPTING
112
116
  --wait-for <selector> Wait for the selector before evaluating
113
117
  --expect-truthy Exit 1 when the result is falsy (CI assertion)
114
118
  Examples:
115
- cbrowser evaluate "document.title"
116
- cbrowser evaluate --file check.js --arg '"#main"' --expect-truthy
117
- cbrowser evaluate "(sel) => !!document.querySelector(sel)" --arg '"nav"'
119
+ cbrowser evaluate "document.title" --force
120
+ cbrowser evaluate --file check.js --arg '"#main"' --expect-truthy --force
121
+ cbrowser evaluate "(sel) => !!document.querySelector(sel)" --arg '"nav"' --force
118
122
 
119
123
  KEYBOARD
120
124
  keyboard <token> [token...] Send a key sequence: chords, keys and text
@@ -995,8 +999,8 @@ const COMMAND_FLAGS = {
995
999
  // this command deletes credentials, so "--kep-config did nothing" is a bad
996
1000
  // way to find out.
997
1001
  uninstall: ["yes", "keep-config"],
998
- evaluate: ["file", "arg", "json", "raw", "wait-for", "timeout", "expect-truthy"],
999
- eval: ["file", "arg", "json", "raw", "wait-for", "timeout", "expect-truthy"],
1002
+ evaluate: ["file", "arg", "json", "raw", "wait-for", "timeout", "expect-truthy", "force"],
1003
+ eval: ["file", "arg", "json", "raw", "wait-for", "timeout", "expect-truthy", "force"],
1000
1004
  keyboard: ["delay", "selector", "hold", "repeat", "text", "force"],
1001
1005
  "test-suite": [
1002
1006
  "capture", "capture-fps", "capture-format", "capture-out",
@@ -1740,10 +1744,23 @@ function reportAutoCapture(capture) {
1740
1744
  // =========================================================================
1741
1745
  /** Flags `evaluate` understands; anything else is rejected rather than ignored. */
1742
1746
  const EVALUATE_FLAGS = new Set([
1743
- "file", "arg", "json", "raw", "wait-for", "timeout", "expect-truthy",
1747
+ "file", "arg", "json", "raw", "wait-for", "timeout", "expect-truthy", "force",
1744
1748
  "url", "browser", "device", "headless", "persistent", "restore",
1745
1749
  "locale", "timezone", "geo", "verbose",
1746
1750
  ]);
1751
+ /**
1752
+ * `--force` is a bare flag, but the parser gives any flag the next non-flag
1753
+ * word as its value, so `evaluate --force "document.title"` reads the SCRIPT as
1754
+ * the value of --force and leaves no script. The gate would refuse it anyway
1755
+ * (only `true` opens it); this says why instead of a confusing refusal.
1756
+ */
1757
+ function rejectForceValue(options) {
1758
+ if (typeof options.force === "string") {
1759
+ console.error(`Error: --force takes no value, so "${options.force}" was read as one.`);
1760
+ console.error(' Put the script first: cbrowser evaluate "<javascript>" --force');
1761
+ process.exit(1);
1762
+ }
1763
+ }
1747
1764
  /**
1748
1765
  * Collect a repeatable flag's values.
1749
1766
  *
@@ -1828,6 +1845,7 @@ async function runEvaluate(browser, args, options) {
1828
1845
  console.error("Error: --json and --raw are mutually exclusive - pick one");
1829
1846
  process.exit(1);
1830
1847
  }
1848
+ rejectForceValue(options);
1831
1849
  const fromFile = typeof options.file === "string";
1832
1850
  if (fromFile && args[0]) {
1833
1851
  console.error("Error: pass the script as an argument OR --file, not both");
@@ -1875,6 +1893,16 @@ async function runEvaluate(browser, args, options) {
1875
1893
  process.exit(1);
1876
1894
  }
1877
1895
  });
1896
+ // Red zone, refused before the page is touched: no navigation, no wait, no
1897
+ // script. A script can click what click refuses (src/security/script-gate.ts).
1898
+ const refusal = evaluateScriptRefusal(options.force === true);
1899
+ if (refusal) {
1900
+ console.error(`✗ ${refusal}`);
1901
+ console.error(" Re-run with --force to run it anyway.");
1902
+ process.exit(1);
1903
+ }
1904
+ // Said on stderr so stdout stays exactly the result (--raw / --json pipes).
1905
+ console.error("⚠ Red zone: running caller-supplied page script (--force)");
1878
1906
  if (options.url)
1879
1907
  await browser.navigate(options.url);
1880
1908
  const page = await browser.getPage();
@@ -2932,6 +2960,7 @@ Documentation: https://github.com/alexandriashai/cbrowser/wiki
2932
2960
  case "eval":
2933
2961
  case "evaluate": {
2934
2962
  validateCommandFlags(command, options);
2963
+ rejectForceValue(options);
2935
2964
  const script = typeof options.file === "string"
2936
2965
  ? readFileSync(resolve(options.file), "utf-8")
2937
2966
  : args[0];
@@ -2939,7 +2968,15 @@ Documentation: https://github.com/alexandriashai/cbrowser/wiki
2939
2968
  console.error('Usage: cbrowser evaluate "<javascript>" | --file <path>');
2940
2969
  process.exit(1);
2941
2970
  }
2942
- daemonArgs = { body: `return (function(){ ${/\breturn\b/.test(script) ? script : `return (${script});`} })();`, args: [] };
2971
+ // Refused here, before the request leaves, and again daemon-side
2972
+ // (anything on this machine can POST to the daemon).
2973
+ const refusal = evaluateScriptRefusal(options.force === true);
2974
+ if (refusal) {
2975
+ console.error(`✗ ${refusal}`);
2976
+ console.error(" Re-run with --force to run it anyway.");
2977
+ process.exit(1);
2978
+ }
2979
+ daemonArgs = { body: `return (function(){ ${/\breturn\b/.test(script) ? script : `return (${script});`} })();`, args: [], force: true };
2943
2980
  break;
2944
2981
  }
2945
2982
  case "screenshot": {