Repository navigation
MCP: SVG export by a confined caller refuses script links outside its read roots - #7264
Merged
bflatastic merged 2 commits intoNov 14, 2026
Merged
Conversation
… read roots An SVG or SVGZ writes each linked JavaScript file of SVG Interactivity into a <script xlink:href> element as stored, so a caller with automation read roots could read a path outside them from the exported text. With read roots in force, an SVG or SVGZ of a document that links such a file is now refused with "a linked JavaScript file is outside the read roots", an error that names no file or folder. No file or folder is written, and the document keeps the link. - The check uses the rule document.json already applies to svg_scripts: a relative path is taken from the document's folder, a file: URL is a file, and another URL is not checked. - It covers document.serialize, document.export, document.exportSelection, document.exportForScreens and assets.export (before the folder is made or any row is written), the SVG and SVGZ saves (also a save without a path of a document saved as SVG), file.exportAs and the SVG Options dialog's Show Code. - Callers without roots, and the person at the keyboard, export the links as stored. Docs: docs/mcp.md, docs/target-app-parity.md.
Contributor
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 3 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
crates/mcp/src/ui_catalog.rs now carries the file.exportAs params text from crates/ui-egui/src/menus/ui_commands.rs, so `cargo xtask ui-commands --check` passes.
3 of 4 tasks
Member
|
Merged, thanks @dotCooCoo! It passed its CI checks. |
This was referenced Nov 14, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
SVG Interactivity links JavaScript files to a document: its JavaScript Files dialog adds a file picked from the computer or a URL that is typed in (Work with SVG interactivity). SVG export writes each linked file into a
<script xlink:href>element as stored (crates/svg/src/export.rs). An automation caller confined with--automation-read-rootcould therefore read the path of a script file outside its read roots from the SVG or SVGZ it exported, althoughdocument.jsonandsvgInteractivity.infoalready name such a file by its file name alone.With read roots in force, every caller-driven SVG and SVGZ output of a document that links a JavaScript file outside them now fails with "a linked JavaScript file is outside the read roots". The error names no file or folder. The href is not shortened and the element is not dropped, and the document keeps the link. This is VectorCraft's own rule for confined callers; no public source describes it. Callers without read roots, and the person at the keyboard, export every link as stored, as before.
This covers SVG and SVGZ only. The native format, PDF with Preserve Editing,
.ai, EPS andfile.packagestill carry the stored script paths, and an SVG export still writes the path of a linked image outside the read roots; this pull request does not change those.fileio::check_linked_scriptsuseslinks::script_hidden(crates/engine/src/cmd/links.rs), the testdocument.jsonandsvgInteractivity.infouse (SVG Interactivity: replies name JavaScript files outside the read roots by file name #7205): a local path, afile:URL, or a relative path taken from the document's folder is checked against the read roots; another URL is not checked.fileio::check_linked_scripts(crates/engine/src/cmd/fileio/access.rs) applies it for the SVG and SVGZ formats. It runs before any encoding or writing indocument.serialize,document.export(MCP'sexport),document.exportSelection(fileio/export.rs), the SVG and SVGZ saves ofdocument.save,file.save,file.saveAsandfile.saveCopy, including a save without a path of a document whose own format is SVG (fileio/save.rs), anddocument.exportForScreensandassets.export, for every format row before the folder is made or any row is written (fileio/screens.rs).file.exportAsandapp.exportwith a path run it (crates/ui-egui/src/io/export.rs);app.exportwithout a path runsdocument.export. The SVG Options dialog's Show Code shows the error instead of the SVG text (crates/ui-egui/src/dialogs/svg_options.rs). The code view's cache now also depends on the read roots in force and the document's path.document.serialize,document.export,document.exportSelection,document.exportForScreens,document.saveandfile.exportAs,docs/mcp.md(the read roots list and SVG Interactivity) and one line indocs/target-app-parity.mddescribe the refusal.How it was tested
New tests, each failing without the change (the check disabled):
confined_svg_output_refuses_a_linked_javascript_file_outside_the_read_roots(crates/engine/src/tests/interactivity.rs): for SVG and SVGZ,document.serialize,document.exportwith and without a path and withselectedOnly,document.exportSelection,document.save,file.saveAs,file.saveCopy,document.exportForScreens(a folder with a PNG and an SVG row, and a ZIP) andassets.exportare refused with an error that names neither the script's folder, the read root nor the file name. A pathless save of a document saved as SVG leaves its file unchanged, no other file is written, and the document keeps the link.control_svg_export_refuses_a_linked_javascript_file_outside_the_read_root(crates/ui-egui/src/tests/automation.rs):app.exportto SVG and SVGZ with a path and to SVG without a path, andfile.exportAsthroughengine.executeare refused and write nothing; the person's ownfile.exportAswrites the link as stored.show_code_leaves_out_a_linked_javascript_file_outside_the_read_roots(crates/ui-egui/src/dialogs/svg_options.rs): Show Code under read roots shows the error without the file name or folder, and without roots shows the<script>element.svg_output_keeps_linked_javascript_files_a_caller_may_read(crates/engine/src/tests/interactivity.rs) checks that a confined caller's SVG and SVGZ keep a file inside the read roots, a relative path that leads inside them and a URL as stored, and that a caller without roots writes a file outside them.Focused checks on the build host, on Linux. The branch is one commit on
mainat08b6cfd3e8and merges cleanly with it.cargo fmt --all -- --checkcargo clippy -p vectorcraft-engine --all-targets -- -D warningsandcargo clippy -p vectorcraft-ui-egui --all-targets -- -D warningscargo check --workspace --testscargo test -p vectorcraft-engine --lib tests::interactivity: 12 passedcargo test -p vectorcraft-engine --lib tests::placed_document::document_(thedocument.jsonrule): 2 passedcargo test -p vectorcraft-ui-egui --lib linked_javascript_file_outside_the_read_root: 2 passedcargo test -p vectorcraft-ui-egui --lib export_notes_an_option_the_format_does_not_read(beside the new automation test): 2 passedcargo test -p vectorcraft-ui-egui --lib i18n: 106 passedcargo xtask brands,layers(30 crates) andassets(337 files)cargo xtask ciruns in this pull request's CI.cargo xtask cipassed in this pull request's CI run on38127af144: https://github.com/storytold/vectorcraft/actions/runs/43525492884/job/132230087367Checklist
cargo xtask cipasses (fmt, clippy, tests, assets, brands, layers, wasm).unwrap(),expect(),panic!,unreachable!,todo!orunimplemented!outside tests, and no unchecked indexing on data from files, parameters ormessages. Errors are returned as
Resultand shown to the user(why and how).
ASSETS.md.