Front-End-Checklist 安全规则实战Secure Password Input Fields 密码输入字段完整实现指南【免费下载链接】Front-End-Checklist The essential checklist for modern web development, for humans and AI agents项目地址: https://gitcode.com/gh_mirrors/fr/Front-End-Checklist密码输入字段是登录、注册等核心表单中最敏感的前端控件。本篇基于 Front-End-Checklist 仓库的password-field-security规则SKILL 与规则文档双形态系统讲解如何用正确的autocomplete语义、可访问的显示/隐藏切换、实时强度指示器与泄露密码检测构建既安全又易用的密码输入体验同时结合仓库中 MCP 代码审查工具对该规则的检测实现与单元测试说明如何在工程化审查流程中自动化落地这一规则。规则背景为什么密码输入字段值得一条独立的安全规则在 Front-End-Checklist 仓库中password-field-security被归类为security 类别同时关联 html、accessibility 两个维度属于subcategory: forms优先级为high难度intermediate预估耗时30 分钟。规则页面位于 packages/content/rules/en/security/password-field-security.mdx并以 Agent 可消费的 SKILL 形态存放在 skills/password-field-security/SKILL.md完整实现细节见其 references/rule.md。该规则的定位一句话即可概括正确实现的密码字段通过配合密码管理器、帮助用户创建强密码、为所有用户提供可访问控件从而显著改善安全性原文Properly implemented password fields improve security by working with password managers, helping users create strong passwords, and providing accessible controls for all users.。从规则元数据看其权威依据来自 OWASP HTTP Headers Cheat Sheet 与 MDN Web security 文档并推荐使用 Mozilla Observatory 作为辅助验证工具见 mdx 前端sources/resources字段。同时该规则在relatedRules中与form-captcha、form-https、search-input、input-image-alt互相引用——它们同属security/forms领域常在一次审查中一起出现。快速检查清单Quick ReferenceSKILL.md 中给出了 5 条可快速执行的核心要点这也是整个规则的检查骨架使用typepassword并搭配正确的autocomplete属性提供可访问的显示/隐藏密码切换控件展示带具体要求的密码强度指示器绝不存储或以明文传输密码使用正确的输入name以支持密码管理器。对应到 SKILL 的四大动作提示Check / Fix / Explain / Code Review其含义分别是Check检查确认密码字段使用typepassword、具有正确的autocomplete值并包含可访问的显示/隐藏切换Fix修复为密码字段补充autocompletenew-password或current-password实现可访问的切换按钮与可选的强度计Explain解释向业务方解释密码字段的安全与 UX 最佳实践包括 autocomplete 属性和可访问的揭示reveal功能Code Review代码审查审查与密码输入字段相关的服务端配置、HTTP 头、表单与集成点标记违反规则的响应、Cookie 或浏览器行为并与真实生产环境的响应进行核对。这四大提示正是 Agent 与人工审查通用的检查-修复-解释-复核闭环。基础实现带正确 autocomplete 的 HTML 登录 / 注册表单规则文档首先给出两个可直接复制的 HTML 示例它们是本规则最底层的落地形态。登录表单!-- Login form -- form methodPOST action/login div label foremailEmail/label input typeemail idemail nameemail autocompleteemail required / /div div label forpasswordPassword/label input typepassword idpassword namepassword autocompletecurrent-password required minlength8 / /div button typesubmitSign In/button /form关键点登录场景使用autocompletecurrent-password浏览器与密码管理器会据此把已保存的密码自动填充进来minlength8提供前端基础长度约束。注册表单!-- Registration form -- form methodPOST action/register div label foremailEmail/label input typeemail idemail nameemail autocompleteemail required / /div div label fornew-passwordCreate Password/label input typepassword idnew-password namepassword autocompletenew-password required minlength12 aria-describedbypassword-requirements / p idpassword-requirements At least 12 characters with uppercase, lowercase, and numbers. /p /div button typesubmitCreate Account/button /form注册场景改用autocompletenew-password触发密码管理器建议强密码能力aria-describedby把密码要求说明至少 12 位包含大小写字母与数字关联到输入框屏幕阅读器用户也能听到约束说明——注意这里的最小长度比登录场景更严格12 位。autocomplete 属性速查表规则文档用一个表格明确了不同场景应使用的 autocomplete 值场景属性用途登录表单autocompletecurrent-password填充已有密码注册表单autocompletenew-password建议强密码用户名autocompleteusername与密码关联邮箱登录autocompleteemail基于邮箱的认证实践中最容易犯的错误就是四个字段全部漏写 autocomplete或一律写成autocompleteoff。后者会直接禁用密码管理器的自动填充能力属于本规则要重点拦截的行为。React 实现可访问的密码显示/隐藏切换Password Field with Toggle规则文档提供了完整的 ReactTSX实现核心是一个支持受控值、错误态、最小长度与显示切换的PasswordField组件。它同时示范了三个可访问性细节useId()生成稳定 id、aria-pressed表达切换状态、aria-invalid/rolealert表达错误。import { useState, useId } from react interface PasswordFieldProps { label: string name: string autocomplete: current-password | new-password value: string onChange: (value: string) void error?: string minLength?: number } export function PasswordField({ label, name, autocomplete, value, onChange, error, minLength 8, }: PasswordFieldProps) { const [showPassword, setShowPassword] useState(false) const inputId useId() const errorId useId() return ( div classNamepassword-field label htmlFor{inputId} classNamepassword-label {label} /label div classNamepassword-input-wrapper input type{showPassword ? text : password} id{inputId} name{name} value{value} onChange{(e) onChange(e.target.value)} autoComplete{autocomplete} minLength{minLength} required aria-invalid{error ? true : false} aria-describedby{error ? errorId : undefined} classNamepassword-input / button typebutton onClick{() setShowPassword(!showPassword)} aria-label{showPassword ? Hide password : Show password} aria-pressed{showPassword} classNamepassword-toggle {showPassword ? ( EyeOffIcon aria-hiddentrue / ) : ( EyeIcon aria-hiddentrue / )} /button /div {error ( p id{errorId} rolealert classNamepassword-error {error} /p )} /div ) } function EyeIcon(props: React.SVGPropsSVGSVGElement) { return ( svg viewBox0 0 24 24 width{20} height{20} {...props} path fillcurrentColor dM12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z / /svg ) } function EyeOffIcon(props: React.SVGPropsSVGSVGElement) { return ( svg viewBox0 0 24 24 width{20} height{20} {...props} path fillcurrentColor dM12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z / /svg ) }几个值得注意的实现决策切换按钮必须typebutton避免误触发表单提交aria-pressed同步状态屏幕阅读器能播报当前是显示还是隐藏错误使用rolealert出错时立即向辅助技术播报图标使用aria-hiddentrue并从可访问名中排除按钮名称完全由aria-label决定。密码强度指示器实时反馈 无障碍播报规则文档提供了一个纯函数式强度计算 展示组件的实现把强度定义为 5 项具体要求的命中数长度 ≥ 12、小写、大写、数字、特殊字符再映射为 0~4 分interface PasswordStrengthProps { password: string } interface StrengthResult { score: 0 | 1 | 2 | 3 | 4 label: string requirements: { met: boolean text: string }[] } function calculateStrength(password: string): StrengthResult { const requirements [ { met: password.length 12, text: At least 12 characters, }, { met: /[a-z]/.test(password), text: One lowercase letter, }, { met: /[A-Z]/.test(password), text: One uppercase letter, }, { met: /[0-9]/.test(password), text: One number, }, { met: /[^a-zA-Z0-9]/.test(password), text: One special character, }, ] const metCount requirements.filter((r) r.met).length const scoreMap: Recordnumber, { score: StrengthResult[score]; label: string } { 0: { score: 0, label: Very weak }, 1: { score: 1, label: Weak }, 2: { score: 1, label: Weak }, 3: { score: 2, label: Fair }, 4: { score: 3, label: Good }, 5: { score: 4, label: Strong }, } return { ...scoreMap[metCount], requirements, } } export function PasswordStrength({ password }: PasswordStrengthProps) { const strength calculateStrength(password) if (!password) return null return ( div classNamepassword-strength aria-livepolite div classNamestrength-bar div className{strength-fill strength-${strength.score}} style{{ width: ${(strength.score 1) * 20}% }} / /div span classNamestrength-label{strength.label}/span ul classNamestrength-requirements {strength.requirements.map((req, index) ( li key{index} className{req.met ? met : unmet} span aria-hiddentrue{req.met ? ✓ : ○}/span span className{req.met ? sr-only : undefined} {req.met ? Complete: : Incomplete: } /span {req.text} /li ))} /ul /div ) }实现细节要点aria-livepolite使强度变化分数、标签、每项要求命中状态被屏幕阅读器温和播报不会打断当前操作进度条宽度按(score 1) * 20%计算从 20%Very weak到 100%Strong每一项要求都渲染为列表项用✓/○视觉区分aria-hidden同时通过sr-only文本补充Complete:/Incomplete:状态做到视觉与无障碍信息双通道空密码时不渲染任何内容if (!password) return null。完整注册表单组件组合与前端校验规则文档把上述组件组装成一个完整的RegistrationForm客户端组件use client示范了邮箱 密码 确认密码的完整流程与提交前校验use client import { useState } from react import { PasswordField } from ./password-field import { PasswordStrength } from ./password-strength export function RegistrationForm() { const [email, setEmail] useState() const [password, setPassword] useState() const [confirmPassword, setConfirmPassword] useState() const [errors, setErrors] useStateRecordstring, string({}) const handleSubmit async (e: React.FormEvent) { e.preventDefault() const newErrors: Recordstring, string {} if (password.length 12) { newErrors.password Password must be at least 12 characters } if (password ! confirmPassword) { newErrors.confirmPassword Passwords do not match } if (Object.keys(newErrors).length 0) { setErrors(newErrors) return } // Submit form // await register({ email, password }) } return ( form onSubmit{handleSubmit} classNameregistration-form div classNameform-group label htmlForemailEmail/label input typeemail idemail nameemail value{email} onChange{(e) setEmail(e.target.value)} autoCompleteemail required / /div div classNameform-group PasswordField labelCreate Password namepassword autocompletenew-password value{password} onChange{setPassword} error{errors.password} minLength{12} / PasswordStrength password{password} / /div div classNameform-group PasswordField labelConfirm Password nameconfirmPassword autocompletenew-password value{confirmPassword} onChange{setConfirmPassword} error{errors.confirmPassword} minLength{12} / /div button typesubmit classNamesubmit-button Create Account /button /form ) }这里体现出两个工程要点校验只在提交时执行检查密码长度是否 ≥ 12、两次输入是否一致错误通过errors对象注入PasswordField的error属性由组件渲染为带rolealert的错误提示确认密码字段同样使用autocompletenew-password避免浏览器把已保存的密码错误填充到确认框。需要强调的是前端校验仅是体验层约束真正的安全边界在服务端——规则文档的Security Best Practices一节对此有明确要求见下文。配套样式兼顾聚焦态、错误态与切换按钮规则文档给出了完整 CSS覆盖输入框、聚焦环、错误态、切换按钮与强度条。以下为可直接复用的核心片段.password-field { margin-bottom: 1rem; } .password-label { display: block; margin-bottom: 0.5rem; font-weight: 500; } .password-input-wrapper { position: relative; display: flex; align-items: center; } .password-input { width: 100%; padding: 0.75rem 3rem 0.75rem 1rem; border: 1px solid #ddd; border-radius: 4px; font-size: 1rem; } .password-input:focus { outline: none; border-color: #0066cc; box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.2); } .password-input[aria-invalidtrue] { border-color: #dc2626; } .password-toggle { position: absolute; right: 0.75rem; padding: 0.25rem; background: none; border: none; color: #666; cursor: pointer; } .password-toggle:hover { color: #333; } .password-toggle:focus-visible { outline: 2px solid #0066cc; outline-offset: 2px; border-radius: 2px; } .password-error { margin-top: 0.5rem; color: #dc2626; font-size: 0.875rem; } /* Strength indicator */ .password-strength { margin-top: 0.75rem; } .strength-bar { height: 4px; background: #e5e5e5; border-radius: 2px; overflow: hidden; } .strength-fill { height: 100%; transition: width 0.3s, background-color 0.3s; } .strength-0 { background: #dc2626; } .strength-1 { background: #f97316; } .strength-2 { background: #eab308; } .strength-3 { background: #84cc16; } .strength-4 { background: #22c55e; } .strength-label { display: block; margin-top: 0.25rem; font-size: 0.75rem; color: #666; } .strength-requirements { list-style: none; padding: 0; margin: 0.5rem 0 0; font-size: 0.875rem; } .strength-requirements li { display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0; } .strength-requirements .met { color: #22c55e; } .strength-requirements .unmet { color: #666; } .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); border: 0; }样式上的设计意图值得说明输入框右侧预留3rem内边距给切换按钮腾出空间聚焦态使用box-shadow外发光而非仅改边框色符合 WCAG 对可见焦点的要求aria-invalidtrue时输入框变红与rolealert的错误文案构成双重错误提示强度条带transition视觉上平滑反馈输入变化。服务端与传输安全基线Security Best Practices规则文档强调前端组件的正确性只是其中一环密码安全是全链路职责。下表是该规则明确列出的安全实践基线实践实现方式绝不记录密码从日志、监控中排除密码字段密码必须哈希存储使用 bcrypt、Argon2 或 scrypt强制最小长度至少 12 个字符检测泄露密码使用 Have I Been Pwned API限制尝试次数防止暴力破解全程使用 HTTPS保证传输加密其中绝不记录密码直接呼应了仓库 MCP 审查工具中的另一条相邻规则review-code.ts的 secret 检测模式包含/(?:password|passwd|pwd)\s*[:]\s*[][^]{6,}[]/i见 review-code.ts一旦在源码中发现硬编码密码/凭据即判定为安全问题。也就是说前端展示层 审查工具层共同把密码不得以明文形式出现落实到了代码评审环节。泄露密码检测基于 k-匿名性的 Breach Check 集成规则文档还给出了一个可选的增强实现——在注册时用 Have I Been Pwned 的 k-anonymityk 匿名接口检查密码是否出现在已知泄露数据中。其核心思想是绝不把完整密码哈希发送给第三方只发送 SHA-1 哈希的前 5 位作为查询前缀再在返回的哈希后缀列表中本地比对。// Check password against known breaches (k-anonymity safe) async function checkPasswordBreach(password: string): Promiseboolean { const encoder new TextEncoder() const data encoder.encode(password) const hashBuffer await crypto.subtle.digest(SHA-1, data) const hashArray Array.from(new Uint8Array(hashBuffer)) const hashHex hashArray.map(b b.toString(16).padStart(2, 0)).join().toUpperCase() const prefix hashHex.slice(0, 5) const suffix hashHex.slice(5) // Only send first 5 chars (k-anonymity) const response await fetch(https://api.pwnedpasswords.com/range/${prefix}) const text await response.text() // Check if suffix is in response return text.includes(suffix) }流程拆解在浏览器端用 Web Crypto APIcrypto.subtle.digest(SHA-1, ...)计算密码的 SHA-1 哈希并以大写十六进制表示拆分为前 5 位prefix与其余suffix仅向https://api.pwnedpasswords.com/range/{prefix}发送前缀服务端返回所有以该前缀开头的泄露哈希后缀列表本地检查suffix是否命中列表命中即说明该密码出现在已知泄露事件中应阻止注册或强制用户更换。由于只传输 5 个十六进制字符即使查询被截获也无法还原密码同时服务端响应按 k 匿名模型设计不会暴露具体是哪一个密码——这是在不泄露用户隐私前提下获得泄露检测能力的关键设计。例外情形Exceptions规则文档明确列出了三条例外边界避免规则被教条化误用只有在业务需求与补偿性控制措施被显式记录时才允许使用较弱表单控件如果整个流程本身已不安全传输未加密、不可访问、或以外嵌方式改变了威胁模型应优先修复更严重的问题而不是纠结于本规则细节在演示demo、沙箱或刻意受限的流程中误报很常见但仍应加以约束并明确标注。验证清单自动化与人工双通道规则文档最后给出验证建议分自动化与人工两层自动化检查用键盘Enter 与 Space测试显示/隐藏切换测试带校验错误的表单提交在 1Password、LastPass、Bitwarden 中实测自动填充。人工检查验证 autocomplete 属性确实与密码管理器协作生效确认屏幕阅读器能播报切换按钮状态确认强度指示器实时更新检查错误态下的焦点管理焦点应正确移动到错误提示或保持在正确位置。仓库源码级佐证规则如何被自动审查Front-End-Checklist 不仅把这条规则写成文档还在 MCPModel Context Protocol审查工具中实现了对应的启发式检测。在 review-code.ts 中可以看到// password-field-security — password fields should declare autocomplete intent if (slug.includes(password-field) || slug.includes(password-security)) { const passwordFields code.match(/input[^]*type\s*\s*[]password[][^]*/gi) || [] const noAutocomplete passwordFields.filter(f !f.includes(autocomplete)) if (noAutocomplete.length 0) { return { hasIssue: true, issue: Found ${noAutocomplete.length} password field(s) without autocomplete attribute — add autocompletecurrent-password or new-password } } }该实现的正则逻辑是找出所有typepassword的input标签再筛选其中缺少autocomplete的字段一旦存在即报告问题提示语与 SKILL 的 Fix 建议完全一致add autocompletecurrent-password or new-password。这一规则被纳入 MCP 审查工具的启发式覆盖清单见 heuristic-coverage.test.ts并有专门单元测试保证检测能力见 review-code-detection.test.tsit(detects password field without autocomplete, () { const html input typepassword namepassword const rules rulesDetectedIn(html, [security]) expect(rules).toContain(password-field-security) })同时在误报审计测试false-positive-audit.test.ts中合规样例autocompletecurrent-password被用于验证规则不会误报。这意味着当你对一段包含input typepassword的代码运行 MCP 审查时缺 autocomplete 的写法会精确命中password-field-security规则而正确写法不会触发告警——文档规则与工具检测形成了闭环。从仓库的生成机制看这些 SKILL 文件并非手写脚本 generate-skills.ts 会读取规则 MDX 的 frontmatter将aiContext或description规范化为以 Use when 开头的 Agent 意图描述再把规则正文转换为纯 Markdown 写入references/rule.md见 SKILL.md 中 seereferences/rule.md 的引用与生成逻辑。因此本规则同时存在两种形态供人类阅读的规则文档MDX与供 Agent 消费的技能文件SKILL两者内容同源、互相对应。总结password-field-security是 Front-End-Checklist 中小而关键的一类安全规则它不要求复杂架构却覆盖了密码字段的四个核心维度——输入语义type与autocomplete、可访问性切换按钮、错误播报、强度播报、强度引导实时指标与要求清单与传输/存储安全HTTPS、哈希、防泄露、防暴力破解。落地时建议按此顺序推进为所有密码输入补上正确的autocomplete登录current-password、注册new-password用typebutton的切换按钮 aria-pressed实现显示/隐藏并确保键盘可达注册流程接入强度指示器提交时校验长度与一致性服务端落实哈希存储、限流与 HTTPS可选增强接入 k-匿名泄露检测把上述检查固化为自动化审查如本仓库 MCP 工具的行为并在密码管理器与屏幕阅读器下做人工回归。深入阅读入口规则文档 MDX、Agent 技能文件、完整实现参考、MCP 审查实现 与 对应单元测试。【免费下载链接】Front-End-Checklist The essential checklist for modern web development, for humans and AI agents项目地址: https://gitcode.com/gh_mirrors/fr/Front-End-Checklist创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
