关于 secure-development
面向软件开发者的安全开发技能,依据 Hack23 ISMS 安全开发政策覆盖从输入校验到依赖管理和代码审查的实践,并列出测试与合规要求。
主要功能
- 01规范输入校验与输出编码
- 02涵盖身份验证和访问控制
- 03要求安全加密与配置管理
- 04规定错误处理与安全测试
- 05覆盖依赖管理和代码审查
适用场景
- 01制定 Web 应用和 API 的安全开发规范
- 02审查认证、授权及输入处理实现
- 03规划提交与发布前的安全测试
- 04管理依赖更新及敏感配置
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ hack23/ homepage --skill secure-development安装后在 Claude Code 中输入/secure-development确认已加载。
详细介绍
安全开发技能
目的
此技能确保所有代码开发都遵循 Hack23 ISMS Secure Development Policy 中规定的安全设计原则。它适用于所有软件开发活动,包括 Web 应用、API、基础设施代码和脚本。
规则
输入验证
必须:
- 在用户输入处验证所有用户输入(必须进行服务器端验证)
- 使用允许列表验证(定义允许的内容,而非不允许的内容)
- 验证数据类型、长度、格式和范围
- 在呈现输出前进行编码,以防止 XSS
- 在将输入用于查询、命令或文件操作前进行清理
- 拒绝无效输入,并提供清晰的错误消息(不得暴露系统详情)
不得:
- 仅依赖客户端验证
- 不经验证就信任来自外部来源(API、数据库、文件)的数据
- 将拒绝列表验证作为主要防御措施
- 将未经处理的用户输入回显到浏览器
- 在错误消息中暴露堆栈跟踪或系统信息
身份验证和授权
必须:
- 对所有非公开资源强制进行身份验证
- 对管理访问实施多因素身份验证(MFA)
- 使用安全的会话管理(HTTPOnly、Secure、SameSite Cookie)
- 强制执行强密码策略(至少 12 个字符,并满足复杂度要求)
- 在登录失败 5 次后锁定账户
- 记录所有身份验证事件(成功和失败)
- 对所有访问控制遵循最小权限原则
- 在每个访问点验证授权,而不仅仅是在入口处验证
不得:
- 以明文或可逆加密方式存储密码
- 使用弱哈希算法(MD5、SHA-1)处理密码
- 未经安全审查就实施自定义身份验证方案
- 在用户或系统之间共享身份验证凭据
- 默认授予广泛访问权限
密码学
必须:
- 对称加密使用 AES-256
- 非对称加密使用 RSA-2048 或更高强度
- 哈希使用 SHA-256 或更高强度
- 对所有网络通信强制使用 TLS 1.2 或更高版本
- 安全存储加密密钥(使用密钥管理系统,不要将密钥写入代码)
- 使用密码学安全的随机数生成器(不要使用 Math.random())
- 根据策略轮换加密密钥
不得:
- 在源代码中硬编码加密密钥、密码或机密
- 使用已弃用的算法(DES、3DES、MD5、SHA-1、SSL、TLS 1.0/1.1)
- 实现自定义密码算法
- 在版本控制中存储机密(使用机密管理工具)
- 使用弱或可预测的初始化向量(IV)
安全错误处理
必须:
- 实施集中式错误处理
- 记录所有与安全相关的错误,并提供足够的调查详情
- 向用户返回通用错误消息
- 安全地失败(出错时拒绝访问,不要回退到不安全状态)
- 在 finally 块中或使用等效模式清理资源
- 监控异常错误模式并发出警报
不得:
- 向用户暴露堆栈跟踪
- 在错误消息中包含敏感数据(密码、密钥、令牌、个人身份信息)
- 记录敏感数据(密码、信用卡号、社会安全号码)
- 在发生严重安全错误后继续处理
- 未记录日志就抑制安全异常
安全配置
必须:
- 使用环境变量或机密管理来处理敏感配置
- 设置安全的默认值(禁用调试模式、启用安全标头)
- 记录所有与安全相关的配置选项
- 评估配置更改对安全性的影响
- 对服务账户和 API 密钥遵循最小权限原则
- 禁用不必要的功能、服务和端点
禁止:
- 将包含机密的配置文件提交到版本控制系统
- 在生产环境中使用默认凭据
- 在生产环境中启用调试或详细日志记录
- 将管理界面暴露给公共网络
- 使用过于宽松的 CORS 策略
安全测试
必须:
- 在每次提交时执行静态应用程序安全测试(SAST)
- 在部署到生产环境之前执行动态应用程序安全测试(DAST)
- 在测试套件中加入安全测试用例
- 执行依赖项漏洞扫描
- 测试身份验证和授权控制
- 测试输入验证是否能防范注入漏洞
- 记录安全测试结果
禁止:
- 部署未通过安全扫描的代码
- 在没有充分理由和批准的情况下忽略或抑制安全发现
- 在生产环境中测试安全控制
- 在测试环境中使用生产数据
依赖项管理
必须:
- 使用依赖项扫描工具(例如 Dependabot、Snyk)
- 及时更新依赖项以应用安全补丁
- 在使用前检查依赖项是否存在已知漏洞
- 使用包锁定文件确保构建可复现
- 记录获准使用的依赖项及其版本
- 移除未使用的依赖项
禁止:
- 使用存在已知严重漏洞的依赖项
- 使用已弃用或不再维护的依赖项
- 从不可信来源下载依赖项
- 未经安全审查绕过依赖项版本约束
代码审查
必须:
- 所有代码更改都必须经过同行审查
- 在代码审查流程中纳入安全审查
- 在 PR 流水线中使用自动化安全扫描
- 在 PR 评论中记录安全决策
- 在批准前确认安全要求均已满足
禁止:
- 未获得所需批准就合并代码
- 绕过 CI/CD 流水线中的安全检查
- 批准自己所做的安全关键更改
示例
示例 1:安全输入验证(JavaScript)
// GOOD: Allowlist validation with type checking
function validateUsername(username) {
// Define what IS allowed
const usernameRegex = /^[a-zA-Z0-9_-]{3,20}$/;
// Validate type
if (typeof username !== 'string') {
throw new Error('Invalid input type');
}
// Validate format and length
if (!usernameRegex.test(username)) {
throw new Error('Username must be 3-20 characters and contain only letters, numbers, hyphens, and underscores');
}
return username;
}
// BAD: No validation
function validateUsernameBad(username) {
return username; // Accepts anything!
}
// BAD: Blocklist validation
function validateUsernameBad2(username) {
if (username.includes('<') || username.includes('>')) {
throw new Error('Invalid characters');
}
return username; // Still vulnerable to many attacks
}
示例 2:安全密码哈希(Node.js)
const bcrypt = require('bcrypt');
// GOOD: Use strong hashing with salt
async function hashPassword(password) {
// MUST use at least 12 rounds (2^12 iterations)
const saltRounds = 12;
const hashedPassword = await bcrypt.hash(password, saltRounds);
return hashedPassword;
}
async function verifyPassword(password, hashedPassword) {
return await bcrypt.compare(password, hashedPassword);
}
// BAD: Using weak hashing
const crypto = require('crypto');
function hashPasswordBad(password) {
// NEVER use MD5 or SHA-1 for passwords!
return crypto.createHash('md5').update(password).digest('hex');
}
// BAD: Storing plaintext
function storePasswordBad(password) {
return password; // NEVER store passwords in plaintext!
}
示例 3:安全会话管理(Express.js)
const session = require('express-session');
const RedisStore = require('connect-redis')(session);
// GOOD: Secure session configuration
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: process.env.SESSION_SECRET, // From environment, not hardcoded
name: 'sessionId', // Don't use default 'connect.sid'
resave: false,
saveUninitialized: false,
cookie: {
secure: true, // MUST use HTTPS
httpOnly: true, // MUST prevent JavaScript access
maxAge: 1800000, // 30 minutes
sameSite: 'strict' // CSRF protection
}
}));
// BAD: Insecure session configuration
app.use(session({
secret: 'mysecret123', // Hardcoded secret!
cookie: {
secure: false, // Allows HTTP
httpOnly: false // Vulnerable to XSS
}
}));
示例 4:防止 SQL 注入(Node.js)
const mysql = require('mysql2/promise');
// GOOD: Parameterized queries
async function getUserByEmail(email) {
const [rows] = await connection.execute(
'SELECT * FROM users WHERE email = ?',
[email]
);
return rows[0];
}
// BAD: String concatenation
async function getUserByEmailBad(email) {
// NEVER concatenate user input into SQL!
const query = `SELECT * FROM users WHERE email = '${email}'`;
const [rows] = await connection.execute(query);
return rows[0];
}
示例 5:安全错误处理(Python)
import logging
# GOOD: Generic error messages to users, detailed logging
def process_payment(user_id, amount):
try:
# Process payment logic
charge_credit_card(user_id, amount)
return {"success": True, "message": "Payment processed"}
except CreditCardError as e:
# Log detailed error securely
logging.error(f"Payment failed for user {user_id}: {str(e)}",
extra={"user_id": user_id, "amount": amount})
# Return generic message to user
return {"success": False, "message": "Payment processing failed. Please try again."}
except Exception as e:
# Log unexpected errors
logging.exception(f"Unexpected error processing payment for user {user_id}")
# Return generic message
return {"success": False, "message": "An error occurred. Please contact support."}
# BAD: Exposing detailed errors
def process_payment_bad(user_id, amount):
try:
charge_credit_card(user_id, amount)
return {"success": True}
except Exception as e:
# NEVER expose stack traces or system details to users!
return {"success": False, "error": str(e), "trace": traceback.format_exc()}
示例 6:安全配置(环境变量)
// GOOD: Use environment variables for secrets
require('dotenv').config();
const config = {
database: {
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD, // Never hardcode!
database: process.env.DB_NAME
},
api: {
key: process.env.API_KEY,
secret: process.env.API_SECRET
},
// Secure defaults
security: {
httpsOnly: true,
hstsEnabled: true,
debugMode: false
}
};
// Validate required environment variables
const required = ['DB_HOST', 'DB_USER', 'DB_PASSWORD', 'API_KEY'];
required.forEach(key => {
if (!process.env[key]) {
throw new Error(`Missing required environment variable: ${key}`);
}
});
// BAD: Hardcoded secrets
const configBad = {
database: {
host: 'localhost',
user: 'admin',
password: 'P@ssw0rd123', // NEVER hardcode passwords!
database: 'production'
},
api: {
key: 'sk_live_abcdef123456' // NEVER commit API keys!
}
};
示例 7:防止 XSS(HTML 输出编码)
// GOOD: Encode output before rendering
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
function displayUserComment(comment) {
const safeComment = escapeHtml(comment);
document.getElementById('comment').innerHTML = safeComment;
}
// Or use a trusted library
const DOMPurify = require('dompurify');
function displayUserContent(content) {
const clean = DOMPurify.sanitize(content);
document.getElementById('content').innerHTML = clean;
}
// BAD: Direct HTML insertion
function displayUserCommentBad(comment) {
// NEVER insert unsanitized user input into HTML!
document.getElementById('comment').innerHTML = comment;
}
相关 ISMS 策略
此技能落实了以下策略中的要求:
相关文档
- SECURITY_ARCHITECTURE.md - 安全控制和架构
- THREAT_MODEL.md - 威胁分析和缓解措施
- SECURITY.md - 安全漏洞报告
合规性映射
ISO 27001:2022
- A.8.24 密码学的使用
- A.8.25 安全开发生命周期
- A.8.26 应用程序安全要求
- A.8.28 安全编码
NIST Cybersecurity Framework
- PR.DS-2:保护传输中的数据
- PR.DS-6:完整性检查机制用于验证软件完整性
- PR.IP-2:实施系统开发生命周期以管理系统
CIS Controls
- Control 16:应用软件安全
- 16.1 建立并维护安全的应用程序开发流程
- 16.2 建立并维护接受和处理软件漏洞的流程
- 16.10 在应用程序架构中应用安全设计原则
执行
违反安全开发规则的情况:
- 严重违规(硬编码机密、使用禁用算法):阻止部署,并要求立即修复
- 高严重性违规(缺少输入验证、身份验证薄弱):要求在合并前修复
- 中严重性违规:要求在当前迭代内修复
- 低严重性违规:创建技术债务工单
必须跟踪所有违规情况,并在安全指标中报告。
评论
支持 Markdown