MCPInstall

form-security

Security patterns for web forms including autocomplete attributes for password managers, CSRF protection, XSS prevention, and input sanitization. Use when implementing authentication forms, payment forms, or any form handling sensitive data.

Installs
64
Last 24h
—
Trending rank
—
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/bbeierle12/skill-mcp-claude --skill form-security
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads form-security automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

Form Security

Security-first patterns for web forms. Ensures password manager compatibility, prevents common attacks, and protects user data.

Quick Start

// The 3 critical security patterns
<form>
  {/* 1. Autocomplete for password managers */}
  <input type="email" autoComplete="email" />
  <input type="password" autoComplete="current-password" />
  
  {/* 2. CSRF token */}
  <input type="hidden" name="_csrf" value={csrfToken} />
  
  {/* 3. Allow paste (never disable!) */}
  <input type="password" /> {/* No onPaste handler blocking */}
</form>

Autocomplete Attributes

Why It Matters

  • 1Password, LastPass, Bitwarden rely on autocomplete to identify fields
  • Without correct values, password managers fail silently
  • Users abandon forms when autofill doesn't work
  • Security improves when users can use unique, strong passwords

The Autocomplete Specification

// autocomplete-config.ts
export const AUTOCOMPLETE = {
  // ===== IDENTITY =====
  name: 'name',                    // Full name
  honorificPrefix: 'honorific-prefix', // Mr., Mrs., Dr.
  givenName: 'given-name',         // First name
  additionalName: 'additional-name', // Middle name
  familyName: 'family-name',       // Last name
  honorificSuffix: 'honorific-suffix', // Jr., III
  nickname: 'nickname',
  
  // ===== AUTHENTICATION (CRITICAL) =====
  email: 'email',
  username: 'username',
  currentPassword: 'current-password',  // LOGIN forms
  newPassword: 'new-password',          // REGISTRATION + RESET forms
  oneTimeCode: 'one-time-code',         // 2FA/OTP codes
  
  // ===== CONTACT =====
  tel: 'tel',                      // Full phone
  telCountryCode: 'tel-country-code',
  telNational: 'tel-national',
  telAreaCode: 'tel-area-code',
  telLocal: 'tel-local',
  telExtension: 'tel-extension',
  
  // ===== ADDRESS =====
  streetAddress: 'street-address', // Full street (may be multiline)
  addressLine1: 'address-line1',   // Street line 1
  addressLine2: 'address-line2',   // Apt, Suite, etc.
  addressLine3: 'address-line3',
  addressLevel1: 'address-level1', // State/Province
  addressLevel2: 'address-level2', // City
  addressLevel3: 'address-level3', // District
  addressLevel4: 'address-level4', // Neighborhood
  postalCode: 'postal-code',
  country: 'country',
  countryName: 'country-name',
  
  // ===== PAYMENT (CRITICAL) =====
  ccName: 'cc-name',               // Name on card
  ccGivenName: 'cc-given-name',
  ccFamilyName: 'cc-family-name',
  ccNumber: 'cc-number',           // Card number
  ccExp: 'cc-exp',                 // Expiry (MM/YY)
  ccExpMonth: 'cc-exp-month',      // Expiry month
  ccExpYear: 'cc-exp-year',        // Expiry year
  ccCsc: 'cc-csc',                 // CVV/CVC
  ccType: 'cc-type',               // Visa, Mastercard, etc.
  
  // ===== ORGANIZATION =====
  organization: 'organization',
  organizationTitle: 'organization-title', // Job title
  
  // ===== DATES =====
  bday: 'bday',                    // Full birthday
  bdayDay: 'bday-day',
  bdayMonth: 'bday-month',
  bdayYear: 'bday-year',
  
  // ===== OTHER =====
  sex: 'sex',                      // Gender
  url: 'url',                      // Website
  photo: 'photo',                  // Photo URL
  language: 'language',
  
  // ===== SPECIAL VALUES =====
  off: 'off',                      // Disable autofill (use sparingly!)
  on: 'on'                         // Enable autofill (default)
} as const;

export type AutocompleteValue = typeof AUTOCOMPLETE[keyof typeof AUTOCOMPLETE];

Critical Password Patterns

// ✅ LOGIN: Use current-password
<form action="/login">
  <input type="email" autoComplete="email" />
  <input type="password" autoComplete="current-password" />
</form>

// ✅ REGISTRATION: Use new-password (BOTH fields)
<form action="/register">
  <input type="email" autoComplete="email" />
  <input type="password" autoComplete="new-password" />
  <input type="password" autoComplete="new-password" /> {/* confirm */}
</form>

// ✅ PASSWORD RESET: Use new-password
<form action="/reset-password">
  <input type="password" autoComplete="new-password" />
  <input type="password" autoComplete="new-password" /> {/* confirm */}
</form>

// ✅ CHANGE PASSWORD: current + new
<form action="/change-password">
  <input type="password" autoComplete="current-password" /> {/* old */}
  <input type="password" autoComplete="new-password" />     {/* new */}
  <input type="password" autoComplete="new-password" />     {/* confirm */}
</form>

// ✅ 2FA/OTP: Use one-time-code
<form action="/verify-2fa">
  <input 
    type="text" 
    inputMode="numeric" 
    autoComplete="one-time-code" 
    pattern="[0-9]*"
  />
</form>

Why new-password for Registration

// ❌ WRONG: Using current-password on registration
// Password manager tries to fill EXISTING password
<input type="password" autoComplete="current-password" />

// ✅ CORRECT: Using new-password
// Password manager offers to GENERATE a new password
<input type="password" autoComplete="new-password" />

Payment Form Pattern

<form action="/checkout">
  <input 
    type="text" 
    autoComplete="cc-name" 
    placeholder="Name on card"
  />
  
  <input 
    type="text" 
    inputMode="numeric"
    autoComplete="cc-number" 
    placeholder="Card number"
  />
  
  <input 
    type="text" 
    autoComplete="cc-exp" 
    placeholder="MM/YY"
  />
  
  <input 
    type="text" 
    inputMode="numeric"
    autoComplete="cc-csc" 
    placeholder="CVV"
  />
</form>

Address Form Pattern

<fieldset>
  <legend>Shipping Address</legend>
  
  <input autoComplete="name" placeholder="Full name" />
  <input autoComplete="address-line1" placeholder="Street address" />
  <input autoComplete="address-line2" placeholder="Apt, Suite, etc." />
  <input autoComplete="address-level2" placeholder="City" />
  <input autoComplete="address-level1" placeholder="State" />
  <input autoComplete="postal-code" placeholder="ZIP code" />
  <select autoComplete="country">
    <option value="US">United States</option>
    {/* ... */}
  </select>
</fieldset>

CSRF Protection

Token Generation (Server)

// server/csrf.ts
import crypto from 'crypto';

export function generateCsrfToken(): string {
  return crypto.randomBytes(32).toString('hex');
}

// Store in session
app.use((req, res, next) => {
  if (!req.session.csrfToken) {
    req.session.csrfToken = generateCsrfToken();
  }
  res.locals.csrfToken = req.session.csrfToken;
  next();
});

Token Inclusion (Client)

// React pattern
function Form({ csrfToken }) {
  return (
    <form method="POST">
      <input type="hidden" name="_csrf" value={csrfToken} />
      {/* form fields */}
    </form>
  );
}

// With fetch
async function submitForm(data: FormData) {
  const response = await fetch('/api/submit', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-CSRF-Token': csrfToken
    },
    body: JSON.stringify(data)
  });
}

Token Validation (Server)

// Middleware
function validateCsrf(req, res, next) {
  const tokenFromBody = req.body._csrf;
  const tokenFromHeader = req.headers['x-csrf-token'];
  const sessionToken = req.session.csrfToken;
  
  const providedToken = tokenFromBody || tokenFromHeader;
  
  if (!providedToken || providedToken !== sessionToken) {
    return res.status(403).json({ error: 'Invalid CSRF token' });
  }
  
  next();
}

// Apply to state-changing routes
app.post('/api/*', validateCsrf);
app.put('/api/*', validateCsrf);
app.delete('/api/*', validateCsrf);

Double Submit Cookie Pattern

// Alternative: Cookie + Header must match
// Server sets cookie
res.cookie('csrf', token, { httpOnly: false, sameSite: 'strict' });

// Client reads cookie and sends in header
const csrfToken = document.cookie
  .split('; ')
  .find(row => row.startsWith('csrf='))
  ?.split('=')[1];

fetch('/api/submit', {
  headers: { 'X-CSRF-Token': csrfToken }
});

// Server validates cookie === header

XSS Prevention

Never Trust User Input

// ❌ DANGEROUS: Directly rendering user input
<div dangerouslySetInnerHTML={{ __html: userInput }} />

// ✅ SAFE: React auto-escapes by default
<div>{userInput}</div>

// ✅ SAFE: Explicit sanitization when HTML needed
import DOMPurify from 'dompurify';
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />

Input Sanitization

// sanitize.ts
import DOMPurify from 'dompurify';

// For plain text (strip all HTML)
export function sanitizeText(input: string): string {
  return DOMPurify.sanitize(input, { ALLOWED_TAGS: [] });
}

// For rich text (allow safe HTML)
export function sanitizeHtml(input: string): string {
  return DOMPurify.sanitize(input, {
    ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p', 'br'],
    ALLOWED_ATTR: ['href', 'title']
  });
}

// For URLs
export function sanitizeUrl(url: string): string {
  const sanitized = DOMPurify.sanitize(url);
  // Only allow http(s) and relative URLs
  if (/^(https?:\/\/|\/[^\/])/i.test(sanitized)) {
    return sanitized;
  }
  return '';
}

Content Security Policy

// Set CSP headers (Express)
app.use((req, res, next) => {
  res.setHeader(
    'Content-Security-Policy',
    "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"
  );
  next();
});

Password Field Security

Never Disable Paste

// ❌ DANGEROUS: Disabling paste
<input type="password" onPaste={(e) => e.preventDefault()} />

// ✅ CORRECT: Allow paste (password managers need it!)
<input type="password" />

Password Visibility Toggle

function PasswordInput({ ...props }) {
  const [visible, setVisible] = useState(false);
  
  return (
    <div className="password-input">
      <input
        type={visible ? 'text' : 'password'}
        {...props}
      />
      <button
        type="button"
        onClick={() => setVisible(!visible)}
        aria-label={visible ? 'Hide password' : 'Show password'}
      >
        {visible ? <EyeOffIcon /> : <EyeIcon />}
      </button>
    </div>
  );
}

Don't Log Passwords

// ❌ DANGEROUS
console.log('Login attempt:', { email, password });

// ✅ SAFE
console.log('Login attempt:', { email, password: '[REDACTED]' });

Secure Form Submission

HTTPS Only

// Redirect HTTP to HTTPS
app.use((req, res, next) => {
  if (req.headers['x-forwarded-proto'] !== 'https') {
    return res.redirect(`https://${req.headers.host}${req.url}`);
  }
  next();
});

Secure Cookies

// Set secure cookie flags
res.cookie('session', sessionId, {
  httpOnly: true,     // Prevent XSS access
  secure: true,       // HTTPS only
  sameSite: 'strict', // CSRF protection
  maxAge: 3600000     // 1 hour
});

Rate Limiting

import rateLimit from 'express-rate-limit';

const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 5, // 5 attempts
  message: 'Too many login attempts. Please try again later.'
});

app.post('/login', loginLimiter, handleLogin);

Security Checklist

Authentication Forms

  • autocomplete="email" on email field
  • autocomplete="current-password" on login password
  • autocomplete="new-password" on registration/reset password
  • autocomplete="one-time-code" on 2FA field
  • Paste is allowed on all password fields
  • CSRF token included
  • Rate limiting enabled
  • HTTPS enforced

Payment Forms

  • autocomplete="cc-*" attributes on all card fields
  • inputMode="numeric" on number fields
  • CSRF token included
  • PCI DSS compliance (use Stripe/Braintree)
  • No card data logged

All Forms

  • Input validation (client + server)
  • Output encoding (XSS prevention)
  • Error messages don't leak sensitive info
  • Secure cookie settings
  • CSP headers configured

File Structure

form-security/
├── SKILL.md
├── references/
│   ├── autocomplete-spec.md    # Full autocomplete reference
│   └── csrf-patterns.md        # CSRF implementation patterns
└── scripts/
    ├── autocomplete-config.ts  # Autocomplete constants
    ├── csrf-token.ts           # CSRF token utilities
    ├── sanitize.ts             # Input sanitization
    └── secure-input.tsx        # Secure input components

Reference

  • references/autocomplete-spec.md — Complete autocomplete attribute reference
  • references/csrf-patterns.md — CSRF implementation patterns

FAQ

What does the form-security skill do?

Security patterns for web forms including autocomplete attributes for password managers, CSRF protection, XSS prevention, and input sanitization. Use when implementing authentication forms, payment forms, or any form handling sensitive data.

How do I install form-security?

Run npx skills add https://github.com/bbeierle12/skill-mcp-claude --skill form-security in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/form-security/ (personal) or .claude/skills/form-security/ (project).

Which AI agents can use form-security?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is form-security safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains form-security?

It is published by bbeierle12 in bbeierle12/skill-mcp-claude. It has 64 recorded installs.

More from bbeierle12/skill-mcp-claude

View all →

gsap-react

bbeierle12/skill-mcp-claude

GSAP integration with React including useGSAP hook, ref handling, cleanup patterns, and context management. Use when implementing GSAP animations in React components, handling component lifecycle, or building reusable animation hooks.

Frontend & Design724 installs

gsap-scrolltrigger

bbeierle12/skill-mcp-claude

Scroll-based animations using GSAP ScrollTrigger plugin including pinning, scrubbing, snap points, and parallax effects. Use when creating scroll-driven animations, sticky sections, progress indicators, or parallax scrolling experiences.

AI & Agents605 installs

gsap-fundamentals

bbeierle12/skill-mcp-claude

Core GSAP animation concepts including tweens, timelines, easing functions, and animation properties. Use when implementing basic animations, transitions, or learning GSAP foundations. Essential starting point for any GSAP-based animation work.

Frontend & Design282 installs

shader-effects

bbeierle12/skill-mcp-claude

Visual shader effects—glow/bloom, chromatic aberration, distortion, vignette, film grain, scanlines, glitch, dissolve, outline, and fresnel. Use when adding visual polish, post-processing effects, or stylized rendering to shaders.

AI & Agents214 installs

d3js-visualization

bbeierle12/skill-mcp-claude

Create D3.js charts and interactive data visualizations. Use when building bar charts, line charts, scatter plots, pie charts, force-directed graphs, geographic maps, or any custom data visualization.

AI & Agents186 installs

particles-gpu

bbeierle12/skill-mcp-claude

GPU-based particle systems using instanced rendering, buffer attributes, Points geometry, and custom shaders. Use when rendering thousands to millions of particles efficiently, creating particle effects like snow, rain, stars, or abstract visualizations.

AI & Agents169 installs

Popular security skills

View category →

azure-compliance

microsoft/azure-skills

Run Azure compliance and security audits with azqr plus Key Vault expiration checks. Covers best-practice assessment, resource review, policy/compliance validation, and security posture checks. WHEN: compliance scan, security audit, BEFORE running azqr (compliance cli tool), Azure best practices, Key Vault expiration check, expired certificates, expiring secrets, orphaned resources, compliance assessment.

OfficialSecurity567K installs

minimal-run-and-audit

lllllllama/rigorpilot-skills

Rigor Run skill for README-first deep learning repo reproduction. Use when the task is specifically to capture or normalize evidence from the selected smoke test or documented inference or evaluation command and write standardized reprooutputs/ files, including patch notes when repository files changed. Do not use for training execution, initial repo intake, generic environment setup, paper lookup, target selection, hidden scientific-meaning changes, or end-to-end orchestration by itself.

Security477.4K installs

seo-audit

coreyhaines31/marketingskills

When the user wants to audit, review, or diagnose SEO issues on their site. Also use when the user mentions "SEO audit," "technical SEO," "why am I not ranking," "SEO issues," "on-page SEO," "meta tags review," "SEO health check," "my traffic dropped," "lost rankings," "not showing up in Google," "site isn't ranking," "Google update hit me," "page speed," "core web vitals," "crawl errors," "indexing issues," "stuck on page 2," "striking distance keywords," "title tag rewrite," "low CTR," "local SEO," "Google Business Profile," or "map pack." Use this even if the user just says something vague like "my SEO is bad" or "help with SEO" — start with an audit. For building pages at scale to target keywords, see programmatic-seo. For adding structured data, see schema. For AI search optimization, see ai-seo.

Security238.7K installs

firebase-security-rules-auditor

firebase/agent-skills

Audits Firebase (Firestore, Cloud Storage) security rules for vulnerabilities, privilege escalation, role bypasses, create vs update inconsistencies, resource exhaustion, type safety, size limits, and hasOnly ownership checks. Use when auditing/reviewing rules, running red-team rule assessments, or scoring against auditor checklists. Don't use for Firebase CLI (login, deploy), Auth, Crashlytics, Remote Config, or database queries.

OfficialSecurity139.1K installs

audit

pbakaus/impeccable

Run technical quality checks across accessibility, performance, theming, responsive design, and anti-patterns. Generates a scored report with P0-P3 severity ratings and actionable plan. Use when the user wants an accessibility check, performance audit, or technical quality review.

Security81.9K installs

competitors

coreyhaines31/marketingskills

When the user wants to create competitor comparison or alternative pages for SEO and buyer-facing use. Also use when the user mentions 'alternative page,' 'vs page,' 'competitor comparison,' 'comparison page,' '[Product] vs [Product],' '[Product] alternative,' 'competitive landing pages,' 'how do we compare to X,' 'competitor teardown,' 'audit our competitor pages,' 'are our comparison pages out of date,' or 'competitive asset audit.' Use this for any content that positions your product against competitors. Covers four formats: singular alternative, plural alternatives, you vs competitor, and competitor vs competitor. For auditing existing claims (not researching competitors from scratch, which is competitor-profiling; not technical SEO on these pages, which is seo-audit), use the asset audit here. For internal battle cards and sales-specific competitor docs, see sales-enablement.

Security79.3K installs