igor-php/igor-php

GitHub: igor-php/igor-php

专为 FrankenPHP Worker 模式设计的静态分析工具,检测 Symfony 共享服务中的状态突变、内存泄漏和全局污染风险。

Stars: 65 | Forks: 0

# 🧟‍♂️⚡ Igor-Php

Igor PHP Logo

**您 FrankenPHP Workers 的忠实助手。** `igor-php` 是一个使用 **Go** 编写的超快静态检测工具,用于为您的 **Symfony** 应用准备好迎接 **FrankenPHP** 的常驻内存模式。 就像传说中的助手一样,`igor` 会检查您应用的每一个连接和部件,以确保在闪电劈下时(Worker 模式)它不会“爆炸”。 ## ✨ 亮点 - **⚡ 闪电般的速度**:利用 Go 原生多线程在毫秒级内扫描数百个文件。 - **🔍 深度审计**:自动检测 Symfony 项目并审计容器中定义的**每一个共享服务**,包括 `vendor/` 和外部 bundle 中的服务。 - **🎯 精准外科手术**:检测复杂的状态修改(`$this->prop[]`、`static::$prop`、自增等)且无误报。 - **🧠 智能化**:不仅验证是否存在 `ResetInterface`,还确保所有被修改的属性都已被正确重置。自动忽略 **`readonly` 属性和类** (PHP 8.1+),因为它们在设计上是不可变的。 - **🛡️ 安全第一**:捕获危险的 `exit()` 或 `die()` 调用,并警告可能导致请求间状态泄漏的 **PHP Superglobals**(`$_GET`、`$_POST` 等)或 **局部静态变量**。 - **🔇 零噪音**:自动忽略 `Symfony\` 和 `Doctrine\` 命名空间,以及常见的数据文件夹(`Entity`、`Dto`、`ApiResource`)。 - **📦 项目与依赖包区分**:清晰区分您的代码和第三方依赖,并为它们提供量身定制的建议。 - **🎯 选择性忽略**:使用 `// @igor-ignore` 注释跳过特定行。 ## 📋 前置条件 - **Go**:编译或安装二进制文件所需。 - **PHP 8.1+**:**深度审计**模式所需。Igor 使用 PHP 反射来精确定位您项目和 `vendor/` 目录中的服务文件。如果没有 PHP,Igor 将回退到标准的目录扫描模式。 ## 🚀 安装说明 ### 通过 Composer 安装(推荐) ``` composer require --dev igor-php/igor-php ``` ### 启用 Symfony Bundle(可选但推荐) 为了让 Igor 更加可靠,您可以启用内嵌的 PHP bundle。它会直接从您的容器中生成精确的服务映射,供 Igor Go 用来审计您的服务。 将该 bundle 添加到您的 `config/bundles.php` 中: ``` return [ // ... IgorPhp\IgorBundle\IgorPhpBundle::class => ['dev' => true, 'test' => true], ]; ``` 或者手动添加到您的 `Kernel.php` 中: ``` public function registerBundles(): iterable { // ... if ($this->getEnvironment() === 'dev') { yield new IgorPhp\IgorBundle\IgorPhpBundle(); } } ``` ### 通过 Go 安装 ``` go install github.com/igor-php/igor-php@latest ``` ## 🛠️ 使用说明 ### 🪄 快速入门 Igor 可以自动检测您的 Symfony 项目类型并为您生成默认配置: ``` # 初始化 igor.json igor-php init # 使用自定义名称/路径初始化 igor-php init -c custom-igor.json ``` ### 🔍 审计您的项目 初始化之后(或使用默认配置),让 Igor 审计您的项目: ``` # 标准用法 igor-php . # 生成 baseline 以忽略现有错误 igor-php --generate-baseline # 自定义配置文件 igor-php --config custom-igor.json . # 或简写形式 igor-php -c custom-igor.json . # 自定义 console 路径、环境和 verbose 模式 igor-php --console app/console --env stage --verbose . ``` ## 🧪 运行效果 想了解为什么 Igor 对您的 Worker 环境至关重要吗?请查看我们 **泄漏实验室** 的这些真实场景: | **1. 内存压力(“BOOM”效应)** | **2. 全局状态污染** | |:---:|:---:| | ![内存泄漏演示](https://raw.githubusercontent.com/igor-php/igor-php/main/docs/heavy-load.gif) | ![全局状态泄漏演示](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/2365a57837213642.gif) | | *向没有重置机制的共享服务添加数据,会导致数据在 RAM 中不断累积,直到 Worker 崩溃。* | *修改全局 PHP 设置(例如时区)会“毒化” Worker 线程,影响所有后续请求。* | ### 🛡️ Igor 的判定:在 1 秒内捕获所有问题 ![Igor 扫描演示](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/ad465d35cb213707.gif) *Igor 会自动识别所有泄漏(静态、有状态、不完整重置)以及危险的全局函数调用。* ### 🧪 亲自体验泄漏实验室! 我们使用 Symfony 和 FrankenPHP 搭建了一个**交互式实验室**。您可以使用 Docker 在本地运行它,亲眼见证内存泄漏的发生。 ## [**探索 Igor 泄漏实验室 →**](examples/demo-leak/README.md) ### 深度审计模式 当检测到 Symfony 项目时,Igor 会结合三层发现机制以确保达到最高的可靠性: 1. **第 1 层:项目代码(递归扫描)**:Igor 会扫描您项目目录中的所有 PHP 文件(排除 `vendor`、`var`、`tests` 等)。这确保了即使 Symfony 为了优化而“内联”或“隐藏”了某个服务,Igor 依然能找到并审计它。 2. **第 2 层:智能过滤**:Igor 会自动解析您的 `composer.json` 以识别 `require-dev` 中的包。它将自动排除源自这些包的任何服务,以减少噪音并仅专注于生产环境代码。 3. **第 3 层:Igor 代理(内嵌 Bundle)**:通过启用可选的 PHP bundle,Igor 将变得“绝对可靠”。该 bundle 会挂钩到 Symfony 的编译过程中,导出所有活跃共享服务的精确映射。 ## 🧠 工作原理 ### 1. 智能过滤 Igor 会读取您 `composer.json` 中的 `require-dev` 部分。当它审计您的 Symfony 容器时,会检查每个服务的物理路径。如果某个服务位于属于开发包(例如 `phpunit/phpunit` 或 `symfony/maker-bundle`)的 `vendor/` 目录中,Igor 将自动跳过它。 ### 2. Igor 代理(PHP Bundle) `IgorPhpBundle` 包含一个 `CompilerPass`,它会在您每次清理 Symfony 缓存时运行(`php bin/console cache:clear`)。 - **它的作用**:遍历 `ContainerBuilder`,识别所有**共享服务**,并提取它们的类名和 ID。 - **缓存机制**:将这些信息写入一个小型 JSON 文件:`var/cache//igor_service_map.json`。 - **优势**:Go 二进制文件读取此文件,而不是执行繁重的 `debug:container` 命令。这使得审计启动几乎瞬间完成,并确保 100% 的准确性,即使是复杂编译器通道或装饰器添加的服务也不例外。 #### `igor_service_map.json` 示例: ``` { "definitions": { "app.mail_service": { "class": "App\\Service\\MailService", "public": true, "shared": true }, "logger": { "class": "Monolog\\Logger", "public": true, "shared": true } }, "aliases": { "Psr\\Log\\LoggerInterface": "logger" } } ``` ## ⚙️ 配置说明 您可以通过在项目根目录创建 `igor.json` 文件来自定义 Igor 的行为: ``` { "exclude": ["vendor", "var", "src/Entity"], "safe_namespaces": ["Symfony\\", "Doctrine\\", "Twig\\", "IgorPhp\\IgorBundle\\"], "console_path": "bin/console", "env": "dev", "verbose": false } ``` 耗时:1.2s 💡 建议: [PROJECT] 由于这是您自己的代码,您应该将这些服务重构为无状态的, 或者实现 ResetInterface 以在请求之间清除状态。 [VENDOR] 这是第三方代码。如果您无法修复它,请考虑在您的 Worker 配置中设置一个 'max_requests' 限制,以缓解内存泄漏。 ``` --- ## ⚙️ 配置 You can customize Igor's behavior by creating an `igor.json` file at the root of your project: ```json { "exclude": ["vendor", "tests", "Entity"], "safe_namespaces": ["Symfony\\", "Doctrine\\", "IgorPhp\\IgorBundle\\"], "scan_vendors": ["my-company/internal-bundle"], "baseline": "igor-baseline.json", "console_path": "bin/console", "env": "dev", "verbose": false } ``` - **exclude**:索引期间要跳过的目录列表。 - **safe_namespaces**:Igor 将忽略以这些前缀开头的类中的状态修改。 - **scan_vendors**:`vendor/` 中要递归扫描的子目录列表。 - **baseline**:包含要忽略的发现结果的基线文件路径。 - **console_path**:Symfony 控制台二进制文件的自定义路径。默认为 `bin/console`。 - **env**:用于容器分析的 Symfony 环境。默认为 `dev`。 - **verbose**:启用详细输出以查看跳过的服务及其原因。默认为 `false`。 ### 选择性忽略 如果您有一行特定的代码确认是安全的,您可以使用 `// @igor-ignore` 注解: ``` // @igor-ignore $this->cache = $data; // This line will be ignored $this->counter++; // @igor-ignore - This line too ``` ## 🔍 了解深度审计过滤机制 使用**深度审计**模式 时,Igor 分析的服务数量可能会少于您容器的总服务数。使用 `--verbose` 标志可以确切了解服务被跳过的原因。常见原因包括: - **🔄 重复文件**:多个服务 ID(别名、定位器等)指向同一个 PHP 文件。Igor 仅对每个唯一文件审计一次。 - **♻️ 非共享**:标记为 `shared: false` 的服务会在每次请求时重新创建,并且不会在 Worker 之间保持状态。它们在设计上是安全的。 - **λ 闭包 / 合成**:未映射到物理 PHP 类的服务(例如 Closures 或合成服务)无法进行静态分析。 - **🛡️ 安全命名空间**:该类属于 `safe_namespaces` 中定义的命名空间(例如 `Symfony\` 或 `Doctrine\`)。 ## 🤖 CI/CD 集成 Igor 旨在在您的 CI 流水线中开箱即用。如果发现任何错误,它将以 **代码 1** 退出,从而有效中止您的构建。 ### GitHub Actions 支持 在 GitHub Actions 内运行时,Igor 会自动生成**行内注解**。这意味着错误将直接显示在您的 Pull Request 审查中,紧挨着导致问题的代码旁。

Igor GitHub Review

### GitHub Actions 示例 ``` name: Static Analysis on: [push, pull_request] jobs: igor: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: '8.3' - name: Install Dependencies run: composer install --no-progress --prefer-dist - name: Warmup Symfony Cache (for Deep Audit) run: php bin/console cache:warmup --env=dev - name: Run Igor Audit run: vendor/bin/igor-php . ``` ## 🙏 致谢与灵感来源 - **[Phanalist](https://github.com/denzyldick/phanalist)**:特别感谢 `phanalist` 及其规则 `E0012`(有状态服务),它启发了 Igor 的核心状态修改检测逻辑。 - **[Gemini CLI](https://github.com/google/gemini-cli)**:本项目是在 Gemini CLI 的协助下构建的。 - **[FrankenPHP](https://frankenphp.dev/)**:感谢这个出色的服务器,使得这些检查变得非常有必要! ## 📄 许可证 MIT
标签:EVTX分析, FrankenPHP, Go语言开发, Linter, PHP Superglobals, PHP代码质量, PHP反射, PHP静态分析, pptx, ResetInterface, Symfony框架, Worker Mode, 不可变对象, 代码审计工具, 内存泄漏检测, 只读属性, 多线程扫描, 开源安全工具, 持久化内存, 日志审计, 本地静态变量, 源码安全审计, 状态变异检测, 逆向工程平台, 静态代码扫描