diff --git a/crates/engine/src/cmd/edit.rs b/crates/engine/src/cmd/edit.rs index 018dd2991..179f35719 100644 --- a/crates/engine/src/cmd/edit.rs +++ b/crates/engine/src/cmd/edit.rs @@ -1183,10 +1183,11 @@ fn paste_special(s: &mut Session, p: &Json) -> Result { *cx.sel = crate::Selection { active: at, anchor: at, ranges: vec![RangeRef::new(at, end)] }; Ok(()) })?; - // Formulas, formats (conditional formats hold formulas) and validation from an untrusted file - // leave the destination untrusted; plain values, column widths and notes carry nothing active - // (a linked paste of values still writes formulas). - let passive = matches!(what, What::ColumnWidths | What::Comments) || (!link && matches!(what, What::Values | What::ValuesAndNumberFormats)); + // Formulas and validation from an untrusted file leave the destination untrusted; plain values, + // formats (cell styles and merged areas, no conditional formats), column widths and notes + // carry nothing active (a linked paste of values still writes formulas). + let passive = + matches!(what, What::Formats | What::ColumnWidths | What::Comments) || (!link && matches!(what, What::Values | What::ValuesAndNumberFormats)); if !same_doc && !passive { let d = s.doc_mut()?; d.trust = d.trust.receive(clip.trust); diff --git a/crates/engine/src/tests/seams.rs b/crates/engine/src/tests/seams.rs index e641fb0cd..16b2617d7 100644 --- a/crates/engine/src/tests/seams.rs +++ b/crates/engine/src/tests/seams.rs @@ -472,6 +472,9 @@ fn pasting_from_a_file_carries_its_trust() { // Values carry nothing that runs. s.execute("edit.pasteSpecial", json!({"what": "values", "at": "B1"})).unwrap(); assert_eq!(trust(&s), Trust::Local); + // Formats carry cell styles and merged areas, nothing that runs. + s.execute("edit.pasteSpecial", json!({"what": "formats", "at": "B3"})).unwrap(); + assert_eq!(trust(&s), Trust::Local); // A linked paste of values still writes formulas. s.execute("edit.pasteSpecial", json!({"what": "values", "link": true, "at": "B2"})).unwrap(); assert_eq!(trust(&s), Trust::FromFile); diff --git a/docs/architecture.md b/docs/architecture.md index 0f97f857b..d815bc81c 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -59,8 +59,8 @@ Actions made of many commands (macros, a debugger that runs one step per call) u Commands run by other commands are not recorded, and the buffer is independent of the journal (Automate › Record Actions still records through the journal). - **Document trust.** `DocState::trust` is `Local` for workbooks made in the session and - `FromFile` for workbooks opened from a file, and for workbooks that received formulas, formats - or validation pasted from one. Active content in a `FromFile` workbook asks before it runs. + `FromFile` for workbooks opened from a file, and for workbooks that received formulas or + validation pasted from one. Active content in a `FromFile` workbook asks before it runs. - **Workbook data in hidden names** (`cmd/stash.rs`). An item is split over hidden workbook-scope names `_gc__0`, `_gc__1`, … of string literals within Excel's 255- and 8,192-character limits, so it survives an xlsx round trip. The older single-name `_sc_`