Files
php-security-linter/README.md
Yutaka Kurosaki 91bcb53ab5 Add PHP_MEMORY_LIMIT option for install.sh
- Document environment variable usage: PHP_MEMORY_LIMIT=2048M ./install.sh
- Update both English and Japanese sections

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 16:05:42 +09:00

695 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PHP/Laravel Security Linter
**[English](#english) | [日本語](#japanese)**
---
<a name="english"></a>
## English
A static security analysis tool for PHP and Laravel applications.
Detects vulnerabilities through recursive taint analysis by tracking data flow across function calls.
### Features
- **Comprehensive Vulnerability Detection**: XSS, SQL Injection, Command Injection, Path Traversal, and more
- **Recursive Taint Analysis**: Tracks how user input propagates through function calls
- **Blade Template Analysis**: Laravel-specific `{!! !!}` syntax and context-aware XSS detection
- **Smart Escape Detection**: Recognizes escape functions like `htmlspecialchars()`
- **Escape Bypass Detection**: Detects escape invalidation by functions like `html_entity_decode()`
- **Syntax Highlighting**: Color-coded code snippets in terminal output
- **Multi-language Support**: Japanese/English message output
### Installation
#### Method 1: Docker (Recommended)
No PHP or Composer environment required. Just Docker.
**Step 1: Clone and build**
```bash
git clone https://opensource.rogarithm.net/rogarithm/php-security-linter.git
cd php-security-linter
docker build -t php-security-linter:latest .
```
**Note:** For large projects, you may need to increase the PHP memory limit:
```bash
# Build with 2GB memory limit (default: 1024M)
docker build --build-arg PHP_MEMORY_LIMIT=2048M -t php-security-linter:latest .
```
**Step 2: Run**
```bash
# Scan your project directory
docker run --rm -v /path/to/your/project:/target:ro php-security-linter:latest /target
# Scan current directory
docker run --rm -v $(pwd):/target:ro php-security-linter:latest /target
# With options (high severity only, JSON output)
docker run --rm -v $(pwd):/target php-security-linter:latest /target -s high -f json -o /target/report.json
```
**Optional: Install wrapper command**
For convenience, you can install a wrapper script:
```bash
./install.sh
# Or with custom memory limit
PHP_MEMORY_LIMIT=2048M ./install.sh
```
After installation, use the `php-security-lint` command anywhere:
```bash
cd /path/to/your/laravel-project
php-security-lint .
php-security-lint app/ -s high
```
#### Method 2: Direct Execution (PHP Required)
Requires PHP 8.1+ and Composer.
```bash
git clone https://opensource.rogarithm.net/rogarithm/php-security-linter.git
cd php-security-linter
composer install
php bin/security-lint /path/to/target
```
### Usage
```bash
# Analyze a single file
php bin/security-lint path/to/file.php
# Analyze a directory
php bin/security-lint app/
# Show high severity only
php bin/security-lint app/ -s high
# Show code context (3 lines)
php bin/security-lint app/ -c
# Show code context (5 lines)
php bin/security-lint app/ -c 5
# Output as JSON
php bin/security-lint app/ -f json -o report.json
# Output in English
php bin/security-lint app/ -l en
```
### Options
#### Output Options
| Option | Description |
|--------|-------------|
| `-f, --format` | Output format: text, json, html, sarif, markdown |
| `-s, --severity` | Minimum severity: low, medium, high, critical |
| `-o, --output` | Output to file |
| `-l, --lang` | Language: ja, en |
| `-c, --context [N]` | Show N lines of code context (default: 3) |
| `--verbose` | Show detailed information |
| `-q, --quiet` | Suppress progress output |
| `--no-colors` | Disable colored output |
#### Exclude/Include Options
| Option | Description |
|--------|-------------|
| `-e, --exclude` | Exclude pattern (can be used multiple times) |
| `-i, --include` | Include pattern (overrides exclude) |
| `--include-vendor` | Also analyze vendor directory |
| `--include-tests` | Also analyze tests directory |
| `--no-default-excludes` | Don't use default exclude patterns |
| `--show-excluded` | Show excluded patterns |
#### Analysis Options
| Option | Description |
|--------|-------------|
| `-d, --recursive-depth` | Recursive analysis depth (default: 10) |
### Default Exclude Patterns
The following directories/patterns are excluded by default:
- `vendor/*` - Composer dependencies
- `node_modules/*` - npm dependencies
- `storage/*` - Laravel storage
- `bootstrap/cache/*` - Laravel cache
- `public/vendor/*` - Public assets
- `.git/*`, `.svn/*` - Version control
- `tests/*` - Test files
- `cache/*`, `tmp/*`, `temp/*` - Temporary files
To include these in analysis, use `--include-vendor` or `--include-tests`, or disable all with `--no-default-excludes`.
### Configuration File
Place `.security-lint.json` in your project root to persist settings:
```json
{
"severity": "medium",
"format": "text",
"lang": "en",
"exclude": ["custom/legacy/*"],
"include": ["vendor/my-company/*"],
"includeVendor": false,
"includeTests": false
}
```
### Detectable Vulnerabilities
#### XSS (Cross-Site Scripting)
- Blade `{!! !!}` raw output
- Output within JavaScript context
- Output within event handler attributes
- URL context (javascript: URLs)
- Style injection
- Template injection
- Escape bypass functions
- Dangerous hardcoded HTML
#### SQL Injection
- Tainted data in `DB::raw()`
- Query construction via string concatenation
- Direct PDO/MySQLi queries
- Laravel Query Builder Raw methods
#### Command Injection
- `exec()`, `shell_exec()`, `system()`, etc.
- `eval()`, `create_function()`, etc.
- Dynamic file includes
- Improper Symfony Process usage
#### Path Traversal
- Tainted paths in file operation functions
- Tainted paths in Laravel Storage
- File download/upload
#### Authentication Security
- Weak hash algorithms (MD5, SHA1)
- Hardcoded credentials
- Timing-vulnerable comparisons
#### CSRF/Session
- Missing CSRF tokens
- Insecure session configuration
- Session fixation
#### Configuration Security
- Debug output (phpinfo, var_dump)
- Insecure unserialize
- Sensitive information logging
#### Laravel-Specific Security
- Mass Assignment (missing $fillable/$guarded, using $request->all())
- Raw SQL injection (DB::raw, whereRaw without bindings)
- CSRF protection (forms without @csrf)
- File upload validation (extensions-only without mimes)
- Route authentication (sensitive routes without auth middleware)
- Rate limiting (auth routes without throttle middleware)
### Output Example
```
╔════════════════════════════════════════════════════════════╗
║ PHP/Laravel Security Linter v0.0.1 ║
╚════════════════════════════════════════════════════════════╝
Analyzing: app/
HIGH (2)
────────────────────────────────────────────────────────────
[XSS] Blade's {!! !!} raw output may cause XSS vulnerability.
📍 resources/views/user.blade.php:15
┌─ user.blade.php
│ 12 <div class="user-info">
│ 13 <h2>{{ $user->name }}</h2>
│ 14 <div class="bio">
│ 15 ▶ {!! $userName !!}
│ 16 </div>
│ 17 </div>
└─
🏷️ CWE-79 | A7:2017-XSS
💡 Use auto-escaped {{ }} instead.
════════════════════════════════════════════════════════════
Summary
────────────────────────────────────────────────────────────
Critical: 0
High: 2
Medium: 0
Low: 0
────────────────────────────────────────────────────────────
Total: 2
Completed in 0.15 seconds
```
### Exit Codes
| Code | Meaning |
|------|---------|
| 0 | No issues found |
| 1 | Medium/low severity issues found |
| 2 | Critical/high severity issues found |
### CI/CD Integration
#### GitHub Actions (Docker)
```yaml
name: Security Scan
on: [push, pull_request]
jobs:
security-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Security Linter
run: |
docker run --rm -v ${{ github.workspace }}:/target \
php-security-linter:latest \
/target -s high -f sarif -o /target/security.sarif
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: security.sarif
```
#### GitLab CI
```yaml
security-lint:
image: php-security-linter:latest
script:
- security-lint . -s medium -f json -o security-report.json
artifacts:
reports:
sast: security-report.json
```
### Docker Details
#### Manual Docker Usage
```bash
# Build image
docker build -t php-security-linter:latest .
# Run (scan current directory)
docker run --rm -v $(pwd):/target:ro php-security-linter:latest /target
# With options
docker run --rm -v $(pwd):/target:ro php-security-linter:latest \
/target/app -s high -f json
```
#### Environment Variables
| Variable | Description |
|----------|-------------|
| `PHP_SECURITY_LINT_IMAGE` | Docker image to use (default: php-security-linter:latest) |
---
<a name="japanese"></a>
## 日本語
PHP および Laravel アプリケーション向けの静的セキュリティ解析ツールです。
再帰的なテイント解析により、関数呼び出しを通じた脆弱性を検出します。
### 特徴
- **包括的な脆弱性検出**: XSS、SQLインジェクション、コマンドインジェクション、パストラバーサルなど
- **再帰的テイント解析**: ユーザー入力が関数を通じてどのように伝播するかを追跡
- **Blade テンプレート解析**: Laravel 特有の `{!! !!}` 構文やコンテキスト別XSS検出
- **スマートなエスケープ検出**: `htmlspecialchars()` 等のエスケープ関数を認識
- **エスケープ破壊の検出**: `html_entity_decode()` 等によるエスケープ無効化を検出
- **シンタックスハイライト**: ターミナル出力でコードスニペットを色分け表示
- **多言語対応**: 日本語/英語のメッセージ出力
### インストール
#### 方法1: Docker推奨
PHPやComposerの環境構築は不要です。Dockerのみで動作します。
**ステップ1: クローンとビルド**
```bash
git clone https://opensource.rogarithm.net/rogarithm/php-security-linter.git
cd php-security-linter
docker build -t php-security-linter:latest .
```
**注意:** 大規模なプロジェクトでは、PHPのメモリ制限を増やす必要がある場合があります
```bash
# 2GBのメモリ制限でビルドデフォルト: 1024M
docker build --build-arg PHP_MEMORY_LIMIT=2048M -t php-security-linter:latest .
```
**ステップ2: 実行**
```bash
# プロジェクトディレクトリをスキャン
docker run --rm -v /path/to/your/project:/target:ro php-security-linter:latest /target
# カレントディレクトリをスキャン
docker run --rm -v $(pwd):/target:ro php-security-linter:latest /target
# オプション付き高重大度のみ、JSON出力
docker run --rm -v $(pwd):/target php-security-linter:latest /target -s high -f json -o /target/report.json
```
**オプション: ラッパーコマンドのインストール**
便利なラッパースクリプトをインストールできます:
```bash
./install.sh
# メモリ制限を指定する場合
PHP_MEMORY_LIMIT=2048M ./install.sh
```
インストール後は `php-security-lint` コマンドでどこからでも使用できます:
```bash
cd /path/to/your/laravel-project
php-security-lint .
php-security-lint app/ -s high
```
#### 方法2: 直接実行PHP必須
PHP 8.1以上とComposerが必要です。
```bash
git clone https://opensource.rogarithm.net/rogarithm/php-security-linter.git
cd php-security-linter
composer install
php bin/security-lint /path/to/target
```
### 使用方法
```bash
# 単一ファイルの解析
php bin/security-lint path/to/file.php
# ディレクトリの解析
php bin/security-lint app/
# 高重大度のみ表示
php bin/security-lint app/ -s high
# コードスニペット表示 (前後3行)
php bin/security-lint app/ -c
# コードスニペット表示 (前後5行)
php bin/security-lint app/ -c 5
# JSON形式で出力
php bin/security-lint app/ -f json -o report.json
# 英語で出力
php bin/security-lint app/ -l en
```
### オプション
#### 出力オプション
| オプション | 説明 |
|-----------|------|
| `-f, --format` | 出力形式: text, json, html, sarif, markdown |
| `-s, --severity` | 最小重大度: low, medium, high, critical |
| `-o, --output` | ファイルに出力 |
| `-l, --lang` | 言語: ja, en |
| `-c, --context [N]` | 問題行の前後N行のコードスニペットを表示 (デフォルト: 3) |
| `--verbose` | 詳細情報を表示 |
| `-q, --quiet` | 進捗を非表示 |
| `--no-colors` | カラー出力を無効化 |
#### 除外/包含オプション
| オプション | 説明 |
|-----------|------|
| `-e, --exclude` | 除外パターン (複数回使用可能) |
| `-i, --include` | 包含パターン (除外を上書き) |
| `--include-vendor` | vendor ディレクトリも解析 |
| `--include-tests` | tests ディレクトリも解析 |
| `--no-default-excludes` | デフォルト除外パターンを使用しない |
| `--show-excluded` | 除外されるパターンを表示 |
#### 解析オプション
| オプション | 説明 |
|-----------|------|
| `-d, --recursive-depth` | 再帰解析の深度 (デフォルト: 10) |
### デフォルト除外パターン
以下のディレクトリ/パターンはデフォルトで除外されます:
- `vendor/*` - Composer 依存関係
- `node_modules/*` - npm 依存関係
- `storage/*` - Laravel ストレージ
- `bootstrap/cache/*` - Laravel キャッシュ
- `public/vendor/*` - 公開アセット
- `.git/*`, `.svn/*` - バージョン管理
- `tests/*` - テストファイル
- `cache/*`, `tmp/*`, `temp/*` - 一時ファイル
これらを含めて解析したい場合は `--include-vendor``--include-tests` を使用するか、`--no-default-excludes` で全て無効化できます。
### 設定ファイル
プロジェクトルートに `.security-lint.json` を配置することで設定を永続化できます:
```json
{
"severity": "medium",
"format": "text",
"lang": "ja",
"exclude": ["custom/legacy/*"],
"include": ["vendor/my-company/*"],
"includeVendor": false,
"includeTests": false
}
```
### 検出可能な脆弱性
#### XSS (クロスサイトスクリプティング)
- Blade の `{!! !!}` 生出力
- JavaScript コンテキスト内の出力
- イベントハンドラ属性内の出力
- URL コンテキスト (javascript: URL)
- Style インジェクション
- テンプレートインジェクション
- エスケープ破壊関数の使用
- 危険なハードコード HTML
#### SQLインジェクション
- `DB::raw()` への汚染データ
- 文字列連結によるクエリ構築
- PDO/MySQLi の直接クエリ
- Laravel クエリビルダーの Raw メソッド
#### コマンドインジェクション
- `exec()`, `shell_exec()`, `system()`
- `eval()`, `create_function()`
- 動的ファイルインクルード
- Symfony Process の不適切な使用
#### パストラバーサル
- ファイル操作関数への汚染パス
- Laravel Storage への汚染パス
- ファイルダウンロード/アップロード
#### 認証セキュリティ
- 弱いハッシュアルゴリズム (MD5, SHA1)
- ハードコードされた認証情報
- タイミング攻撃に脆弱な比較
#### CSRF/セッション
- CSRF トークンの欠落
- 安全でないセッション設定
- セッション固定化
#### 設定セキュリティ
- デバッグ出力 (phpinfo, var_dump)
- 安全でない unserialize
- 機密情報のログ出力
#### Laravel特有のセキュリティ
- Mass Assignment ($fillable/$guarded の欠落、$request->all() の使用)
- Raw SQL インジェクション (DB::raw、バインディングなしの whereRaw)
- CSRF 保護 (@csrf のないフォーム)
- ファイルアップロード検証 (mimes なしの extensions のみ)
- ルート認証 (auth ミドルウェアのないセンシティブなルート)
- レート制限 (throttle ミドルウェアのない認証ルート)
### 出力例
```
╔════════════════════════════════════════════════════════════╗
║ PHP/Laravel セキュリティリンター v0.0.1 ║
╚════════════════════════════════════════════════════════════╝
解析中: app/
HIGH (2)
────────────────────────────────────────────────────────────
[XSS] Blade の {!! !!} による生出力はXSSの脆弱性を引き起こす可能性があります。
📍 resources/views/user.blade.php:15
┌─ user.blade.php
│ 12 <div class="user-info">
│ 13 <h2>{{ $user->name }}</h2>
│ 14 <div class="bio">
│ 15 ▶ {!! $userName !!}
│ 16 </div>
│ 17 </div>
└─
🏷️ CWE-79 | A7:2017-XSS
💡 自動エスケープされる {{ }} を使用してください。
════════════════════════════════════════════════════════════
サマリー
────────────────────────────────────────────────────────────
クリティカル: 0
高: 2
中: 0
低: 0
────────────────────────────────────────────────────────────
合計: 2
0.15 秒で完了
```
### 終了コード
| コード | 意味 |
|--------|------|
| 0 | 問題なし |
| 1 | 中/低重大度の問題あり |
| 2 | クリティカル/高重大度の問題あり |
### CI/CD 統合
#### GitHub Actions (Docker)
```yaml
name: Security Scan
on: [push, pull_request]
jobs:
security-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Security Linter
run: |
docker run --rm -v ${{ github.workspace }}:/target \
php-security-linter:latest \
/target -s high -f sarif -o /target/security.sarif
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: security.sarif
```
#### GitLab CI
```yaml
security-lint:
image: php-security-linter:latest
script:
- security-lint . -s medium -f json -o security-report.json
artifacts:
reports:
sast: security-report.json
```
### Docker 詳細
#### 手動でDockerを使用
```bash
# イメージのビルド
docker build -t php-security-linter:latest .
# 実行 (カレントディレクトリをスキャン)
docker run --rm -v $(pwd):/target:ro php-security-linter:latest /target
# オプション付き
docker run --rm -v $(pwd):/target:ro php-security-linter:latest \
/target/app -s high -f json
```
#### 環境変数
| 変数 | 説明 |
|------|------|
| `PHP_SECURITY_LINT_IMAGE` | 使用するDockerイメージ (デフォルト: php-security-linter:latest) |
---
## Documentation / ドキュメント
- [Detection Rules / 検出ルール詳細](docs/DETECTION_RULES.md)
- [Quick Reference / クイックリファレンス](docs/QUICK_REFERENCE.md)
## License / ライセンス
MIT License
## References / 参考資料
- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
- [CWE/SANS Top 25](https://cwe.mitre.org/top25/)
- [Laravel Security](https://laravel.com/docs/security)