Skip to main content
VelinStyle v1.0.0
⌂ Home
  1. Docs
  2. Extend
  3. Security

Security

VelinStyle ships sanitization helpers, hardened components, and CSS utilities for user content. The CLI scan command flags XSS, PII, and accessibility issues (see rule table). Use HTTP CSP and Trusted Types for defense in depth.

XSS Protection

Dynamic text should use escapeHTML(), sanitizeURL(), or sanitizeSearchUrl() from components/sanitize.js. Icons use sanitizeSVG() (DOMPurify).

Defense in depth. Sanitization is not automatic for every tag — treat user-controlled strings as untrusted.

High-signal components

ComponentNotes
<velin-lightbox>sanitizeURL + escaped alt
<velin-search>Escaped highlights; sanitized href
<velin-icon>SVG sanitized; local sprite default
<velin-email>Obfuscation only — not encryption
<velin-secure-field>Demo only — client encoding, no secrets
<velin-dialog>, <velin-modal>, …Escaped titles/messages where dynamic

How it works

import { escapeHTML, sanitizeURL } from './sanitize.js';

// escapeHTML replaces <, >, &, ", and ' with HTML entities
escapeHTML('<img onerror=alert(1)>');
// → "&lt;img onerror=alert(1)&gt;"

// sanitizeURL blocks javascript: and data: URIs
sanitizeURL('javascript:alert(1)'); // → ""
sanitizeURL('https://example.com'); // → "https://example.com"

CSP Compatibility

VelinStyle is designed to work with strict Content-Security-Policy headers. No inline style attributes are injected at runtime, and all Web Components use shadow DOM or class-based styling.

Recommended headers

Content-Security-Policy:
  default-src 'self';
  script-src  'self';
  style-src   'self' 'unsafe-inline';
  img-src     'self' data:;
  font-src    'self';

Trusted Types

VelinStyle exposes getTrustedPolicy() for environments that enforce Trusted Types. Wrap your HTML assignments with the returned policy to stay compliant:

import { getTrustedPolicy } from 'velinstyle';

const policy = getTrustedPolicy();
element.innerHTML = policy.createHTML(safeContent);

CSS Security Utilities

The stylesheet src/a11y/security.css provides defensive CSS classes that mitigate common web vulnerabilities without JavaScript.

.velin-user-content

Apply to any container that renders untrusted or user-generated content. It sandboxes the content by blocking scripts, iframes, object embeds, and inline event handlers via CSS containment.

<div class="velin-user-content">
  <!-- User-generated HTML goes here -->
  <!-- Scripts, iframes, and event handlers are neutralized -->
</div>

.velin-secure-frame

Provides clickjacking protection for embedded frames by ensuring the frame cannot be overlaid with invisible elements.

<iframe class="velin-secure-frame" src="..."></iframe>

External link indicator

Links with target="_blank" that are missing rel="noopener" automatically receive a visual warning indicator, reminding developers to add the attribute:

/* security.css — flags unsafe external links */
a[target="_blank"]:not([rel~="noopener"])::after {
  content: " ⚠";
  color: var(--velin-color-warning);
}

Autofill & paste-jacking prevention

Password fields are protected against browser autofill abuse, and paste-jacking attacks are mitigated by blocking invisible clipboard-hijacking overlays within .velin-user-content containers.

Form Persistence Security

The velin-persist module stores form data in localStorage for convenience — but it is hardened against abuse:

ProtectionDetail
Key validationStorage keys must be alphanumeric (plus hyphens/underscores), max 64 characters. Invalid keys are rejected silently.
Size limitEach entry is capped at 64 KB. Larger payloads are discarded to prevent localStorage flooding.
QuotaExceededErrorCaught and handled gracefully — the user is not shown a raw browser error.
Sensitive fields excludedFields with type="password" and type="file" are never persisted.
<!-- Password and file fields are automatically excluded -->
<form data-velin-persist="signup">
  <input type="text" name="username">     <!-- ✓ persisted -->
  <input type="email" name="email">        <!-- ✓ persisted -->
  <input type="password" name="password">  <!-- ✗ excluded -->
  <input type="file" name="avatar">        <!-- ✗ excluded -->
</form>

Security in 0.8.0

Security in 0.9.0

PII & email protection (0.9.0)

Three layers: CLI scan, display obfuscation, optional form encoding.

npx velinstyle scan --only pii
npx velinstyle scan --only pii --fix
RuleSeverity
pii/hardcoded-emailwarning (autofix)
pii/hardcoded-secreterror
pii/mailto-in-sourceinfo
pii/localstorage-piiwarning

velin-email · velin-secure-field

Security Scanner

VelinStyle ships with a built-in velinstyle scan CLI command that checks your project for common security issues:

npx velinstyle scan

# Example output:
# ✓ All components use escapeHTML()
# ✓ No inline event handlers found
# ⚠ 2 links missing rel="noopener"  (src/page.html:14, src/page.html:28)
# ✓ CSP meta tag present
# ✓ No raw innerHTML assignments

See the CLI documentation for the full list of scan rules and configuration options.

Best Practices

A quick security checklist for VelinStyle projects: