LiteLLM 的 .semgrep/rules 自定义 Semgrep 规则:从无界队列到供应链安全的静态检查守门

LiteLLM 的 .semgrep/rules 自定义 Semgrep 规则:从无界队列到供应链安全的静态检查守门 LiteLLM 的 .semgrep/rules 自定义 Semgrep 规则从无界队列到供应链安全的静态检查守门【免费下载链接】litellmThe fastest, litest AI Gateway. Rust core with Python SDK. Call 100 LLM APIs in OpenAI (or native) format with cost tracking, guardrails, load balancing, and logging [Bedrock, Azure, OpenAI, Anthropic, OpenAI, VertexAI, vLLM, Nvidia NIM]项目地址: https://gitcode.com/GitHub_Trending/li/litellmLiteLLM 在仓库根目录的.semgrep/rules下维护了一组自定义 Semgrep 规则用于在 CI 中以--error模式强制拦截两类典型问题Python 侧无maxsize的asyncio.Queue潜在内存无界增长和误提交开发机特有的.claude/目录。读完本文你将掌握 LiteLLM 自定义 Semgrep 规则的目录布局、两条规则的完整 YAML 定义与匹配原理、CI 工作流中的执行方式以及规则在 LiteLLM 源码中对应的真实落点受约束的队列常量与各日志/花费队列实现并能按同一模式为自己的仓库编写自定义规则。目录布局与运行方式README 明确了三个要点加载方式将规则 YAML 文件放入.semgrep/rules/Semgrep 会加载该目录下的所有.yml/.yaml文件两条运行命令仅运行自定义规则CI / 发现问题即失败semgrep scan --config .semgrep/rules . --error注册表规则 自定义规则一起运行semgrep scan --config auto --config .semgrep/rules .--error的含义是只要扫描出任何 finding命令就以非零退出码结束从而让 CI 流水线直接失败——这是守门语义的关键。目录约定python/— Python 语言专属规则安全、模式类可按需增加子目录例如generic/存放语言无关规则。当前仓库实际落地的规则文件共三个与 README 描述的布局一一对应规则文件规则 id语言类别.semgrep/rules/python/unbounded-memory.ymlunbounded-asyncio-queuepythoncorrectness.semgrep/rules/python/reliability/unbounded-memory.ymlunbounded-asyncio-queuepythonreliability.semgrep/rules/security/no-claude-directory.ymlno-claude-directory-committedgenericsecurity规则一拦截无 maxsize 的 asyncio.Queue.semgrep/rules/python/unbounded-memory.yml的完整内容如下含文件头注释# Unbounded memory growth – data structures without a clear max limit # Can lead to OOM under load. rules: - id: unbounded-asyncio-queue message: asyncio.Queue() with no maxsize can grow unbounded. Use asyncio.Queue(maxsizeN) for integrations (e.g. log queues). severity: ERROR languages: [python] pattern-either: - pattern: asyncio.Queue() - pattern: asyncio.Queue(maxsize0) metadata: category: correctness cwe: CWE-400: Uncontrolled Resource Consumption逐字段解读pattern-either匹配无参数构造或显式maxsize0两种写法。在 asyncio 中maxsize为0或缺省都表示无界队列——生产端可以无限入队消费端一旦落后如数据库或下游日志服务变慢内存就会持续膨胀直至 OOM。因此这两个 pattern 覆盖的是同一类风险的两个入口。severity: ERROR错误级配合 CI 中的--error直接阻断 PR。metadata.cwe映射到 CWE-400Uncontrolled Resource Consumption便于安全团队按标准漏洞分类汇总。.semgrep/rules/python/reliability/unbounded-memory.yml与上一文件规则 id、匹配模式完全相同差异仅在 metadatacategory: reliability、tags: [python, reliability]、confidence: HIGH并附source指向 Python 官方asyncio.queue文档。从两个文件并存且 id 相同这一点可以推断它们是同一条规则在不同分类口径correctness vs reliability下的两个迭代版本由于 README 声明 Semgrep 会加载该目录下全部 YAML两个文件都会被加载规则 id 相同时 Semgrep 会按 id 去重处理。若在自己的仓库复刻此规则保留一份即可不必同时维护两份。为什么 LiteLLM 要专门写这条规则这条规则不是纸面预防——LiteLLM Proxy 内部大量使用asyncio.Queue作为日志队列与数据库花费更新队列无界队列在高并发下确实会导致内存失控。规则所约束的正确写法正是源码中的通用常量litellm/constants.py 中定义了# Bounds asyncio.Queue() instances (log queues, spend update queues, etc.) to prevent unbounded memory growth LITELLM_ASYNCIO_QUEUE_MAXSIZE: Final int(os.getenv(LITELLM_ASYNCIO_QUEUE_MAXSIZE, 1000))即所有队列默认上限 1000 条并可通过环境变量LITELLM_ASYNCIO_QUEUE_MAXSIZE覆盖。仓库中所有队列实现都遵循这一约定例如日志工作线程队列litellm/litellm_core_utils/logging_worker.py 中asyncio.Queue(maxsizeself.max_queue_size)花费更新队列litellm/proxy/db/db_transaction_queue/spend_update_queue.py 与 base_update_queue.py 均使用asyncio.Queue(maxsizeLITELLM_ASYNCIO_QUEUE_MAXSIZE)GCS 日志桶litellm/integrations/gcs_bucket/gcs_bucket.py 同样以该常量限定maxsize代理主服务中的请求体队列litellm/proxy/proxy_server.py 显式给出asyncio.Queue(maxsize1024)。此外constants.py 还定义了MAX_SIZE_IN_MEMORY_QUEUE默认取队列上限的 80%int(LITELLM_ASYNCIO_QUEUE_MAXSIZE * 0.8)注释明确说明它必须小于队列 maxsize否则内存聚合逻辑永远不会触发——这说明有界队列 背压阈值在 LiteLLM 中是一套相互配合的设计而 Semgrep 规则正是保证后人写新队列时不会绕开这套设计的自动化手段。规则二禁止提交 .claude/ 目录供应链/密钥类.semgrep/rules/security/no-claude-directory.yml完整内容rules: - id: no-claude-directory-committed message: .claude/ directory must not be committed to the repository. It contains local Claude Code settings (permissions, worktree paths) that are developer-machine-specific and may expose internal paths or credentials. Add .claude/ to .gitignore instead. severity: ERROR languages: [generic] paths: include: - /.claude/** - /.claude/* pattern-regex: [\s\S] metadata: category: security tags: [supply-chain, secrets] confidence: HIGH这条规则展示了 Semgrep 语言无关generic写法的典型组合languages: [generic]pattern-regex: [\s\S]正则[\s\S]能匹配任意内容包括跨行含义是只要该路径下存在任何文件内容就告警从而把检查范围完全交给路径paths.include仅扫描/.claude/下的文件其他路径一律不进入匹配风险描述.claude/存放的是开发机本地的 Claude Code 配置权限设置、worktree 路径等具有机器特异性提交后可能泄露内部路径乃至凭据因此规则将其归入supply-chain, secrets标签。message使用 YAML 的折叠块书写多行文本输出时会被压成一段便于在 CI 日志中阅读。CI 集成test-semgrep.yml 如何执行规则规则只有在流水线上强制执行才有意义。LiteLLM 在.github/workflows/test-semgrep.yml中配置了独立工作流name: Semgrep on: pull_request: branches: - main - litellm_internal_staging - litellm_oss_staging - litellm_** permissions: contents: read concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true jobs: semgrep: runs-on: ubuntu-latest timeout-minutes: 10 steps: # ... checkout、setup-python (3.12)、setup uv (0.10.9) 略 - name: Run Semgrep (custom rules) run: uv tool run --from semgrep1.157.0 semgrep scan --config .semgrep/rules . --error几个值得注意的工程细节锁定工具版本通过uv tool run --from semgrep1.157.0固定 Semgrep 版本避免上游 Semgrep 升级改变规则语义导致 CI 行为漂移只跑自定义规则目录--config .semgrep/rules而非--config auto即 PR 门禁只对本仓库的自定义规则负责执行快、边界清晰README 中--config auto的组合方式留给需要叠加社区注册表规则的场合触发范围面向main、两条 staging 分支以及litellm_*命名空间的所有 PRconcurrency组保证同一 PR 的重复推送会取消旧任务节省 CI 资源超时 10 分钟对纯静态扫描的自定义规则集而言是充裕且可预期的上限。如何按此模式扩展规则结合以上三个实例可以为自己的仓库沉淀出 LiteLLM 式的自定义规则编写范式语言相关的模式规则如队列那条用languages: [python]pattern/pattern-either精确描述坏写法的正则式 AST 模式把maxsize0这类看似显式实为无界的变体一并纳入pattern-either语言无关的路径规则如.claude/那条用languages: [generic]pattern-regex: [\s\S]paths.include把不该存在于仓库的目录整体封死元数据规范化统一给出severity: ERROR、metadata.categorycorrectness / reliability / security、tags、confidence安全类规则附cwe映射CI 落地独立 workflow、固定工具版本、--config 规则目录 . --error三要素缺一不可配套源码约束规则不是孤立的——如队列规则背后有LITELLM_ASYNCIO_QUEUE_MAXSIZE这样的全局常量和全仓库统一实现兜底规则负责防新增违规常量负责定义正确写法。规则的完整语法细节可参考 README 指向的 Semgrep 官方规则语法文档见.semgrep/rules/README.md末尾链接。小结LiteLLM 的.semgrep/rules用三个规则文件演示了一套低成本、高收益的静态检查守门方案一条 Python 模式规则拦截无界asyncio.Queue对齐 CWE-400并有 constants.py 常量与各队列实现作为正确写法的源码背书一条 generic 正则规则封禁开发机特有的.claude/目录入库再由 test-semgrep.yml 以固定版本、--error模式在 PR 上强制执行。对任何以 Python asyncio 为主、且多人协作的大规模仓库这一规则目录 路径约束 CI 强制失败的组合都可直接借鉴。【免费下载链接】litellmThe fastest, litest AI Gateway. Rust core with Python SDK. Call 100 LLM APIs in OpenAI (or native) format with cost tracking, guardrails, load balancing, and logging [Bedrock, Azure, OpenAI, Anthropic, OpenAI, VertexAI, vLLM, Nvidia NIM]项目地址: https://gitcode.com/GitHub_Trending/li/litellm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考