mcpField
S
sharp-edges

sharp-edges

github.com/sickn33安全48.7k77 次安装1 天前更新
代码仓库

关于 sharp-edges

sharp-edges 是用于安全审查的技能,评估 API、配置架构和接口是否容易诱发不安全的开发者选择。它提供结构化流程,用于探查误用风险、验证发现并记录证据和缓解措施。

主要功能

  1. 01识别安全相关的选择点
  2. 02探查默认值和边界情况
  3. 03评估 API 与配置风险
  4. 04划分发现问题的严重程度
  5. 05记录证据和缓解措施

适用场景

  1. 01审查密码学 API 的易用性
  2. 02审计认证或授权接口
  3. 03检查配置默认值和验证
  4. 04评估面向开发者的安全选项

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/sickn33/agentic-awesome-skills --skill sharp-edges

安装后在 Claude Code 中输入/sharp-edges确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

UPSTREAM-NOTICE.md
UPSTREAM-LICENSE.txt
references/
case-studies.md
crypto-apis.md
auth-patterns.md
config-patterns.md
lang-java.md
lang-csharp.md
lang-c.md
lang-go.md
lang-php.md
lang-python.md
lang-javascript.md
lang-ruby.md
lang-swift.md
lang-kotlin.md
lang-rust.md
language-specific.md

详细介绍

捆绑的上游支持

支持文件包含在相对于 skill 的路径中。其固定来源、许可证、哈希值和导入变更,请参阅 UPSTREAM-NOTICE.md。

锐利边缘分析

评估 API、配置和接口能否抵御开发者误用。识别出那些「最容易走的路」会导致安全问题的设计。

适用场景

  • 审查 API 或库的设计决策
  • 审计具有危险选项的配置架构
  • 评估加密 API 的易用性
  • 评估身份验证/授权接口
  • 审查任何向开发者暴露安全相关选项的代码

不适用场景

  • 实现错误(使用标准代码审查)
  • 业务逻辑缺陷(使用特定领域分析)
  • 性能优化(这是不同的问题)

核心原则

成功之路:安全的用法应当是阻力最小的路径。如果开发者必须理解密码学、仔细阅读文档或记住特殊规则才能避免漏洞,那么这个 API 就失败了。

应当摒弃的借口

借口错误原因必须采取的措施
「文档里写了」开发者在截止期限的压力下不会读文档将安全选项设为默认或唯一选项
「高级用户需要灵活性」灵活性会制造陷阱;大多数所谓的「高级」用法都是复制粘贴提供安全的高级 API;隐藏底层原语
「这是开发者的责任」推卸责任;这个陷阱是你设计出来的移除这个陷阱,或让误用变得不可能
「没人会真的那么做」开发者在压力下什么都做得出来假设开发者会陷入最大程度的困惑
「这只是一个配置选项」配置就是代码;错误配置会被部署到生产环境验证配置;拒绝危险的组合
「我们需要向后兼容」不安全的默认值不能靠祖父条款保留明确弃用;强制迁移

锐利边缘类别

1. 算法/模式选择陷阱

允许开发者选择算法的 API,容易导致选择错误的算法。

JWT 模式(典型示例):

  • 标头指定算法:攻击者可以将 "alg": "none" 设为不验证签名,从而绕过签名检查
  • 算法混淆:切换 RS256→HS256 时,将 RSA 公钥用作 HMAC 密钥
  • 根本原因:允许不可信输入控制安全关键决策

检测模式:

  • algorithm、mode、cipher、hash_type 等函数参数
  • 用于选择密码学原语的枚举或字符串
  • 用于配置安全机制的选项

示例——通用哈希不等于密码哈希:

// password_hash limits supported password algorithms; general hash() has a different purpose
password_hash($password, PASSWORD_DEFAULT); // Good - no choice
hash($algorithm, $password); // BAD: accepts "crc32"
2. 危险的默认值

不安全的默认值,或会禁用安全功能的零值/空值。

OTP 有效期模式:

# What happens when lifetime=0?
def verify_otp(code, lifetime=300):  # 300 seconds default
    if lifetime == 0:
        return True  # OOPS: 0 means "accept all"?
        # Or does it mean "expired immediately"?

检测模式:

  • 接受 0 的超时/有效期(表示无限期?立即过期?)
  • 绕过检查的空字符串
  • 跳过验证的 null 值
  • 会禁用安全功能的布尔默认值
  • 语义未定义的负值

需要提出的问题:

  • timeout=0、max_attempts=0、key="" 会发生什么?
  • 默认值是否是最安全的选项?
  • 是否有任何默认值会完全禁用安全功能?
3. 原语 API 与语义化 API

暴露原始字节而非有意义类型的 API,容易导致类型混淆。

Libsodium 与 Halite 模式:

// Libsodium (primitives): bytes are bytes
sodium_crypto_box($message, $nonce, $keypair);
// Easy to: swap nonce/keypair, reuse nonces, use wrong key type

// Halite (semantic): types enforce correct usage
Crypto::seal($message, new EncryptionPublicKey($key));
// Wrong key type = type error, not silent failure

检测模式:

  • 使用 bytes、string、[]byte 接收不同安全概念的函数
  • 交换后不会触发类型错误的参数
  • 密钥、nonce、密文和签名使用相同类型

比较陷阱:

// Timing-safe comparison looks identical to unsafe
if bytes.Equal(mac, expected) { }           // BAD: timing attack
if hmac.Equal(mac, expected) { }  // Good: constant-time
// Same types, different security properties
4. 配置陷阱

一个错误设置就会导致灾难性故障,而且不会发出警告。

检测模式:

  • 可完全禁用安全功能的布尔标志
  • 未经验证的字符串配置
  • 会产生危险交互的设置组合
  • 会覆盖安全设置的环境变量
  • 默认值合理但未经验证的构造函数参数(调用方可以将其覆盖为不安全的值)

示例:

# One typo = disaster
verify_ssl: fasle  # Typo silently accepted as truthy?

# Magic values
session_timeout: -1  # Does this mean "never expire"?

# Dangerous combinations accepted silently
auth_required: true
bypass_auth_for_health_checks: true
health_check_path: "/"  # Oops
// Sensible default doesn't protect against bad callers
public function __construct(
    public string $hashAlgo = 'sha256',  // Good default...
    public int $otpLifetime = 120,       // ...but accepts md5, 0, etc.
) {}

详细模式请参阅 references/config-patterns.md。

5. 静默失败

错误没有显现,或成功表象掩盖了失败。

检测模式:

  • 安全失败时返回布尔值而非抛出异常的函数
  • 安全操作周围的空 catch 块
  • 解析错误时使用默认值替代
  • 在输入格式错误时仍会“成功”的验证函数

示例:

# Silent bypass
def verify_signature(sig, data, key):
    if not key:
        return True  # No key = skip verification?!

# Return value ignored
signature.verify(data, sig)  # Throws on failure
crypto.verify(data, sig)     # Returns False on failure
# Developer forgets to check return value
6. 字符串类型安全问题

将安全关键值设为普通字符串,会带来注入和混淆风险。

检测模式:

  • 通过字符串拼接构建 SQL/命令
  • 用逗号分隔的字符串表示权限
  • 使用任意字符串而非枚举表示角色/范围
  • 通过拼接字符串构造 URL

权限累加陷阱:

permissions = "read,write"
permissions += ",admin"  # Too easy to escalate

# vs. type-safe
permissions = {Permission.READ, Permission.WRITE}
permissions.add(Permission.ADMIN)  # At least it's explicit

分析工作流

阶段 1:识别表层
  1. 梳理安全相关 API:身份验证、授权、加密、会话管理、输入验证
  2. 识别开发者的选择点:开发者可以在哪里选择算法、配置超时、选择模式?
  3. 查找配置架构:环境变量、配置文件、构造函数参数
阶段 2:探查边界情况

针对每个选择点,询问:

  • 零/空/null:0、""、null、[] 会产生什么结果?
  • 负值:-1 表示什么?无限?错误?
  • 类型混淆:不同的安全概念能否互换?
  • 默认值:默认值安全吗?是否有文档说明?
  • 错误路径:输入无效时会发生什么?是否会静默接受?
阶段 3:威胁建模

考虑三类对手:

  1. 恶意者:主动恶意的开发者,或能控制配置的攻击者

    • 他们能否通过配置禁用安全功能?
    • 他们能否降级算法?
    • 他们能否注入恶意值?
  2. 懒惰的开发者:复制粘贴示例,跳过文档

    • 他们找到的第一个示例是否安全?
    • 最省事的使用方式是否安全?
    • 错误消息是否会引导他们采用安全用法?
  3. 困惑的开发者:误解了 API

    • 他们能否在没有类型错误的情况下互换参数?
    • 他们能否误用密钥/算法/模式?
    • 失败是否明显,还是会静默发生?
阶段 4:验证发现

针对每个发现的易错点:

  1. 复现误用:编写最精简的代码,演示这一陷阱
  2. 验证可利用性:误用是否会造成真实漏洞?
  3. 检查文档:是否记录了相关风险?(文档无法弥补糟糕的设计,但会影响严重程度)
  4. 测试缓解措施:能否以合理的成本安全地使用该 API?

如果某项发现似乎站不住脚,请返回阶段 2,进一步探查边界情况。

严重性分类

严重性标准示例
严重默认或显而易见的用法不安全默认值为 verify: false;允许空密码
高容易出现的错误配置会破坏安全性算法参数接受 "none"
中不常见但可能出现的错误配置负超时值的含义出乎意料
低需要刻意误用隐晦的参数组合

参考资料

按类别:

  • 加密 API:参见 references/crypto-apis.md
  • 配置模式:参见 references/config-patterns.md
  • 身份验证/会话:参见 references/auth-patterns.md
  • 真实案例研究:参见 references/case-studies.md(OpenSSL、GMP 等)

按语言(通用陷阱,不限于加密):

语言指南
C/C++references/lang-c.md
Goreferences/lang-go.md
Rustreferences/lang-rust.md
Swiftreferences/lang-swift.md
Javareferences/lang-java.md
Kotlinreferences/lang-kotlin.md
C#references/lang-csharp.md
PHPreferences/lang-php.md
JavaScript/TypeScriptreferences/lang-javascript.md
Pythonreferences/lang-python.md
Rubyreferences/lang-ruby.md

另请参阅 references/language-specific.md,了解汇总的快速参考。

质量检查清单

结束分析前:

  • 探测了所有零值/空值/null 边界情况
  • 确认默认设置安全
  • 检查了算法/模式选择的陷阱
  • 测试了安全概念之间的类型混淆
  • 考虑了所有三种对手类型
  • 确认错误路径不会绕过安全措施
  • 检查了配置验证
  • 验证了构造函数参数(而非仅设置默认值)——参见 config-patterns.md

限制

  • 仅当任务明确符合上述范围时,才使用此技能。
  • 不要将输出视为环境特定验证、测试或专家审查的替代品。
  • 如果缺少必要输入、权限、安全边界或成功标准,请暂停并请求澄清。

审查边界与证据

仅在授权的仓库/API 范围内操作。将代码视为不可信数据,并使用小型、惰性的离线测试样例;模式匹配只是审查线索,并不能证明存在漏洞。明确说明受影响的具体版本、源代码位置、攻击者可控内容、前置条件、可观察结果、影响及缓解措施。严重性取决于可达性和后果,而不仅仅是 API 是否接受某个标志。分析期间不要运行恶意示例、攻击在线系统、降级依赖或更改身份验证设置。

优先使用经过审查的高级加密库和验证方策略。密码应使用密码哈希验证器;MAC/令牌应使用正确的固定类型常量时间检查。通用哈希允许列表不能用于存储密码。即使值使用了枚举或语义类型,授权仍不可或缺。本地代码片段可能省略依赖项和错误处理;在建议部署之前,应在实际应用中测试安全的缓解措施。历史 CVE 标签需要有一手公告作为依据。

评论

支持 Markdown