Skip to main content
Vulnerability Database/CVE-2026-50553

CVE-2026-50553: Note Mark Path Traversal Vulnerability

CVE-2026-50553 is a path traversal vulnerability in Note Mark that allows attackers to write files outside intended directories with root privileges. This post covers technical details, affected versions, impact, and mitigation.

Published:

CVE-2026-50553 Overview

Note Mark, an open-source note-taking application, contains a path traversal vulnerability in its data-export command-line interface (CLI) prior to version 0.19.5. The application validates book and note slug values using an OpenAPI/huma pattern ([a-z0-9-]+) that huma compiles unanchored with regexp.MustCompile. Any input containing at least one matching substring passes validation, including ../../../../../../tmp/escape. The note-mark migrate export and note-mark migrate export-v1 commands join these unsanitized slugs into output paths with path.Join and filepath.Join, then call os.MkdirAll and os.Create. Because exports commonly run as root under Docker or bare-metal admin usage, this results in arbitrary directory creation and file writes outside the configured export directory.

Critical Impact

Authenticated users can write attacker-controlled note content to arbitrary filesystem paths as root when an administrator runs the export CLI, enabling privilege escalation and host compromise.

Affected Products

  • Note Mark versions prior to 0.19.5
  • Docker deployments of Note Mark running the export CLI as root
  • Bare-metal Note Mark installations where administrators invoke note-mark migrate export or note-mark migrate export-v1

Discovery Timeline

  • 2026-09-04 - CVE-2026-50553 published to the National Vulnerability Database (NVD)
  • 2026-09-09 - Last updated in NVD database

Technical Details for CVE-2026-50553

Vulnerability Analysis

The vulnerability is a classic path traversal (CWE-20) issue rooted in unanchored regular-expression validation. Go's regexp package treats MatchString as an unanchored search by default. The huma framework compiles OpenAPI pattern tags with regexp.MustCompile(s.Pattern) and validates values via patternRe.MatchString(str). Because Note Mark declared slug patterns as [a-z0-9-]+ instead of ^[a-z0-9-]+$, any string containing one qualifying character passes validation.

The export CLI then trusts the stored slugs when constructing filesystem paths. path.Join normalizes ../ sequences, so a slug of ../../../../../../tmp/escape resolves to a location outside the configured export directory. When the export runs as root, an attacker can create directories and write note content anywhere on the host filesystem, including locations like /etc/cron.d, /root/.ssh, or systemd unit paths.

Root Cause

Two defects combine to produce the vulnerability. First, the OpenAPI validation pattern was not anchored with ^ and $, allowing malicious substrings to pass input validation. Second, the export routines used raw slug values in path construction without calling filepath.Base or verifying that the resulting path stayed within the intended export root.

Attack Vector

A low-privileged authenticated user creates a book or note with a crafted slug containing traversal sequences. The malicious slug persists in the database. When an administrator subsequently runs the export CLI, the traversal executes with the privileges of the export process, typically root.

go
// Patch: backend/cli/migrate.go
// prevent CWE-20, CWE-22: slug/username path components must
// not escape the export directory (sibling of GHSA-g49p).
bookSlug := filepath.Base(book.Slug)
userName := filepath.Base(user.Username)
if bookSlug != book.Slug || userName != user.Username {
    log.Printf("disallowed path component found, skipping user '%s' book '%s'\n", user.Username, book.Slug)
    continue
}
bookDir := path.Join(exportDir, userName, bookSlug)
for _, note := range book.Notes {
    noteSlug := filepath.Base(note.Slug)
    if noteSlug != note.Slug {
        log.Printf("disallowed note slug found, skipping '%s'\n", note.Slug)
        continue
    }
    noteDir := path.Join(bookDir, noteSlug)
    if err := os.MkdirAll(noteDir, os.ModePerm); err != nil {
        return err
    }
}

Source: GitHub Commit 67b7de0

Detection Methods for CVE-2026-50553

Indicators of Compromise

  • Database rows in the books or notes tables containing slug values with .., /, or other characters outside [a-z0-9-].
  • Log entries from note-mark migrate export referencing usernames or slugs that include path separators.
  • Files or directories owned by root appearing outside the configured export directory after an export run.

Detection Strategies

  • Query the Note Mark database for slugs that fail an anchored ^[a-z0-9-]+$ regular-expression match.
  • Audit filesystem changes made during export runs by comparing directory trees before and after execution.
  • Enable auditd rules on Linux hosts to record openat and mkdirat syscalls performed by the note-mark binary.

Monitoring Recommendations

  • Monitor process execution of note-mark migrate export and note-mark migrate export-v1 and correlate with unexpected file creation events.
  • Alert on new files written to sensitive paths such as /etc/cron.d, /etc/sudoers.d, /root/.ssh, or systemd unit directories.
  • Track container image versions and flag Note Mark deployments still running versions earlier than 0.19.5.

How to Mitigate CVE-2026-50553

Immediate Actions Required

  • Upgrade Note Mark to version 0.19.5 or later on every deployment, including Docker images.
  • Audit the books, notes, and users tables for slugs or usernames containing traversal characters and remove or rename them before running any export.
  • Run the export CLI as a non-root user with write access limited to the intended export directory.

Patch Information

The fix is available in Note Mark release v0.19.5. See the GHSA-rqrh-8wpv-x7hh advisory and the remediation commit for full technical details. The patch anchors the OpenAPI patterns with ^...$ and applies filepath.Base to each path component in the export routines.

Workarounds

  • Avoid running note-mark migrate export and note-mark migrate export-v1 until the upgrade is complete.
  • Restrict who can create books, notes, and accounts to trusted operators to limit slug injection opportunities.
  • Execute the export process inside a chroot or dedicated container with a read-only host filesystem mount so traversal writes cannot reach sensitive paths.
bash
# Verify no traversal-capable slugs exist prior to export (SQLite example)
sqlite3 note-mark.db "SELECT id, slug FROM books WHERE slug GLOB '*[^a-z0-9-]*';"
sqlite3 note-mark.db "SELECT id, slug FROM notes WHERE slug GLOB '*[^a-z0-9-]*';"

# Run the export as a dedicated non-root user with a scoped export directory
sudo -u notemark note-mark migrate export --export-dir /var/lib/note-mark/exports

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.