Skip to main content

Security

Weblisk's security modules cover the OWASP essentials with zero dependencies.

Content Security Policy

Generate and inject a strict CSP:

js
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:

js
const hash = await scriptHash('console.log("hello")');
// → 'sha256-abc...'

CSRF Protection

Generate and inject CSRF tokens:

js
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:

js
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>');
// → '&lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;'

// 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:

js
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:

js
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

js
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:

js
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

js
// 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:

js
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

ExportDescription
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