Security
Weblisk's security modules cover the OWASP essentials with zero dependencies.
Content Security Policy
Generate and inject a strict CSP:
import { applyCSP, scriptHash } from 'weblisk/security/csp.js'; applyCSP({ 'script-src': ["'self'"], 'style-src': ["'self'", "'unsafe-inline'"], 'img-src': ["'self'", 'data:'], 'connect-src': ["'self'", 'https://api.example.com'], });
Inline Script Hashes
For inline scripts, compute the hash:
const hash = await scriptHash('console.log("hello")'); // → 'sha256-abc...'
CSRF Protection
Generate and inject CSRF tokens:
import { protectForm, csrfToken } from 'weblisk/security/csrf.js'; // Auto-inject a hidden _csrf field into a form protectForm('#payment-form'); // Or get the token manually for fetch requests const token = csrfToken(); fetch('/api/transfer', { method: 'POST', headers: { 'X-CSRF-Token': token }, body: JSON.stringify(data), });
Tokens are generated using crypto.getRandomValues() and stored in sessionStorage.
Input Sanitization
Clean untrusted HTML before inserting into the DOM:
import { sanitize, escapeHTML, html } from 'weblisk/security/sanitize.js'; // Remove dangerous elements/attributes const safe = sanitize(userProvidedHTML); // Escape for text content const escaped = escapeHTML('<script>alert("xss")</script>'); // → '<script>alert("xss")</script>' // Tagged template — values are auto-escaped el.innerHTML = html`<p>Hello, ${userName}!</p>`;
Uses the native Sanitizer API where available, DOMParser fallback elsewhere.
Trusted Types
Prevent DOM XSS by routing all dynamic HTML through a Trusted Types policy:
import { trustedHTML, trustedScriptURL } from 'weblisk/security/trusted.js'; // Create trusted HTML (sanitized) el.innerHTML = trustedHTML('<p>Safe content</p>'); // Create trusted script URL (must be same-origin) const url = trustedScriptURL('./lib/weblisk/core/signal.js');
Permissions Policy
Restrict browser features to reduce attack surface:
import { applyPermissionsPolicy } from 'weblisk/security/permissions.js'; applyPermissionsPolicy({ camera: 'none', microphone: 'none', geolocation: 'self', payment: 'self', });
Default policy denies all features unless explicitly allowed.
Client-Side Auth Pro
JWT-based authentication with reactive session signals, auto-refresh, and route guards. Works with any JWT-issuing backend — zero server coupling.
Setup
import { init, setToken, logout, user, authenticated } from 'weblisk/pro/auth.js'; // Initialize — hydrates from localStorage, schedules auto-refresh init({ storageKey: 'wl-token', refreshBefore: 60, // Refresh 60s before expiry onRefresh: async () => { const res = await fetch('/api/refresh', { method: 'POST' }); const data = await res.json(); return data.token; }, });
Reactive Signals
The user and authenticated exports are reactive computed signals — use them in effects or bindings to auto-update your UI:
import { effect } from 'weblisk'; import { user, authenticated } from 'weblisk/pro/auth.js'; effect(() => { if (authenticated()) { const u = user(); greeting.textContent = `Welcome, ${u.name}`; } else { greeting.textContent = 'Please sign in'; } });
Login & Logout
// After a successful login setToken(response.jwt); // Sign out — clears token, stops refresh timer logout();
Route Guard
Protect routes by combining auth signals with Weblisk guards:
import { guard } from 'weblisk/nav/guard.js'; import { authenticated } from 'weblisk/pro/auth.js'; guard(() => { if (!authenticated()) { location.href = '/login.html'; return false; } return true; });
API Reference
| Export | Description |
|---|---|
init(opts?) | Initialize auth — hydrate from storage, schedule refresh |
setToken(jwt) | Set the auth token (after login) |
logout() | Clear token and stop refresh timer |
user() | Reactive signal — decoded JWT payload or null |
authenticated() | Reactive signal — true if valid & not expired |
getToken() | Get the raw JWT string |