Skip to content

fix(examples/chrome-applescript): use JSON.stringify for AppleScript string interpolation#231

Merged
tobinsouth merged 1 commit intomainfrom
fix/chrome-applescript-json-stringify-interpolation
Apr 17, 2026
Merged

fix(examples/chrome-applescript): use JSON.stringify for AppleScript string interpolation#231
tobinsouth merged 1 commit intomainfrom
fix/chrome-applescript-json-stringify-interpolation

Conversation

@bryan-anthropic
Copy link
Copy Markdown
Collaborator

@bryan-anthropic bryan-anthropic commented Apr 17, 2026

Summary

Follow-up to #230. Replaces escapeForAppleScript() with JSON.stringify() at the two remaining AppleScript string-interpolation sites in examples/chrome-applescript: the url param in open_url and the code param in execute_javascript (via wrappedCode).

escapeForAppleScript only handled backslash, double quote, \n, and \r — tab, null, and other control characters passed through unescaped. JSON.stringify produces an RFC 8259–compliant quoted string that AppleScript parses as a string literal, covering the gaps.

Also adds new URL(url) validation to open_url so malformed URLs return isError: true instead of reaching osascript.

With those call sites migrated, escapeForAppleScript has no remaining callers and is deleted.

Fix

Test plan

  • node --check examples/chrome-applescript/server/index.js
  • yarn install && yarn lint clean
  • grep -n escapeForAppleScript examples/chrome-applescript/server/index.js → no matches
  • Manual: open_url with url: "https://example.com/a\"b" → navigates to example.com/a%22b; the " is percent-encoded as a literal URL character, not an osascript escape
  • Manual: execute_javascript with a code string containing ", \t, and \\ → characters preserved as-is in the returned value
  • Manual: open_url with url: "not a url"isError: true, Invalid URL

Note for reviewers: testing execute_javascript requires Chrome's View → Developer → Allow JavaScript from Apple Events toggle to be enabled. Without it, the call to execute t javascript fails and is surfaced as a generic "Chrome not running" error via the existing outer try/catch. Not a change in this PR — documenting the prerequisite.

Copy link
Copy Markdown

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Code review skipped — your organization's overage spend limit has been reached.

Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit at claude.ai/admin-settings/claude-code.

Once credits are available, reopen this pull request to trigger a review.

Copy link
Copy Markdown
Collaborator

@tobinsouth tobinsouth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security review

Verdict: ✅ Safe — fix is complete and correct.

Reviewed for: JSON.stringify → AppleScript breakout potential, regression vs the deleted escapeForAppleScript, new URL() validation scope, and completeness of interpolation-site coverage.

JSON.stringify safety — AppleScript string literals terminate only on an unescaped ". JSON.stringify guarantees "\\" and \\\\\\, so no raw terminator or stray escape can reach the closing quote. The non-AppleScript escapes JSON emits (\\b, \\f, \\uXXXX) and raw U+2028/U+2029 contain no " — worst case is mis-rendering or a script parse error, never breakout. Inputs are type-guarded as strings before stringify (the existing typeof url !== "string" check; wrappedCode is a template literal), so output is always the "..." form. No injection path.

Regression vs old escaper — None. The deleted helper already covered \\ and " (the only breakout-relevant characters); JSON.stringify covers those plus \\t and all C0 control chars. Strictly ≥ old coverage.

new URL() validation — Permits javascript: / file: / data:, but the prior code had no validation at all and the server already exposes execute_javascript, so no new capability is granted. Defense-in-depth only.

CompletenessescapeForAppleScript fully removed. Remaining AppleScript interpolations are: safeTabId (sanitized in #230), JSON.stringify(url) (L296-297), JSON.stringify(wrappedCode) (L656/666), the hardcoded jsCode constant (L727/737), and operation.tabScript / successMessage (all callers pass literal constants). No user-input site left uncovered.

CI green across CodeQL + full test matrix. Approving.

@tobinsouth tobinsouth merged commit f9a551b into main Apr 17, 2026
10 checks passed
@tobinsouth tobinsouth deleted the fix/chrome-applescript-json-stringify-interpolation branch April 17, 2026 20:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants