Kai Nakamura
Apr 2026
3 tabs
<h1><%= @post.title %></h1>
<p><%= @post.author_name %></p>
<%# Only sanitized rich text should be rendered as HTML %>
<div class="prose"><%= sanitize(@post.body_html, tags: %w[p a ul ol li strong em code], attributes: %w[href]) %></div>
Rails.application.config.content_security_policy do |policy|
policy.default_src :self
policy.base_uri :self
policy.object_src :none
policy.frame_ancestors :none
policy.img_src :self, :https, :data
policy.font_src :self, :https, :data
policy.script_src :self
policy.style_src :self, :https, :unsafe_inline
policy.connect_src :self, 'https://api.example.com'
policy.report_uri '/csp-reports'
end
import DOMPurify from 'dompurify';
export function renderPreview(input) {
const sanitized = DOMPurify.sanitize(input, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'code', 'pre'],
ALLOWED_ATTR: ['href'],
});
document.querySelector('#preview').innerHTML = sanitized;
}
3 files · erb, ruby, javascript
Explain with highlit
XSS defense works best in layers: correct output encoding, sanitization for trusted rich text only, and a restrictive Content-Security-Policy. I avoid storing untrusted HTML unless there is a strong product reason. When rich content is required, I sanitize at write time and keep CSP strict enough to limit blast radius.
Related snips
ruby
# Vulnerable: user input is concatenated directly into SQL.
email = params[:email]
password = params[:password]
sql = "SELECT * FROM users WHERE email = '#{email}' AND password_hash = '#{password}'"
user = ActiveRecord::Base.connection.execute(sql).first
SQL injection prevention with unsafe and safe query patterns
sql-injection
owasp
database
by Kai Nakamura
3 tabs
typescript
import { defaultSchema, type Schema } from 'hast-util-sanitize';
export const markdownSchema: Schema = {
...defaultSchema,
attributes: {
...defaultSchema.attributes,
Safe markdown rendering (remark + rehype)
markdown
security
remark
by codesnips
3 tabs
ruby
Rails.application.config.content_security_policy do |policy|
policy.default_src :self
policy.font_src :self, :https, :data
policy.img_src :self, :https, :data, "https://cdn.example.com"
policy.object_src :none
policy.script_src :self, :https
Content Security Policy (CSP) Starter
rails
security
csp
by codesnips
3 tabs
typescript
import { JSDOM } from 'jsdom';
import createDOMPurify, { DOMPurifyI } from 'dompurify';
const { window } = new JSDOM('');
const DOMPurify: DOMPurifyI = createDOMPurify(window as unknown as Window);
Sanitize user HTML safely (DOMPurify + JSDOM)
security
html
dompurify
by codesnips
2 tabs
ruby
require "loofah"
class HtmlSanitizer
ALLOWED_TAGS = %w[p br a strong em ul ol li blockquote code pre h2 h3].freeze
ALLOWED_ATTRS = %w[href title].freeze
SAFE_SCHEMES = %w[http https mailto].freeze
Safer HTML Sanitization Pipeline
rails
security
xss
by codesnips
4 tabs
plaintext
SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess Off
SecRule ARGS|REQUEST_HEADERS|XML:/* "@detectSQLi" \
"id:1001,phase:2,deny,status:403,log,msg:'Potential SQLi detected'"
ModSecurity WAF rules for common web attack patterns
waf
modsecurity
web-security
by Kai Nakamura
1 tab
Share this code
Here's the card — post it anywhere.