LinkNote takes security seriously. This document outlines the security measures implemented to protect users from common web vulnerabilities, particularly Cross-Site Scripting (XSS) attacks.
Cross-Site Scripting (XSS) is a security vulnerability where malicious scripts are injected into otherwise benign websites. In a Markdown editor, users could potentially write Markdown that contains:
- JavaScript code in
<script>tags - Event handlers like
onclick,onerror, etc. - Malicious
javascript:URLs - Data URIs containing executable code
Example malicious Markdown:
<script>alert('XSS')</script>
<img src="x" onerror="alert('XSS')">
[Click me](javascript:alert('XSS'))LinkNote uses DOMPurify to sanitize all HTML before rendering it in the preview pane.
- User types Markdown in the editor
- marked.js parses Markdown → HTML
- DOMPurify sanitizes the HTML
- Safe HTML is rendered in the preview
// In MarkdownEngine.parse()
const rawHtml = marked.parse(markdown); // Parse Markdown
const cleanHtml = DOMPurify.sanitize(rawHtml); // Sanitize HTML
preview.innerHTML = cleanHtml; // Safe to injectDOMPurify automatically removes or neutralizes:
- ✅
<script>tags and their contents - ✅ Event handlers (
onclick,onload,onerror, etc.) - ✅
javascript:protocol in links - ✅
data:URIs (except safe image formats) - ✅
<iframe>,<object>,<embed>tags - ✅ Dangerous attributes (
formaction, etc.) - ✅ CSS expressions
- ✅ HTML imports
Common Markdown/HTML elements are preserved:
- ✅ Headings (
<h1>through<h6>) - ✅ Paragraphs and line breaks
- ✅ Text formatting (
<strong>,<em>,<code>, etc.) - ✅ Lists (
<ul>,<ol>,<li>) - ✅ Links with
http(s):andmailto:protocols - ✅ Images from
http(s):URLs - ✅ Tables
- ✅ Blockquotes
- ✅ Code blocks
You can test the XSS protection by trying to inject malicious code:
Input:
<script>alert('XSS')</script>Result: Script tag is removed, no JavaScript executes
Input:
<img src="x" onerror="alert('XSS')">Result: onerror attribute is removed
Input:
[Click me](javascript:alert('XSS'))Result: Link is removed or neutralized
Input:
<img src="data:text/html,<script>alert('XSS')</script>">Result: Dangerous data URI is blocked
Input:
[Safe link](https://example.com)Result: ✅ Link works normally
DOMPurify is configured with specific allowed tags and attributes:
DOMPurify.sanitize(rawHtml, {
ALLOWED_TAGS: [
'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
'p', 'br', 'hr',
'strong', 'em', 'b', 'i', 'u', 's', 'del', 'mark', 'sub', 'sup',
'ul', 'ol', 'li',
'blockquote', 'pre', 'code',
'a', 'img',
'table', 'thead', 'tbody', 'tr', 'th', 'td',
'div', 'span',
'details', 'summary'
],
ALLOWED_ATTR: [
'href', 'title', 'alt', 'src',
'class', 'id',
'align', 'width', 'height',
'target', 'rel'
],
ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i,
FORCE_BODY: true
});- ALLOWED_TAGS: Only tags needed for Markdown rendering
- ALLOWED_ATTR: Only safe attributes that don't execute code
- ALLOWED_URI_REGEXP: Only safe protocols (http, https, mailto, etc.)
- FORCE_BODY: Ensures output is wrapped in a safe container
While not currently implemented, you can add CSP headers to further restrict what scripts can run:
<meta http-equiv="Content-Security-Policy"
content="default-src 'self';
script-src 'self' https://cdn.jsdelivr.net;
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
font-src https://fonts.gstatic.com;
img-src * data:;">The codebase does not use eval(), Function(), or setTimeout(string) which could execute arbitrary code.
All JavaScript runs in strict mode ("use strict";) to catch common coding errors.
Content in the URL fragment is Base64-encoded, not executed as code.
- marked.js: Updated regularly, no known vulnerabilities
- DOMPurify: Industry-standard HTML sanitizer, actively maintained
✅ XSS via Markdown: Malicious scripts in user content ✅ XSS via URL: Malicious scripts in shared URLs ✅ HTML injection: Arbitrary HTML that could break the page
❌ URL Privacy: URLs are visible in browser history and can be shared ❌ Content Privacy: Anyone with the URL can read the content
If you discover a security vulnerability in LinkNote:
- Do NOT open a public GitHub issue
- Email the maintainers privately (see SECURITY.md)
- Include steps to reproduce the vulnerability
- Allow time for a fix before public disclosure
Regularly check for updates to:
Monitor security advisories:
- Don't trust all shared URLs: Be cautious of LinkNote URLs from unknown sources
- Use HTTPS: Always access LinkNote over HTTPS in production
- Keep browser updated: Modern browsers have additional security features
- Be careful with sensitive data: URLs are not encrypted
LinkNote implements industry-standard XSS protection via DOMPurify. While Markdown is user-generated content, it is sanitized before rendering to prevent malicious code execution.
Key Points:
- ✅ DOMPurify sanitizes all HTML
- ✅ XSS attacks are prevented
- ✅ Common Markdown features work normally
- ✅ Regular security updates recommended
For questions or concerns, please refer to the main documentation or open a GitHub issue (for non-security bugs).
