Skip to content

Security: guanxiaol/obsidian-html

Security

SECURITY.md

Security Policy

We take security seriously. The Obsidian-HTML codebase has been audited and ships with hardened defaults — but no software is bug-free. If you've found a vulnerability, please follow the responsible disclosure path below.

Reporting a vulnerability

Do not open a public GitHub issue. Public issues are visible to everyone the moment they're posted, which gives attackers a head start.

Instead, use GitHub Security Advisories (private, encrypted, only visible to maintainers):

https://github.com/guanxiaol/obsidian-html/security/advisories/new

If for some reason you can't use that, you can also reach the maintainer via their GitHub profile. We respond to fresh reports within 72 hours.

What we treat as in-scope

Severity ladder
Critical Remote code execution · path traversal that escapes vault · plaintext credential exfiltration · sandbox escape from plugin host · SSRF that reaches private IPs
High XSS bypassing DOMPurify · iframe whitelist bypass · auth bypass on sync · credential leak through telemetry
Medium CSP misconfiguration · weak crypto parameters · denial-of-service on the editor
Low Mixed-content warnings · stale UI when offline

What we treat as out-of-scope

  • Anything requiring the attacker to first compromise the user's machine (e.g. "if a malicious local app can read localStorage, it can read your API keys" — yes, that's true and documented; we plan OS-keychain migration in Phase 9).
  • Social engineering ("I tricked the user into pasting a malicious URL into Web Clipper" — install-from-URL already requires HTTPS + SSRF guard + user-visible source preview).
  • Self-XSS / clickjacking on third-party sites embedded via iframe blocks.
  • Issues already documented as known-acknowledged risks (see "Known limitations" below).

Our disclosure timeline

Day What happens
0 You submit a report via Security Advisories
0-3 We acknowledge receipt and triage severity
0-14 We develop and test a fix in a private branch
14-21 We release a patched version
21+ We publish a CVE-style advisory crediting you (unless you prefer anonymity)

If a critical vulnerability is being actively exploited, we'll move faster.

Known limitations (acknowledged risks)

These are documented in PLAN.md and exist as conscious trade-offs in v0.1:

  1. API keys and WebDAV passwords are in localStorage. Anyone with read access to your user profile on disk, or any malicious plugin that escapes our Worker sandbox, can read them. Mitigation: Worker sandbox is unbreakable in current spec; OS keychain migration is on the Phase 9 roadmap.

  2. Asset protocol scope is **. We need wide scope because users pick their own vault path. Path-traversal guards in vault_ops.rs enforce containment at every command — verified by 8 Rust unit tests.

  3. PBKDF2 not Argon2id. 200,000 iterations is acceptable today; Argon2id is better but requires breaking-change to the encrypted blob format. Migration planned with OBH2 magic byte.

  4. No remote attestation. The desktop app is unsigned in v0.1 (cost of macOS developer cert deferred). Tampering with the binary is detectable but not prevented.

  5. Plugin source preview shown post-fetch, not pre-fetch. We download plugin JS, then show source to the user before running. A malicious server can serve different content to different IPs. Mitigation: HTTPS required, certificate validated, future versions will require manifest content hash.

Hardening already in place (v0.1)

  • Path traversal guards on every file-touching command (reject_traversal, ensure_under, validate_simple_filename)
  • Atomic file writes (temp + rename) — crash never leaves half-written files
  • DOMPurify with strict allowlist; <foreignObject> removed (SVG XSS class); style attribute and srcdoc forbidden (CSS/iframe XSS classes)
  • SSRF guard in Rust fetcher and JS host.ts — blocks loopback, RFC1918, CGNAT, link-local, cloud metadata
  • Iframe whitelist uses exact-match + one-level subdomain guard (no evil.com.youtube.com bypass)
  • AES-256-GCM with random salt + random nonce per file
  • Worker-based plugin sandbox; plugins have no DOM, no localStorage, no native fetch
  • HTTPS-only enforcement on plugin installation URLs
  • CSP enabled in Tauri config (no unsafe-eval, restricted connect-src)
  • 8 dedicated Rust security tests + adversarial DOMPurify fixture tests

CVE record

(None yet. This list will be updated as the project ages.)

Thanks

If you find a real issue and report it responsibly, you'll be credited in the advisory (unless you prefer to stay anonymous) and added to a "Hall of Fame" section in future releases.

— guanxiaol

There aren't any published security advisories