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.
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.
| 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 |
- 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).
| 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.
These are documented in PLAN.md and exist as conscious trade-offs in v0.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. -
Asset protocol scope is
**. We need wide scope because users pick their own vault path. Path-traversal guards invault_ops.rsenforce containment at every command — verified by 8 Rust unit tests. -
PBKDF2 not Argon2id. 200,000 iterations is acceptable today; Argon2id is better but requires breaking-change to the encrypted blob format. Migration planned with
OBH2magic byte. -
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.
-
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.
- 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);styleattribute andsrcdocforbidden (CSS/iframe XSS classes) - SSRF guard in Rust
fetcherand JShost.ts— blocks loopback, RFC1918, CGNAT, link-local, cloud metadata - Iframe whitelist uses exact-match + one-level subdomain guard (no
evil.com.youtube.combypass) - 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
(None yet. This list will be updated as the project ages.)
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