DataDog/guarddog

GitHub: DataDog/guarddog

GuardDog 是一款 CLI 供应链安全工具,通过基于风险的关联分析模型识别 PyPI、npm、Go 等多生态中的恶意软件包。

Stars: 1169 | Forks: 111

# GuardDog [![Test](https://static.pigsec.cn/wp-content/uploads/repos/cas/bf/bf0d093f807aade2261be7ab200aba8418de0fc2e0f0520bd52d207c55e691ba.svg)](https://github.com/DataDog/guarddog/actions/workflows/checks.yml) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/DataDog/guarddog/badge)](https://securityscorecards.dev/viewer/?uri=github.com/DataDog/guarddog) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/12273/badge)](https://www.bestpractices.dev/projects/12273)

GuardDog

GuardDog 是一个 CLI 工具,用于识别恶意的 PyPI 和 npm 包、Go 模块、GitHub Actions 或 VSCode 扩展。它通过 YARA 规则对包源代码进行静态分析,并分析包的元数据以检测供应链攻击。 **GuardDog 的与众不同之处:** GuardDog 不仅仅是列出可疑模式,它还会将发现的结果关联起来,根据攻击链识别真正的**风险**。一个包必须同时具备执行某项操作的**能力**(例如网络访问)并且在同一文件中存在**威胁指标**(例如可疑域名),才会被标记为高风险。 它从以下位置下载并扫描代码: * NPM:托管在 [npmjs.org](https://www.npmjs.com/) 上的包 * PyPI:托管在 [PyPI.org](https://pypi.org/) 上的源文件 (tar.gz) 包 * Go:托管在 [GitHub.com](https://github.com) 上的仓库的 GoLang 源文件 * RubyGems:托管在 [rubygems.org](https://rubygems.org/) 上的 Gem 包 * GitHub Actions:托管在 [GitHub.com](https://github.com) 上的仓库的 JavaScript 源文件 * VSCode Extensions:托管在 [marketplace.visualstudio.com](https://marketplace.visualstudio.com/) 上的扩展 (.vsix) 包 ![GuardDog 演示用法](https://static.pigsec.cn/wp-content/uploads/repos/cas/f7/f74d39fb7280a4ae9918b785d6fb66171aed93b9469b7c7fb6bfba00cd353c2d.png) ## GuardDog 的工作原理 GuardDog 使用**基于风险的检测模型**,将代码能力与威胁指标进行关联: 1. **检测**:规则用于识别**能力**(代码*能*做什么)或**威胁**(可疑指标) 2. **关联**:在同一文件中发现的能力和威胁构成**风险**(跨文件匹配也会构成风险,但严重性会降低) 3. **评分**:根据攻击链的完整性和复杂程度对风险进行评分 (0-10) 4. **报告**:包将获得严重性评级(低/中/高),并附带详细的风险分解说明 ### 为什么采用这种方法? 传统的 SAST 工具会独立标记每一个可疑模式,从而导致告警疲劳。GuardDog 认为: - **仅有能力**并不代表恶意(网络库本来就应该发起 HTTP 请求) - **仅有威胁指标**可能是误报(测试用例、文档) - **能力 + 威胁**结合在一起才表明存在实际风险(即代码*能够*且*将会*进行恶意操作) ### 风险评分 包将根据四个因素获得 **0-10** 的评分: | 因素 | 权重 | 描述 | |--------|--------|-------------| | **严重性** | 30% | 最高严重性发现(低/中/高) | | **攻击链** | 20% | 完整攻击阶段的存在情况(早期 → 中/后期) | | **特异性** | 30% | 模式对恶意软件的针对程度相对于正常代码 | | **复杂度** | 20% | 技术的先进水平 | **评分标签:** - **0**:未检测到风险 - **0.1-3**:低风险(单阶段威胁,特异性低) - **3.1-7.5**:中风险(部分攻击链、元数据指标或单阶段代码发现) - **7.6-10**:高风险(具有源代码证据的多阶段攻击链 —— 几乎可以确定已被入侵) **攻击链阶段**(基于 MITRE ATT&CK): - **早期**:初始访问、执行能力 - **中期**:持久化、防御规避、凭证获取 - **后期**:命令与控制、数据窃取、影响 ### 查看用于 GuardDog 的新 Datadog Agent [集成](https://docs.datadoghq.com/integrations/guarddog/)和 Cloud SIEM [内容包](https://app.datadoghq.com/security/siem/content-packs?query=guarddog)。 ## 开始使用 ### 安装 运行 GuardDog 最简单的方法是使用 [`uvx`](https://docs.astral.sh/uv/guides/tools/): ``` uvx guarddog pypi scan requests ``` 要在本地安装: ``` uv tool install guarddog # 或 pip install guarddog ``` 或者使用 Docker 镜像: ``` docker pull ghcr.io/datadog/guarddog alias guarddog='docker run --rm ghcr.io/datadog/guarddog' ``` *注意:在 Windows 上,唯一支持的安装方法是 Docker。* ### 示例用法 ``` # 扫描 'requests' 包的最新版本 guarddog pypi scan requests # 扫描 'requests' 包的特定版本 guarddog pypi scan requests --version 2.28.1 # 使用 2 个特定启发式方法扫描 'request' 包 guarddog pypi scan requests --rules exec-base64 --rules code-execution # 使用除一个之外的所有规则扫描 'requests' 包 guarddog pypi scan requests --exclude-rules exec-base64 # 扫描本地包归档 guarddog pypi scan /tmp/triage.tar.gz # 扫描本地包目录 guarddog pypi scan /tmp/triage/ # 扫描存储在 S3 中的包(一个文件夹/前缀或单个归档对象) guarddog pypi scan s3://my-bucket/path/to/package/ guarddog pypi scan s3://my-bucket/path/to/package.tar.gz # 扫描本地文件夹的 requirements.txt 文件中引用的每个包 guarddog pypi verify workspace/guarddog/requirements.txt # 扫描 requirements.txt 文件中引用的每个包并输出一个 sarif 文件 - 仅适用于 verify guarddog pypi verify --output-format=sarif workspace/guarddog/requirements.txt # 将 JSON 输出到标准输出 - 适用于每个命令 guarddog pypi scan requests --output-format=json # 所有命令也适用于 npm, go, rubygems guarddog npm scan express guarddog go scan github.com/DataDog/dd-trace-go guarddog go verify /tmp/repo/go.mod # 扫描 RubyGems 包 guarddog rubygems scan rails guarddog rubygems verify /tmp/repo/Gemfile.lock # 此外还可以支持扫描以 JavaScript 实现的 GitHub actions guarddog github_action scan DataDog/synthetics-ci-github-action guarddog github_action verify /tmp/repo/.github/workflows/main.yml # 从 marketplace 扫描 VSCode 扩展 guarddog extension scan ms-python.python # 扫描 VSCode 扩展的特定版本 guarddog extension scan ms-python.python --version 2023.20.0 # 扫描本地 VSCode 扩展目录或 VSIX 归档 guarddog extension scan /tmp/my-extension/ # 在 debug 模式下运行 guarddog --log-level debug npm scan express ``` ## 沙箱扫描 在扫描包时,GuardDog 会在**内核级沙箱**内运行源代码分析(Linux 通过 Landlock,macOS 通过 Seatbelt,使用 [nono](https://github.com/always-further/nono-py))。该沙箱会阻止所有网络访问,并将文件系统操作限制在分析所需的路径内。这可以防范那些试图在归档文件解压或扫描期间执行代码的恶意包。 默认情况下,沙箱是必需的:如果平台上不可用沙箱,扫描将会失败,而不是在没有保护的情况下运行。要禁用沙箱进行扫描,你必须显式传递 `--no-sandbox` 参数: ``` # 默认:需要 sandbox,如果不可用则退出并报错 guarddog pypi scan requests # 显式禁用 sandbox guarddog pypi scan requests --no-sandbox ``` 对于远程包,三个阶段在不同的权限级别下运行: 1. **下载**和**元数据分析**在没有沙箱的情况下运行(需要网络访问) 2. **归档文件解压**在沙箱子进程中运行(网络被阻止,文件系统受限) 3. **源代码分析** (YARA) 在应用沙箱后于主进程中运行(网络被阻止,文件系统限制为解压后的文件) 引入沙箱是为了缓解归档文件解压期间的路径遍历和代码执行漏洞(CVE-2022-23530, CVE-2022-23531, CVE-2026-22870, CVE-2026-22871)。 ## 扫描来自 S3 的包 GuardDog 可以扫描存储在 S3 中的包,可以是文件夹/前缀,也可以是单个归档文件对象: ``` guarddog npm scan s3://my-bucket/path/to/package/ guarddog npm scan s3://my-bucket/path/to/package.tar.gz ``` 这会使用你现有的 AWS 凭证(环境变量、`~/.aws`、SSO 或 IAM 角色)。GuardDog 在执行任何操作之前会通过 STS 验证身份验证,如果没有找到有效的凭证,则会报错退出。这些对象会被同步到一个临时目录中,像任何其他不受信任的内容一样在沙箱下进行扫描,并在之后从磁盘上删除。 ## 规则 GuardDog 使用两种类型的检测规则,两者都参与基于风险的评分引擎: * **源代码规则** (YARA):对包源代码进行静态分析,检测能力和威胁 * **元数据规则** (Python 检测器):分析包注册表元数据,检测供应链攻击指标 有关每个生态系统的完整规则列表,请参阅 **[RULES.md](RULES.md)**。 有关编写新规则的指南,请参阅 **[WRITING_RULES.md](WRITING_RULES.md)**。 ## 在 GitHub Action 中运行 GuardDog 将 GuardDog 集成到你的 CI pipeline 中最简单的方法是利用 SARIF 输出格式,并将其上传到 GitHub 的 [代码扫描](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/about-code-scanning) 功能。 使用此方法,你将获得: * 根据 GuardDog 扫描输出自动对你的 Pull Request 进行评论 * 直接在 GitHub UI 中进行内置的误报管理 使用 GuardDog 的 GitHub Action 示例: ``` name: GuardDog on: push: branches: - main pull_request: branches: - main permissions: contents: read jobs: guarddog: permissions: contents: read # for actions/checkout to fetch code security-events: write # for github/codeql-action/upload-sarif to upload SARIF results name: Scan dependencies runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: astral-sh/setup-uv@v7 - run: uvx guarddog pypi verify requirements.txt --output-format sarif --exclude-rules repository_integrity_mismatch > guarddog.sarif - name: Upload SARIF file to GitHub uses: github/codeql-action/upload-sarif@v3 with: category: guarddog-builtin sarif_file: guarddog.sarif ``` ## 开发 ### 运行本地版本的 GuardDog * 确保 poetry 拥有一个使用 `python >=3.10` 的环境 `poetry env use 3.10.0` * 安装依赖 `poetry install` * 运行 guarddog `poetry run guarddog` 或执行 `poetry shell` 后运行 `guarddog` ### 单元测试 运行所有单元测试:`make test` 针对包元数据启发式规则运行单元测试:`make test-metadata-rules`(测试位于[此处](https://github.com/DataDog/guarddog/tree/v3/tests/analyzer/metadata))。 ### 基准测试 你可以在合法和恶意的包上运行 GuardDog,以确定误报和漏报情况。请参阅 [./tests/samples](./tests/samples) ### 代码质量检查 使用以下命令运行类型检查器 ``` mypy --install-types --non-interactive guarddog ``` 并使用以下命令运行 linter ``` flake8 guarddog --count --select=E9,F63,F7,F82 --show-source --statistics --exclude tests/analyzer/sourcecode,tests/analyzer/metadata/resources,evaluator/data flake8 guarddog --count --max-line-length=120 --statistics --exclude tests/analyzer/sourcecode,tests/analyzer/metadata/resources,evaluator/data --ignore=E203,W503 ``` ### 通过环境变量进行配置 GuardDog 的行为可以使用环境变量进行自定义: #### 常规配置 | 环境变量 | 描述 | 默认值 | |---------------------|-------------|---------------| | `GUARDDOG_PARALLELISM` | 用于并行处理的线程数 | 可用的 CPU 数量 | | `GUARDDOG_VERIFY_EXHAUSTIVE_DEPENDENCIES` | 分析所有可能的依赖项版本 (`true`/`false`) | `false` | | `GUARDDOG_TOP_PACKAGES_CACHE_LOCATION` | 热门包缓存目录的位置 | `guarddog/analyzer/metadata/resources` | | `GUARDDOG_YARA_EXT_EXCLUDE` | 从 YARA 扫描中排除的文件扩展名逗号分隔列表 | `ini,md,rst,txt,lock,json,yaml,yml,toml,xml,html,csv,sql,pdf,doc,docx,ppt,pptx,xls,xlsx,odt,changelog,readme,makefile,dockerfile,pkg-info,d.ts` | #### 元数据规则配置 | 环境变量 | 描述 | 默认值 | |---------------------|-------------|---------------| | `GUARDDOG_NEW_DEPENDENCY_RISK_THRESHOLD` | 新引入的依赖项触发 `risky_new_dependency` 规则标记父包所需的最低风险评分 | `5.0` | #### 归档文件解压安全限制 GuardDog 在解压包归档文件时实施了多项安全检查,以防范压缩炸弹和文件描述符耗尽攻击: | 环境变量 | 描述 | 默认值 | |---------------------|-------------|---------------| | `GUARDDOG_MAX_UNCOMPRESSED_SIZE` | 允许的最大解压后大小(以字节为单位)(防止磁盘空间耗尽) | 2147483648 (2 GB) | | `GUARDDOG_MAX_COMPRESSION_RATIO` | 允许的最大压缩率(检测可疑的压缩模式) | 100 (100:1) | | `GUARDDOG_MAX_FILE_COUNT` | 归档文件中允许的最大文件数量(防止文件描述符/inode 耗尽) | 100000 | ## 维护者 * [Sebastian Obregoso](https://www.linkedin.com/in/sebastianobregoso/) * [Ian Kretz](https://github.com/ikretz) * [Tesnim Hamdouni](https://github.com/tesnim5hamdouni) ## 作者 * [Ellen Wang](https://www.linkedin.com/in/ellen-wang-4bb5961a0/) * [Christophe Tafani-Dereeper](https://github.com/christophetd) ## 致谢 灵感来源: * [Backstabber’s Knife Collection: A Review of Open Source Software Supply Chain Attacks](https://arxiv.org/pdf/2005.09535) * [What are Weak Links in the npm Supply Chain?](https://arxiv.org/pdf/2112.10165.pdf) * [A Survey on Common Threats in npm and PyPi Registries](https://arxiv.org/pdf/2108.09576.pdf) * [A Benchmark Comparison of Python Malware Detection Approaches](https://arxiv.org/pdf/2209.13288.pdf) * [Towards Measuring Supply Chain Attacks on Package Managers for Interpreted Languages](https://arxiv.org/pdf/2002.01139)
标签:LNA, YARA, 云安全监控, 云资产可视化, 域名收集, 网络信息收集, 请求拦截, 逆向工具, 静态分析