Compare commits

...

10 Commits

Author SHA1 Message Date
b7457a4dc7 Update .dockerignore for renamed compose.yml
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 19:36:10 +09:00
f0674365b3 Rename docker-compose.yml to compose.yml
- Use modern Compose file naming convention
- Remove deprecated version specification
- Update command example to use 'docker compose'

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 19:33:38 +09:00
4e069f39ed Fix placeholder URLs and references for OSS release
- Update php-security-lint wrapper script with correct repository URL
- Remove non-existent schema reference from config example
- Replace GitHub placeholder URLs with Gitea URLs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 19:32:08 +09:00
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
c562116568 Add PHP memory limit documentation for Docker builds
- Document --build-arg PHP_MEMORY_LIMIT option for large projects
- Default is 1024M, can increase to 2048M or more as needed
- Update Dockerfile version label to 0.0.1
- Add notes in both English and Japanese sections

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 16:04:56 +09:00
d407e95d1c Improve Docker installation documentation
- Reorganize Installation section with Docker as primary method
- Add step-by-step Docker build and run instructions
- Show direct docker run commands without wrapper script
- Make wrapper script optional
- Fix directory name to php-security-linter
- Update both English and Japanese sections

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 16:02:03 +09:00
62a4d499ae Update repository URLs to Gitea
- Change all URLs from github.com to opensource.rogarithm.net
- Update Docker image references to local build (php-security-linter:latest)
- Fix Gitea Issues URL in CONTRIBUTING.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 12:07:21 +09:00
208227b77e Prepare for OSS release v0.0.1
Version updates:
- Set version to 0.0.1 across all files
- Update CLI banner, SARIF output, and documentation

New files:
- LICENSE: MIT license
- CHANGELOG.md: Initial changelog with all features
- CONTRIBUTING.md: Contribution guidelines

composer.json enhancements:
- Add version, keywords, homepage, support URLs
- Add authors section
- Add require-dev for PHPUnit

README.md updates:
- Update repository URLs to security-linter/php-laravel
- Update Docker image references

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 11:57:18 +09:00
dbbde1cc45 Add documentation for Laravel-specific security detection
- Add section 8 to DETECTION_RULES.md covering:
  - Mass Assignment detection patterns
  - Raw SQL injection detection
  - CSRF protection checks
  - File upload validation rules
  - Route authentication middleware
  - Rate limiting detection
- Update README.md with Laravel-specific security in
  detectable vulnerabilities section (ja/en)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 21:45:26 +09:00
31a20b0509 Add Laravel security rule messages (ja/en)
Add message translations for LaravelSecurityRule:
- laravel.mass_assignment: Model without $fillable/$guarded
- laravel.mass_assignment_all: Using $request->all()
- laravel.raw_sql: Raw SQL without bindings
- laravel.db_raw: DB::raw() with variables
- laravel.csrf_missing: Form without @csrf
- laravel.file_validation: Extensions only validation
- laravel.route_auth: Sensitive route without auth
- laravel.route_throttle: Auth route without throttle

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 21:23:02 +09:00
14 changed files with 728 additions and 48 deletions

View File

@@ -20,5 +20,5 @@ vendor/
# Docker files (avoid recursion)
Dockerfile
docker-compose.yml
compose.yml
.dockerignore

View File

@@ -1,5 +1,4 @@
{
"$schema": "https://raw.githubusercontent.com/security-linter/php-laravel/main/schema/config.json",
"$comment": "Example configuration file for PHP/Laravel Security Linter",
"severity": "low",

77
CHANGELOG.md Normal file
View File

@@ -0,0 +1,77 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.0.1] - 2024-01-31
### Added
#### Core Features
- Recursive taint analysis for tracking user input through function calls
- Multi-language support (Japanese/English)
- Syntax highlighting in terminal output
- Multiple output formats: text, JSON, HTML, SARIF, Markdown
- Docker support for easy deployment
- Configuration file support (.security-lint.json)
#### Vulnerability Detection
**XSS (Cross-Site Scripting)**
- Blade `{!! !!}` raw output detection
- JavaScript context XSS
- Event handler attribute XSS
- URL context XSS (javascript: URLs)
- Style injection
- Template injection
- Escape bypass function detection
- Dangerous hardcoded HTML detection
**SQL Injection**
- Laravel Query Builder raw methods
- PDO/MySQLi direct queries
- String concatenation in queries
- Sanitizer bypass detection
**Command Injection**
- Shell execution functions (exec, shell_exec, system, etc.)
- Code execution functions (eval, create_function, etc.)
- Dynamic file includes
- Symfony Process usage
**Path Traversal**
- File operation functions
- Laravel Storage operations
- File download/upload
**Authentication Security**
- Weak hash algorithms (MD5, SHA1)
- Hardcoded credentials detection
- Timing-vulnerable comparisons
**CSRF/Session Security**
- Missing CSRF tokens
- Insecure session configuration
- Session fixation
**Configuration Security**
- Debug output (phpinfo, var_dump, dd)
- Insecure unserialize
- Sensitive information logging
**Laravel-Specific Security**
- Mass Assignment (missing $fillable/$guarded)
- Raw SQL injection (DB::raw, whereRaw without bindings)
- CSRF protection (forms without @csrf)
- File upload validation (extensions-only without mimes)
- Route authentication middleware
- Rate limiting for auth routes
### Security
- Safe pattern recognition for Laravel helpers (route(), url(), action())
- Value-based credential detection to reduce false positives
- Escape function recognition (htmlspecialchars, e(), etc.)
[0.0.1]: https://opensource.rogarithm.net/rogarithm/php-security-linter/releases/tag/v0.0.1

204
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,204 @@
# Contributing to PHP/Laravel Security Linter
Thank you for your interest in contributing to this project! This document provides guidelines and instructions for contributing.
## Code of Conduct
Please be respectful and constructive in all interactions. We welcome contributors of all experience levels.
## How to Contribute
### Reporting Bugs
1. Check if the issue already exists in [Gitea Issues](https://opensource.rogarithm.net/rogarithm/php-security-linter/issues)
2. If not, create a new issue with:
- Clear description of the problem
- Steps to reproduce
- Expected vs actual behavior
- PHP/Laravel versions
- Sample code that triggers the issue
### Reporting False Positives/Negatives
Security linters can produce false positives (safe code flagged as vulnerable) or false negatives (vulnerable code not detected). Please report these with:
- The code snippet being analyzed
- Why you believe it's a false positive/negative
- Any relevant context
### Suggesting Features
1. Check existing issues and discussions
2. Create a new issue describing:
- The vulnerability type you want to detect
- Example vulnerable and safe code patterns
- References to security documentation (CWE, OWASP, etc.)
### Pull Requests
1. Fork the repository
2. Create a feature branch: `git checkout -b feature/your-feature-name`
3. Make your changes
4. Test your changes
5. Commit with clear messages
6. Push and create a Pull Request
## Development Setup
### Requirements
- PHP 8.1+
- Composer
### Installation
```bash
git clone https://opensource.rogarithm.net/rogarithm/php-security-linter.git
cd php-laravel
composer install
```
### Running the Linter
```bash
# Analyze a file
php bin/security-lint path/to/file.php
# Analyze a directory
php bin/security-lint path/to/directory/
```
### Project Structure
```
├── bin/
│ └── security-lint # CLI entry point
├── src/
│ ├── SecurityLinter.php # Main linter class
│ ├── Rules/ # Detection rules
│ │ ├── XssRule.php
│ │ ├── SqlInjectionRule.php
│ │ ├── CommandInjectionRule.php
│ │ ├── PathTraversalRule.php
│ │ ├── AuthenticationRule.php
│ │ ├── CsrfRule.php
│ │ ├── InsecureConfigRule.php
│ │ └── LaravelSecurityRule.php
│ ├── Analysis/ # Analysis utilities
│ │ ├── TaintAnalyzer.php
│ │ └── FunctionAnalyzer.php
│ ├── Report/ # Report generation
│ │ ├── Vulnerability.php
│ │ └── ReportGenerator.php
│ └── I18n/ # Internationalization
│ └── Messages.php
├── docs/ # Documentation
│ ├── DETECTION_RULES.md
│ └── QUICK_REFERENCE.md
└── test-samples/ # Test samples
```
## Adding New Detection Rules
### 1. Create a New Rule Class
Create a new file in `src/Rules/`:
```php
<?php
namespace SecurityLinter\Rules;
use PhpParser\Node;
use SecurityLinter\Report\Vulnerability;
class YourNewRule extends AbstractRule
{
protected string $name = 'your_rule';
public function analyze(Node $node, string $file, array $context = []): array
{
$vulnerabilities = [];
// Your detection logic here
return $vulnerabilities;
}
}
```
### 2. Register the Rule
Add your rule to `SecurityLinter.php`:
```php
private function registerDefaultRules(): void
{
$this->rules = [
// ... existing rules
new YourNewRule(),
];
}
```
### 3. Add Messages
Add messages in `src/I18n/Messages.php` for both Japanese and English:
```php
// Japanese
'your_rule.name' => 'ルール名',
'your_rule.vulnerability_message' => '脆弱性の説明...',
// English
'your_rule.name' => 'Rule Name',
'your_rule.vulnerability_message' => 'Vulnerability description...',
```
### 4. Update Documentation
- Add detection patterns to `docs/DETECTION_RULES.md`
- Update README.md if needed
## Testing
### Manual Testing
Create test files in `test-samples/` to verify detection:
```php
<?php
// test-samples/your-test.php
// VULNERABLE: Should be detected
vulnerable_pattern();
// SAFE: Should not be detected
safe_pattern();
```
Run the linter against your test files:
```bash
php bin/security-lint test-samples/your-test.php -c
```
## Commit Guidelines
- Use clear, descriptive commit messages
- Reference issue numbers when applicable
- Keep commits focused on single changes
Example:
```
Add detection for insecure deserialization
- Detect unserialize() with allowed_classes => true
- Add messages in Japanese and English
- Update DETECTION_RULES.md
Fixes #123
```
## Questions?
Feel free to open an issue for questions or discussions.

View File

@@ -2,7 +2,7 @@ FROM php:8.3-cli-alpine
LABEL maintainer="Security Linter Team"
LABEL description="PHP/Laravel Security Linter - Static security analysis tool"
LABEL version="1.0.0"
LABEL version="0.0.1"
# Build arguments
ARG PHP_MEMORY_LIMIT=1024M

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Security Linter Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

136
README.md
View File

@@ -24,33 +24,62 @@ Detects vulnerabilities through recursive taint analysis by tracking data flow a
#### Method 1: Docker (Recommended)
No PHP or Composer environment required.
No PHP or Composer environment required. Just Docker.
**Step 1: Clone and build**
```bash
# Clone the repository
git clone https://github.com/your-org/php-laravel-security-linter.git
cd php-laravel-security-linter
# Install (builds Docker image and installs command)
./install.sh
git clone https://opensource.rogarithm.net/rogarithm/php-security-linter.git
cd php-security-linter
docker build -t php-security-linter:latest .
```
After installation, use the `php-security-lint` command:
**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
# Run in your project directory
cd /path/to/your/laravel-project
php-security-lint .
php-security-lint app/ -s high
```
#### Method 2: Direct Execution
#### Method 2: Direct Execution (PHP Required)
Requires PHP 8.1+ and Composer.
```bash
git clone https://github.com/your-org/php-laravel-security-linter.git
cd php-laravel-security-linter
git clone https://opensource.rogarithm.net/rogarithm/php-security-linter.git
cd php-security-linter
composer install
php bin/security-lint /path/to/target
```
@@ -194,11 +223,20 @@ Place `.security-lint.json` in your project root to persist settings:
- 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 v1.0.0
║ PHP/Laravel Security Linter v0.0.1
╚════════════════════════════════════════════════════════════╝
Analyzing: app/
@@ -258,7 +296,7 @@ jobs:
- name: Run Security Linter
run: |
docker run --rm -v ${{ github.workspace }}:/target \
ghcr.io/your-org/php-security-linter:latest \
php-security-linter:latest \
/target -s high -f sarif -o /target/security.sarif
- name: Upload SARIF
@@ -271,7 +309,7 @@ jobs:
```yaml
security-lint:
image: ghcr.io/your-org/php-security-linter:latest
image: php-security-linter:latest
script:
- security-lint . -s medium -f json -o security-report.json
artifacts:
@@ -323,33 +361,62 @@ PHP および Laravel アプリケーション向けの静的セキュリティ
#### 方法1: Docker推奨
PHPやComposerの環境構築なしで使用できます。
PHPやComposerの環境構築は不要です。Dockerのみで動作します。
**ステップ1: クローンとビルド**
```bash
# リポジトリをクローン
git clone https://github.com/your-org/php-laravel-security-linter.git
cd php-laravel-security-linter
# インストール (Dockerイメージのビルドとコマンドのインストール)
./install.sh
git clone https://opensource.rogarithm.net/rogarithm/php-security-linter.git
cd php-security-linter
docker build -t php-security-linter:latest .
```
インストール後は `php-security-lint` コマンドで使用できます:
**注意:** 大規模なプロジェクトでは、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: 直接実行
#### 方法2: 直接実行PHP必須
PHP 8.1以上とComposerが必要です。
```bash
git clone https://github.com/your-org/php-laravel-security-linter.git
cd php-laravel-security-linter
git clone https://opensource.rogarithm.net/rogarithm/php-security-linter.git
cd php-security-linter
composer install
php bin/security-lint /path/to/target
```
@@ -493,11 +560,20 @@ php bin/security-lint app/ -l en
- 安全でない unserialize
- 機密情報のログ出力
#### Laravel特有のセキュリティ
- Mass Assignment ($fillable/$guarded の欠落、$request->all() の使用)
- Raw SQL インジェクション (DB::raw、バインディングなしの whereRaw)
- CSRF 保護 (@csrf のないフォーム)
- ファイルアップロード検証 (mimes なしの extensions のみ)
- ルート認証 (auth ミドルウェアのないセンシティブなルート)
- レート制限 (throttle ミドルウェアのない認証ルート)
### 出力例
```
╔════════════════════════════════════════════════════════════╗
║ PHP/Laravel セキュリティリンター v1.0.0
║ PHP/Laravel セキュリティリンター v0.0.1
╚════════════════════════════════════════════════════════════╝
解析中: app/
@@ -557,7 +633,7 @@ jobs:
- name: Run Security Linter
run: |
docker run --rm -v ${{ github.workspace }}:/target \
ghcr.io/your-org/php-security-linter:latest \
php-security-linter:latest \
/target -s high -f sarif -o /target/security.sarif
- name: Upload SARIF
@@ -570,7 +646,7 @@ jobs:
```yaml
security-lint:
image: ghcr.io/your-org/php-security-linter:latest
image: php-security-linter:latest
script:
- security-lint . -s medium -f json -o security-report.json
artifacts:

View File

@@ -35,7 +35,7 @@ use SecurityLinter\I18n\Messages;
*/
class SecurityLintCLI
{
private const VERSION = '1.0.0';
private const VERSION = '0.0.1';
/** @var array Default directories/patterns to exclude */
private const DEFAULT_EXCLUDES = [

View File

@@ -1,5 +1,3 @@
version: '3.8'
services:
security-lint:
build:
@@ -10,4 +8,4 @@ services:
# Mount the target directory as read-only
- ${TARGET_PATH:-.}:/target:ro
# Default command can be overridden
# Example: docker-compose run --rm security-lint /target/app -s high
# Example: docker compose run --rm security-lint /target/app -s high

View File

@@ -1,8 +1,31 @@
{
"name": "security-linter/php-laravel",
"description": "Security linter for PHP and Laravel applications",
"description": "A static security analysis tool for PHP and Laravel applications with recursive taint analysis",
"version": "0.0.1",
"type": "project",
"license": "MIT",
"keywords": [
"security",
"linter",
"static-analysis",
"php",
"laravel",
"xss",
"sql-injection",
"vulnerability",
"sast"
],
"homepage": "https://opensource.rogarithm.net/rogarithm/php-security-linter",
"support": {
"issues": "https://opensource.rogarithm.net/rogarithm/php-security-linter/issues",
"source": "https://opensource.rogarithm.net/rogarithm/php-security-linter"
},
"authors": [
{
"name": "Security Linter Contributors",
"homepage": "https://opensource.rogarithm.net/rogarithm/php-security-linter/contributors"
}
],
"autoload": {
"psr-4": {
"SecurityLinter\\": "src/"
@@ -12,5 +35,13 @@
"php": ">=8.1",
"nikic/php-parser": "^5.0"
},
"bin": ["bin/security-lint"]
"require-dev": {
"phpunit/phpunit": "^10.0"
},
"bin": [
"bin/security-lint"
],
"config": {
"sort-packages": true
}
}

View File

@@ -13,6 +13,7 @@
5. [認証セキュリティ](#5-認証セキュリティ)
6. [CSRF/セッションセキュリティ](#6-csrfセッションセキュリティ)
7. [設定セキュリティ](#7-設定セキュリティ)
8. [Laravel特有のセキュリティ](#8-laravel特有のセキュリティ)
---
@@ -751,6 +752,241 @@ unserialize($data, ['allowed_classes' => [AllowedClass::class]]);
---
## 8. Laravel特有のセキュリティ
Laravel フレームワーク固有の脆弱性パターンを検出します。
### 8.1 Mass Assignment一括代入
Eloquent モデルで `$fillable` または `$guarded` プロパティが定義されていない場合を検出します。
| パターン | 重大度 |
|---------|--------|
| Model without `$fillable` or `$guarded` | HIGH |
| `Model::create($request->all())` | HIGH |
| `$model->fill($request->all())` | HIGH |
| `$model->update($request->all())` | HIGH |
**脆弱なコード:**
```php
// 危険: $fillable/$guarded がない
class User extends Model
{
// Mass Assignment 脆弱性
}
// 危険: $request->all() を直接使用
User::create($request->all());
$user->update($request->all());
```
**安全なコード:**
```php
// $fillable を定義
class User extends Model
{
protected $fillable = ['name', 'email'];
}
// または $guarded を定義
class User extends Model
{
protected $guarded = ['id', 'is_admin'];
}
// 特定のフィールドのみ使用
User::create($request->only(['name', 'email']));
$user->update($request->validated());
```
### 8.2 Raw SQL インジェクション
Laravel のクエリビルダーで生SQLを使用し、パラメータバインディングがない場合を検出します。
| パターン | 重大度 |
|---------|--------|
| `DB::raw($variable)` | HIGH |
| `whereRaw($sql)` (バインディングなし) | HIGH |
| `selectRaw($sql)` (バインディングなし) | HIGH |
| `orderByRaw($sql)` (バインディングなし) | HIGH |
| `havingRaw($sql)` (バインディングなし) | HIGH |
| `groupByRaw($sql)` (バインディングなし) | HIGH |
**脆弱なコード:**
```php
// 危険: 変数を含む DB::raw
$column = $request->input('column');
DB::table('users')->select(DB::raw($column))->get();
// 危険: バインディングなしの whereRaw
$name = $request->input('name');
User::whereRaw("name = '$name'")->get();
// 危険: バインディングなしの orderByRaw
$order = $request->input('order');
User::orderByRaw($order)->get();
```
**安全なコード:**
```php
// パラメータバインディングを使用
User::whereRaw('name = ?', [$name])->get();
User::orderByRaw('FIELD(status, ?, ?, ?)', ['active', 'pending', 'inactive'])->get();
// クエリビルダーを使用(推奨)
User::where('name', $name)->get();
User::orderBy($allowedColumns[$request->input('column')])->get();
```
### 8.3 CSRF 保護
POST/PUT/PATCH/DELETE メソッドのフォームに CSRF トークンがない場合を検出します。
| パターン | 重大度 |
|---------|--------|
| `<form method="POST">` without `@csrf` | HIGH |
| `<form method="post">` without `csrf_field()` | HIGH |
| `<form method="PUT">` without CSRF | HIGH |
| `<form method="DELETE">` without CSRF | HIGH |
**脆弱なコード:**
```blade
{{-- 危険: @csrf がない --}}
<form method="POST" action="/submit">
<input type="text" name="data">
<button type="submit">送信</button>
</form>
```
**安全なコード:**
```blade
{{-- @csrf ディレクティブを使用 --}}
<form method="POST" action="/submit">
@csrf
<input type="text" name="data">
<button type="submit">送信</button>
</form>
{{-- または csrf_field() ヘルパー --}}
<form method="POST" action="/submit">
{{ csrf_field() }}
<input type="text" name="data">
<button type="submit">送信</button>
</form>
```
### 8.4 ファイルアップロード検証
ファイルアップロードで `extensions` ルールのみを使用し、`mimes` または `mimetypes` ルールがない場合を検出します。拡張子のみのチェックは簡単にバイパスできます。
| パターン | 重大度 |
|---------|--------|
| `'file' => 'extensions:jpg,png'` (mimes なし) | MEDIUM |
| `'file' => ['extensions:jpg', 'file']` (mimes なし) | MEDIUM |
**脆弱なコード:**
```php
// 危険: 拡張子のみで検証
public function rules()
{
return [
'avatar' => ['required', 'file', 'extensions:jpg,png'],
'document' => 'file|extensions:pdf,doc',
];
}
```
**安全なコード:**
```php
// mimes または mimetypes を併用
public function rules()
{
return [
// mimes を使用(推奨)
'avatar' => ['required', 'file', 'mimes:jpeg,png'],
// extensions と mimes を両方使用
'document' => ['file', 'extensions:pdf,doc', 'mimes:pdf,msword'],
// mimetypes を使用
'video' => ['file', 'mimetypes:video/mp4,video/mpeg'],
];
}
```
### 8.5 ルート認証ミドルウェア
センシティブなルートに `auth` ミドルウェアがない場合を検出します。
| パターン | 重大度 |
|---------|--------|
| `Route::*('/admin/*')` without auth | LOW |
| `Route::*('/dashboard/*')` without auth | LOW |
| `Route::*('/user/*')` without auth | LOW |
| `Route::*('/account/*')` without auth | LOW |
| `Route::*('/settings/*')` without auth | LOW |
| `Route::*('/profile/*')` without auth | LOW |
**検出対象のセンシティブなルートパターン:**
- `/admin/`, `/dashboard/`, `/user/`, `/users/`
- `/account/`, `/settings/`, `/profile/`
- `/manage/`, `/management/`, `/billing/`
**脆弱なコード:**
```php
// 危険: 認証なしで管理画面にアクセス可能
Route::get('/admin/dashboard', [AdminController::class, 'index']);
Route::get('/users/manage', [UserController::class, 'manage']);
```
**安全なコード:**
```php
// ルートにミドルウェアを追加
Route::get('/admin/dashboard', [AdminController::class, 'index'])
->middleware('auth');
// グループでミドルウェアを適用(推奨)
Route::middleware(['auth'])->group(function () {
Route::get('/admin/dashboard', [AdminController::class, 'index']);
Route::get('/users/manage', [UserController::class, 'manage']);
});
```
### 8.6 レート制限
認証関連のルートに `throttle` ミドルウェアがない場合を検出します。ブルートフォース攻撃を防ぐために重要です。
| パターン | 重大度 |
|---------|--------|
| `Route::post('/login')` without throttle | LOW |
| `Route::post('/register')` without throttle | LOW |
| `Route::post('/password/reset')` without throttle | LOW |
| `Route::post('/password/email')` without throttle | LOW |
| `Route::post('/forgot-password')` without throttle | LOW |
| `Route::post('/2fa/*')` without throttle | LOW |
**脆弱なコード:**
```php
// 危険: レート制限なしでブルートフォース可能
Route::post('/login', [AuthController::class, 'login']);
Route::post('/password/reset', [PasswordController::class, 'reset']);
```
**安全なコード:**
```php
// throttle ミドルウェアを追加
Route::post('/login', [AuthController::class, 'login'])
->middleware('throttle:5,1'); // 1分間に5回まで
// グループでレート制限を適用
Route::middleware(['throttle:60,1'])->group(function () {
Route::post('/login', [AuthController::class, 'login']);
Route::post('/password/reset', [PasswordController::class, 'reset']);
});
```
---
## 再帰的なテイント解析
リンターは、関数呼び出しを通じてユーザー入力(テイントデータ)がどのように伝播するかを追跡します。
@@ -856,6 +1092,6 @@ php bin/security-lint app/ -l en
## バージョン
- ドキュメント作成日: 2024
- 対応 PHP バージョン: 8.0+
- バージョン: 0.0.1
- 対応 PHP バージョン: 8.1+
- 対応 Laravel バージョン: 9.x, 10.x, 11.x

View File

@@ -11,8 +11,9 @@
# php-security-lint -s high -f json .
#
# Installation:
# curl -o /usr/local/bin/php-security-lint https://raw.githubusercontent.com/your-org/php-laravel-security-linter/main/php-security-lint
# chmod +x /usr/local/bin/php-security-lint
# Copy this script to /usr/local/bin/ after building the Docker image:
# sudo cp php-security-lint /usr/local/bin/
# sudo chmod +x /usr/local/bin/php-security-lint
#
set -e
@@ -106,11 +107,10 @@ check_image() {
else
echo -e "${RED}Error: Docker image '$DOCKER_IMAGE' not found.${NC}" >&2
echo "" >&2
echo "To build the image, run from the security-linter directory:" >&2
echo "To build the image, clone the repository and run:" >&2
echo " git clone https://opensource.rogarithm.net/rogarithm/php-security-linter.git" >&2
echo " cd php-security-linter" >&2
echo " docker build -t php-security-linter:latest ." >&2
echo "" >&2
echo "Or pull from registry (if published):" >&2
echo " docker pull your-org/php-security-linter:latest" >&2
exit 1
fi
fi

View File

@@ -293,6 +293,25 @@ class Messages
'config.env_no_default' => '変数が存在しない場合に問題を引き起こす可能性があるデフォルト値なしの env() が呼び出されています。',
'config.env_no_default.rec' => 'デフォルト値を指定してください: env(\'KEY\', \'default\')',
// Laravel-specific messages
'laravel.name' => 'Laravelセキュリティ',
'laravel.mass_assignment' => 'Eloquentモデル \':class\' に $fillable または $guarded プロパティが定義されていません。Mass Assignment攻撃に対して脆弱です。',
'laravel.mass_assignment.rec' => 'モデルに protected $fillable = [...] または protected $guarded = [...] を定義してください。',
'laravel.mass_assignment_all' => ':method() で $request->all() を使用しています。Mass Assignment攻撃のリスクがあります。',
'laravel.mass_assignment_all.rec' => '$request->only([\'field1\', \'field2\']) または $request->validated() を使用してください。',
'laravel.raw_sql' => ':method() でパラメータバインディングなしの生SQLを使用しています。SQLインジェクションのリスクがあります。',
'laravel.raw_sql.rec' => 'バインディングを使用してください: ->:method(\'column = ?\', [$value])',
'laravel.db_raw' => 'DB::raw() に変数が含まれています。SQLインジェクションのリスクがあります。',
'laravel.db_raw.rec' => 'パラメータバインディングを使用するか、DB::raw() でのユーザー入力の使用を避けてください。',
'laravel.csrf_missing' => 'POST/PUT/PATCH/DELETE フォームに CSRF 保護がありません。',
'laravel.csrf_missing.rec' => 'フォーム内に @csrf ディレクティブを追加してください。',
'laravel.file_validation' => 'ファイルフィールド \':field\' は extensions のみで検証されています。MIMEタイプの検証がありません。',
'laravel.file_validation.rec' => 'mimes または mimetypes ルールを追加してください: \'file|mimes:jpg,png\'',
'laravel.route_auth' => 'センシティブなルート \':route\' に認証ミドルウェアがない可能性があります。',
'laravel.route_auth.rec' => 'middleware(\'auth\') または middleware(\'auth:sanctum\') を追加してください。',
'laravel.route_throttle' => '認証関連ルート \':route\' にレート制限がない可能性があります。',
'laravel.route_throttle.rec' => 'ブルートフォース攻撃を防ぐために middleware(\'throttle:login\') を追加してください。',
// Report messages
'report.title' => 'セキュリティスキャン結果',
'report.generated' => '生成日時',
@@ -537,6 +556,25 @@ class Messages
'config.env_no_default' => 'env() called without default value may cause issues if variable is missing.',
'config.env_no_default.rec' => 'Provide a default value: env(\'KEY\', \'default\')',
// Laravel-specific messages
'laravel.name' => 'Laravel Security',
'laravel.mass_assignment' => 'Eloquent model \':class\' has no $fillable or $guarded property defined. Vulnerable to Mass Assignment attacks.',
'laravel.mass_assignment.rec' => 'Define protected $fillable = [...] or protected $guarded = [...] in the model.',
'laravel.mass_assignment_all' => ':method() uses $request->all(). Risk of Mass Assignment attack.',
'laravel.mass_assignment_all.rec' => 'Use $request->only([\'field1\', \'field2\']) or $request->validated() instead.',
'laravel.raw_sql' => ':method() uses raw SQL without parameter binding. Risk of SQL injection.',
'laravel.raw_sql.rec' => 'Use bindings: ->:method(\'column = ?\', [$value])',
'laravel.db_raw' => 'DB::raw() contains variables. Risk of SQL injection.',
'laravel.db_raw.rec' => 'Use parameter bindings or avoid user input in DB::raw().',
'laravel.csrf_missing' => 'POST/PUT/PATCH/DELETE form is missing CSRF protection.',
'laravel.csrf_missing.rec' => 'Add @csrf directive inside the form.',
'laravel.file_validation' => 'File field \':field\' is validated with extensions only. Missing MIME type validation.',
'laravel.file_validation.rec' => 'Add mimes or mimetypes rule: \'file|mimes:jpg,png\'',
'laravel.route_auth' => 'Sensitive route \':route\' may be missing authentication middleware.',
'laravel.route_auth.rec' => 'Add middleware(\'auth\') or middleware(\'auth:sanctum\').',
'laravel.route_throttle' => 'Auth-related route \':route\' may be missing rate limiting.',
'laravel.route_throttle.rec' => 'Add middleware(\'throttle:login\') to prevent brute force attacks.',
// Report messages
'report.title' => 'Security Scan Results',
'report.generated' => 'Generated',

View File

@@ -299,7 +299,7 @@ HTML;
'tool' => [
'driver' => [
'name' => 'PHP/Laravel Security Linter',
'version' => '1.0.0',
'version' => '0.0.1',
],
],
'results' => $results,