π Security Features
OnigiriJS includes enterprise-grade security features to protect your applications from CSRF, XSS, and other attacks.
CSRF Protection
Quick Start
<!-- Add CSRF token to your HTML -->
<meta name="csrf-token" content="<?= csrf_token() ?>">
<script>
// Initialize security module (auto-detects token)
Onigiri.security.init({
autoInjectCSRF: true // Automatically add to forms
});
// That's it! All AJAX requests and forms now include CSRF
</script>
Configuration
Onigiri.security.init({
csrfToken: null, // Auto-detected from meta tag
csrfHeader: 'X-CSRF-Token', // Header name for AJAX
csrfParam: '_csrf', // Form parameter name
csrfMetaName: 'csrf-token', // Meta tag name
cspNonce: null, // Auto-detected from scripts
autoInjectCSRF: true // Auto-add to all forms
});
Manual Token Management
// Get current token
const token = Onigiri.security.getToken();
// Set new token
Onigiri.security.setToken('your-new-token');
// Add to specific form
const form = document.querySelector('#my-form');
Onigiri.security.addCSRFToForm(form);
// Add to headers object
let headers = { 'Content-Type': 'application/json' };
headers = Onigiri.security.addCSRFToHeaders(headers);
// Add to data object
let data = { name: 'John' };
data = Onigiri.security.addCSRFToData(data);
Automatic Form Protection
<!-- Forms automatically get CSRF token when autoInjectCSRF is true -->
<form action="/submit" method="POST">
<!-- Hidden CSRF input added automatically -->
<input type="text" name="username">
<button type="submit">Submit</button>
</form>
<script>
// No extra code needed!
// CSRF token is already in the form
</script>
Automatic AJAX Protection
// All AJAX requests include CSRF token automatically
await Onigiri.post('/api/save', { data: 'value' });
// Request includes X-CSRF-Token header
// Convenience methods also include CSRF
await Onigiri.get('/api/users');
await Onigiri.put('/api/users/1', userData);
await Onigiri.delete('/api/users/1');
// Disable CSRF for specific request
await Onigiri.ajax({
url: '/public/api',
method: 'POST',
csrf: false // Disable CSRF for this request
});
CSP (Content Security Policy) Support
Nonce Management
<!-- Server generates nonce -->
<script nonce="<?= csp_nonce() ?>">
// Nonce is auto-detected
Onigiri.security.init();
// Or set manually
Onigiri.security.setNonce('random-nonce-value');
// Get current nonce
const nonce = Onigiri.security.getNonce();
</script>
Safe Script Creation
// Create script element with CSP nonce
const script = Onigiri.security.createScript('app.js', () => {
console.log('π Script loaded!');
});
document.head.appendChild(script);
// Create inline script
const inlineScript = Onigiri.security.createScript(null);
inlineScript.textContent = 'console.log("Hello");';
document.body.appendChild(inlineScript);
Safe Style Creation
// Create style element with CSP nonce
const style = Onigiri.security.createStyle(\`
body {
background: #fff5e6;
font-family: sans-serif;
}
.onigiri {
color: #ff6b6b;
}
\`);
document.head.appendChild(style);
Execute Inline Scripts Safely
// Execute inline code with CSP nonce
Onigiri.security.executeScript(\`
console.log('π This runs safely with CSP!');
const widget = new OnigiriWidget();
widget.init();
\`);
XSS Prevention
HTML Sanitization
// Sanitize user input before displaying
const userInput = '<script>alert("xss")</script>Hello <b>World</b>';
const safe = Onigiri.security.sanitizeHTML(userInput);
console.log(safe); // "Hello World" (script removed, b tag removed)
// Display safely
O('#user-content').html(safe);
HTML Entity Escaping
// Escape HTML entities for safe display
const userText = '<div>User & Content</div>';
const escaped = Onigiri.security.escapeHTML(userText);
console.log(escaped);
// "<div>User & Content</div>"
// Display as text (not HTML)
O('#display').html(escaped);
// Shows: <div>User & Content</div>
Safe User Content Display
// Never trust user input
const comment = userComment; // From form or API
// Method 1: Use text() instead of html()
O('#comment').text(comment); // Safe - displays as text
// Method 2: Escape HTML
O('#comment').html(Onigiri.security.escapeHTML(comment));
// Method 3: Sanitize HTML (removes scripts but keeps formatting)
O('#comment').html(Onigiri.security.sanitizeHTML(comment));
URL Validation
Prevent Open Redirects
// Validate URLs before redirecting
const redirectUrl = getUrlParameter('redirect');
if (Onigiri.security.isValidURL(redirectUrl)) {
window.location = redirectUrl; // Safe
} else {
console.error('Invalid redirect URL');
window.location = '/dashboard'; // Safe fallback
}
Same-Origin Check
// Check if URL is from same origin
const apiUrl = '/api/data';
const externalUrl = 'https://external-site.com/api';
if (Onigiri.security.isSameOrigin(apiUrl)) {
// Safe to load without CORS
await Onigiri.get(apiUrl);
}
if (!Onigiri.security.isSameOrigin(externalUrl)) {
console.warn('External URL - CORS required');
}
π Complete Security Setup
PHP Backend
<?php
// Generate CSRF token
function csrf_token() {
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf_token'];
}
// Generate CSP nonce
function csp_nonce() {
if (empty($_SESSION['csp_nonce'])) {
$_SESSION['csp_nonce'] = base64_encode(random_bytes(16));
}
return $_SESSION['csp_nonce'];
}
// Verify CSRF token
function verify_csrf() {
$token = $_POST['_csrf'] ?? $_SERVER['HTTP_X_CSRF_TOKEN'] ?? '';
return hash_equals($_SESSION['csrf_token'] ?? '', $token);
}
// Set CSP header
$nonce = csp_nonce();
header("Content-Security-Policy: script-src 'self' 'nonce-{$nonce}'; style-src 'self' 'nonce-{$nonce}'");
?>
HTML Template
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="csrf-token" content="<?= csrf_token() ?>">
<title>Secure App</title>
</head>
<body>
<form id="secure-form" action="/api/submit" method="POST">
<input type="email" name="email" placeholder="Email">
<input type="password" name="password" placeholder="Password">
<button type="submit">Login</button>
</form>
<script src="onigiri.core.js"></script>
<script src="onigiri.security.js"></script>
<script src="onigiri.ajax.js"></script>
<script nonce="<?= csp_nonce() ?>">
// Initialize security
Onigiri.security.init({
autoInjectCSRF: true
});
// Form now has CSRF token
// AJAX requests now include CSRF
// Scripts use CSP nonce
O('#secure-form').on('submit', async (e) => {
e.preventDefault();
try {
// CSRF token automatically included
const response = await Onigiri.post('/api/submit', {
email: O('[name="email"]').val(),
password: O('[name="password"]').val()
});
console.log('π Success:', response);
} catch (error) {
console.error('β Error:', error);
}
});
</script>
</body>
</html>
API Endpoint
<?php
// API endpoint with CSRF verification
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Verify CSRF token
if (!verify_csrf()) {
http_response_code(403);
echo json_encode(['error' => 'CSRF token mismatch']);
exit;
}
// Process request safely
$email = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
$password = $_POST['password'];
// Validate
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
http_response_code(400);
echo json_encode(['error' => 'Invalid email']);
exit;
}
// Process login
// ...
echo json_encode(['success' => true]);
}
?>
π Security Best Practices:
- Always initialize the security module before making requests
- Use
text()instead ofhtml()for user content - Validate and sanitize all user input
- Use HTTPS in production
- Rotate CSRF tokens after authentication
- Implement rate limiting on the backend
Security Checklist
- CSRF protection enabled with
Onigiri.security.init() - CSP headers set with nonce for inline scripts
- User input sanitized with
sanitizeHTML()orescapeHTML() - URLs validated before redirects with
isValidURL() - HTTPS enabled in production
- Backend validates CSRF tokens
- Sensitive data stored securely (not in localStorage)
- Rate limiting implemented on API endpoints
Common Security Patterns
Secure Form Submission
// HTML form with validation and CSRF
<form id="registration">
<input name="email" type="email">
<input name="password" type="password">
<button type="submit">Register</button>
</form>
// JavaScript with security
Onigiri.security.init({ autoInjectCSRF: true });
O('#registration').on('submit', async (e) => {
e.preventDefault();
// Validate
const result = O(e.target).validate({
email: { required: true, email: true },
password: { required: true, minLength: 8 }
});
if (!result.isValid) {
// Show errors
return;
}
// Sanitize input
const email = O('[name="email"]').val().trim();
const password = O('[name="password"]').val();
// Submit with CSRF (automatic)
await Onigiri.post('/api/register', { email, password });
});
Secure API Request
async function secureApiCall(endpoint, data) {
try {
// Validate endpoint
if (!Onigiri.security.isSameOrigin(endpoint)) {
throw new Error('Invalid API endpoint');
}
// Make request with CSRF
const response = await Onigiri.post(endpoint, data);
return response;
} catch (error) {
console.error('API Error:', error);
throw error;
}
}
β Development Roadmap
Track the progress of OnigiriJS modules. Tasks are marked complete by the development team.
OnigiriJS Module Roadmap
Implementation progress of planned modules
6 / 21 completed (29%)
onigiri-state
Shared global & scoped state management
onigiri-directives
Declarative DOM bindings (o-show, o-model, etc.)
onigiri-resource
REST-style data models over AJAX
onigiri-observe
Intersection & Mutation observer helpers
onigiri-humhub-ui
Standard HumHub UI abstractions (modal, notify, confirm)
onigiri-lifecycle
Component lifecycle hooks
onigiri-guard
Debounce, throttle, single-run guards
onigiri-scroll
Scroll save/restore & helpers (PJAX-friendly)
onigiri-permission
Client-side permission awareness
onigiri-portal
DOM teleport / overlay mounting
onigiri-router
Micro router (non-SPA, PJAX-first)
onigiri-sanitize
HTML & input sanitization
onigiri-shortcut
Keyboard shortcut manager
onigiri-queue
Sequential async task runner
onigiri-gesture
Touch & swipe helpers
onigiri-devtools
Debugging & inspection helpers
onigiri-plugin
Plugin registration system
onigiri-time
Relative time & timezone utilities
onigiri-emojis
Emoji Picker and Manager
onigiri-tasks
Task Management
onigiri-polls
Polls creation and management
Note: Task completion is managed by the OnigiriJS development team.