Skip to content

fix(files): don't expose WebDAV XML-attribute artifacts as DOM attributes#3225

Open
chrip wants to merge 1 commit into
nextcloud:masterfrom
chrip:fix/5490-systemtags-invalid-dom-attribute
Open

fix(files): don't expose WebDAV XML-attribute artifacts as DOM attributes#3225
chrip wants to merge 1 commit into
nextcloud:masterfrom
chrip:fix/5490-systemtags-invalid-dom-attribute

Conversation

@chrip

@chrip chrip commented Jun 22, 2026

Copy link
Copy Markdown

Summary

Tagged office files (and other tagged files) cannot be opened in the Viewer on Firefox and Safari since Nextcloud 33. Opening them throws:

InvalidCharacterError: Invalid qualified name: '@canAssign'  (vue.runtime.esm.js)

Chrome is unaffected (it silently tolerates the invalid attribute name).

Originally reported against Nextcloud Office: nextcloud/richdocuments#5490 — but the crash is in the Viewer's genFileInfo, triggered for any tagged file.

Root cause

genFileInfo() (src/utils/fileUtils.ts) recursively flattens every DAV property and runs camelcase() on every key.

Since Nextcloud 33, a file's nc:system-tags PROPFIND property contains <nc:system-tag> elements that carry XML attributes (can-assign, id, user-visible, …) — see apps/dav/lib/SystemTag/SystemTagList.php in server. The WebDAV/fast-xml-parser layer represents those attributes with a leading @ (e.g. @can-assign), and camelcase('@can-assign') preserves the leading @, yielding @canAssign.

genFileInfo therefore produces a key @canAssign on the file-info object. Viewer.vue binds that object with v-bind="currentFile", so Vue calls el.setAttribute('@canAssign', …). @ is illegal in a DOM/XML qualified name → Firefox & Safari throw, Chrome ignores it.

The server XML is valid; the bug is purely in the client-side flattening.

Fix

In genFileInfo:

  • Skip the structured system-tags subtree — it is not scalar file metadata and should not be flattened into the file-info object.
  • Defensively drop any camelCased key that still starts with @, so WebDAV XML-attribute artifacts can never reach the DOM.

Testing

Validated with a faithful reproduction of genFileInfo's logic + the real camelcase@8 package against a webdav-parsed PROPFIND of a tagged file:

Case before after
Single tag emits @canAssign, @id, @userVisiblesetAttribute throws gone, no invalid keys
Multiple tags leaks systemTag array as attr clean
Real metadata (fileid, filename, …) preserved still preserved

To reproduce manually: tag any office file, open it in Firefox → console InvalidCharacterError on master, gone with this change.

Notes

  • Compiled assets under js/ are not included (my local toolchain is Node 22 / npm 10, the repo requires Node ^24 / npm ^11). Please recompile via CI / the compile bot.

Ref: nextcloud/richdocuments#5490

Assisted-by: ClaudeCode:Opus-4.8

…utes

genFileInfo() flattens every DAV property and runs camelcase() on each
key. Since Nextcloud 33, a file's nc:system-tags property contains
<nc:system-tag> elements that carry XML attributes (can-assign, id,
user-visible, ...). The WebDAV parser represents those attributes with a
leading "@", and camelcase() preserves it, so genFileInfo produced keys
such as "@canAssign". When the resulting object is bound via v-bind in
Viewer.vue, Vue calls setAttribute("@canAssign", ...), which throws
"InvalidCharacterError: Invalid qualified name" on Firefox and Safari
(Chrome silently ignores it). The result is that tagged office files
cannot be opened in those browsers.

Skip the structured system-tags subtree (it is not scalar file metadata)
and, as a defensive backstop, drop any camelCased key that still starts
with "@", so XML-attribute artifacts never reach the DOM.

Ref: nextcloud/richdocuments#5490

Assisted-by: ClaudeCode:Opus-4.8
Signed-off-by: Christoph Schaefer <christoph.schaefer@nextcloud.com>
@chrip chrip force-pushed the fix/5490-systemtags-invalid-dom-attribute branch from 2cc5765 to f7e98f3 Compare June 22, 2026 14:38
@chrip chrip marked this pull request as ready for review June 22, 2026 14:42
@chrip chrip requested a review from salmart-dev June 22, 2026 14:44
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.

1 participant