A Pasted Reply Brought a Script Nobody Approved

Mina pasted the vendor's outage notice into the Service Status: November Outage article to save retyping it. The vendor's page brought a script tag, a live iframe widget, and its own custom badge markup along with the words.

1.00

Locking Down Scripts, Iframes, and Embedded Objects

The paragraph of outage wording looked clean in preview, but the pasted block underneath carried more than words. It carried a script tag reporting back to the vendor's analytics endpoint, an iframe pulling in their live status dashboard, and a badge element built from the vendor's own markup. None of it came from Mina's keyboard. All of it rode in with one paste, sitting in the same block as the sentence she meant to reuse.

Published, the help article ran a script nobody on the support team had reviewed. It displayed a third party's dashboard inside a page meant to show one outage. The vendor's badge sat in the document as a tag the help center's own stylesheet did not recognize and could not draw.

Catching any of this meant opening the raw HTML of every article before it went out. Someone had to read it line by line for tags that did not belong there. A reply pasted on a Friday afternoon was easy to skim and publish without that check. One missed script in forty replies was the kind of mistake nobody noticed until the vendor's dashboard had been live on the status page for a week, loading content none of the support team controlled.

The same block was ready to carry the same risk into the next reply.

How to Restrict Which Files Reach the Editor

Filtering what lands in the document only covers content typed or pasted directly into it. A document can also arrive already built. It can be brought in as a file and converted into the document, or attached as a plain upload for someone to open later. Each of those is a separate doorway into the same document, and a filter watching only the paste doorway leaves the other two standing open.

Mina's paste was only one of those three doors.

A complete answer has to treat every path the same way. Whatever is typed, pasted, or converted from an imported file has to be checked against the same rules. A script or an iframe should not slip in just because it arrived by a different route. The file formats allowed to reach the editor in the first place also need their own limit, separate from what happens to content once it is inside.

A format built for exchanging documents is not the same risk as a format built for marking up a web page. A file that is only stored as an upload, never parsed into the document, can still be handed back to someone later exactly as it was received.

Three Checks: Tags, File Formats, and Unknown Markup

Synap Editor already does three separate things here: filters content, limits which formats get in, and decides what to do with markup it does not recognize.

Synap Editor filters what gets inserted into a document. A script tag, an iframe, an embed, an object, a stylesheet link tag, or an onclick-style attribute is kept out by default. The risk is not the default. It is someone allowing one of them for a single widget and never switching it back.

The same gate also decides which file formats are allowed to reach the editor as an import or an upload at all. A format meant for exchanging documents between office tools can be allowed in. A format built for marking up a web page does not have to be trusted in the first place. What is left afterward is markup the editor genuinely does not recognize, like the vendor's own badge tag.

Rather than carry an unfamiliar tag through untouched, Synap Editor can turn it into a plain div the moment the document loads. The document stops holding foreign elements with behavior nobody on the team reviewed. It keeps only markup its own renderer already understands. For Mina's team, a pasted reply no longer needs a line by line read before it goes out.

Checking What Actually Reaches the Document

Mina pastes the same vendor announcement into a fresh draft of the Service Status article. The script tag, the iframe, and the vendor's badge tag all arrive in one block, exactly as they did the first time.

The preview does not change. When she opens the saved HTML afterward, there is no script tag anywhere in the document and no iframe. The vendor's badge tag is gone too, replaced by a plain div holding the same badge text, styled by the help center's own rules instead of the vendor's.

[[shot: The published Service Status article showing the outage text and the vendor's badge rendered as a plain styled block, with no embedded dashboard widget anywhere on the page.]]

She does not open the raw HTML to check for anything else afterward. There is nothing left in it to find. Support leads reviewing the article before it ships see the same thing: plain text and a plain badge, nothing else. The same paste that once needed a careful read before publishing now goes out as soon as the preview looks right.

The vendor's original script and dashboard never reach the page at all.

Where to Tighten the Filter Further

The content filter, the allowed extensions, and the custom tag conversion are each one setting in synapeditor.config.js.

// synapeditor.config.js
{
  'editor.contentFilter.allowScript': false,
  'editor.contentFilter.allowIframe': false,
  'editor.contentFilter.allowEmbed': false,
  'editor.contentFilter.allowObject': false,
  'editor.contentFilter.allowLink': false,
  'editor.contentFilter.allowEventAttribute': false
}

These six values are already the defaults. Scripts, iframes, embeds, objects, <link> tags (stylesheet links, not ordinary hyperlinks), and event attributes like onclick stay out unless a setting allows them. If any of these reads true in your configuration, that is the line to check first. The manual warns that allowing scripts or event attributes opens the editor to cross-site scripting.

// synapeditor.config.js
{
  'editor.import.extensions': ['docx', 'hwpx', 'xlsx'],
  'editor.upload.file.extensions': [
    'bmp', 'gif', 'jpeg', 'jpg', 'png', 'tif', 'tiff', 'webp',
    'mp3', 'mp4', 'm4a', 'ogg', 'wav', 'webm',
    'txt'
  ]
}

Only the listed formats can be imported or uploaded; everything else is rejected before it reaches the editor.

// synapeditor.config.js
'editor.buildOption.html': {
  'customTagToDiv': true
}

An unrecognized tag like synap-custom becomes a div the moment the document loads.

Files that reach your server by other routes need their own checks there. None of this sanitizes style attributes inside allowed tags or scans uploaded files for malware. It only decides which tags, attributes, and file extensions get in.

Common questions

Does allowEventAttribute block onclick and onload both, or just one of them? It blocks both, along with the rest of a maintained list of event attributes such as onchange. Turning allowEventAttribute off strips every attribute in that list, not just one.

What's the minimum editor release these content filter options need? allowLink and allowEventAttribute need release 2.7.0 or later. The manual lists no minimum release for allowScript, allowIframe, allowEmbed, or allowObject.

If I never set customTagToDiv, what happens to a tag like <synap-custom>? The tag stays in the document instead of becoming a div. While editing, it is wrapped in an internal container class. The saved HTML drops that class again and keeps the tag itself, with its inner content unchanged.

Does restricting editor.upload.file.extensions also block hwp or hwpx imports? No. Upload and import use separate lists: editor.upload.file.extensions covers generic file uploads, while editor.import.extensions covers document conversion formats such as hwp and hwpx. Restricting one list does not change the other.