mcpField
S
secure-development

secure-development

github.com/hack23安全1335 次安装今天更新
代码仓库

关于 secure-development

面向软件开发者的安全开发技能,依据 Hack23 ISMS 安全开发政策覆盖从输入校验到依赖管理和代码审查的实践,并列出测试与合规要求。

主要功能

  1. 01规范输入校验与输出编码
  2. 02涵盖身份验证和访问控制
  3. 03要求安全加密与配置管理
  4. 04规定错误处理与安全测试
  5. 05覆盖依赖管理和代码审查

适用场景

  1. 01制定 Web 应用和 API 的安全开发规范
  2. 02审查认证、授权及输入处理实现
  3. 03规划提交与发布前的安全测试
  4. 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, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#039;");
}

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 策略

此技能落实了以下策略中的要求:

相关文档

合规性映射

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