Communitygithub.com

laravel-security

Laravel 安全最佳實務 — 身分驗證、授權、Eloquent 安全、CSRF、XSS 防護、API 安全與安全部署設定。在審查 Laravel 認證、Eloquent 安全、CSRF、XSS、API 安全性或部署配置時使用。

laravel-security 是什麼?

這份 Laravel 安全最佳實務技能為開發者提供了全面的安全指南,涵蓋 Laravel 應用程式的常見漏洞防護。它支援 Laravel 的多種認證與授權機制,包括 Sanctum、Passport、Jetstream 和 Breeze,並詳細說明如何使用 Gates 和 Policies 進行細緻的權限控制。此技能也著重於 Eloquent ORM 的安全性,包括大量指派保護、SQL 注入防範、屬性型別轉換與模型安全設定,確保資料庫操作的安全性。此外,它還涵蓋了 CSRF 防護、XSS 預防策略、API 安全措施(如令牌過期與能力驗證),以及生產環境的配置最佳實務,例如強制 HTTPS、環境檔案安全與信任代理設定。通過具體的程式碼範例和明確的危險模式警告,此技能幫助開發者在審查或建置 Laravel 應用時,能有效識別並修補安全漏洞,適用於 Cursor、Claude Code、Codex 等多種 AI 代理平台。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/laravel-security

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

Laravel 安全最佳實務

全面的 Laravel 應用安全指南,保護應用免受常見漏洞攻擊。

使用時機

  • 設定 Laravel 身分驗證與授權 (Sanctum、Passport、Jetstream、Breeze)
  • 實作使用者角色、權限與政策
  • 設定生產環境安全設定與環境變數
  • 審查 Laravel 應用的安全性漏洞
  • 部署 Laravel 應用到生產環境
  • 撰寫安全的 Eloquent 查詢與遷移

生產環境設定

必要的生產設定

// config/app.php
'env' => env('APP_ENV', 'production'),
'debug' => (bool) env('APP_DEBUG', false), // 關鍵:生產環境絕不能為 true
'key' => env('APP_KEY'), // 必須設定:php artisan key:generate

// config/session.php
'secure' => env('SESSION_SECURE_COOKIE', true),
'http_only' => true,
'same_site' => 'lax',

// 啟動時驗證 APP_KEY 是否已設定
// bootstrap/app.php 或某個服務提供者
if (empty(config('app.key'))) {
    throw new RuntimeException('APP_KEY 未設定。請執行:php artisan key:generate');
}

環境檔案安全性

# 絕不要將 .env 提交到版本控制
# .gitignore 預設已包含 .env

# 改為使用 .env.example 並保留佔位符
DB_PASSWORD=
APP_KEY=
SANCTUM_TOKEN_PREFIX=

# 啟動時驗證必要的變數
// 在 AppServiceProvider::boot() 中
$requiredKeys = ['app.key', 'database.connections.mysql.database', 'database.connections.mysql.username'];
foreach ($requiredKeys as $key) {
    if (empty(config($key))) {
        throw new RuntimeException("缺少必要的設定鍵:{$key}");
    }
}

強制 HTTPS

// AppServiceProvider::boot() 或中介層
if (app()->environment('production')) {
    URL::forceScheme('https');
    request()->server->set('HTTPS', 'on');
}

// config/app.php 中的信任代理設定 (負載平衡器)
// 請使用特定的 IP 範圍 — * 會信任所有來源,允許 X-Forwarded-* 偽造
// AWS:'10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'
'trusted_proxies' => ['10.0.0.0/8', '172.16.0.0/12'],

// 透過中介層在生產環境強制 HTTPS
// app/Http/Middleware/ForceHttps.php
public function handle($request, Closure $next)
{
    if (!$request->secure() && app()->environment('production')) {
        return redirect()->secure($request->getRequestUri());
    }
    return $next($request);
}

身分驗證

Sanctum (API 令牌認證)

// config/sanctum.php
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
    '%s%s',
    'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
    env('APP_URL') ? ',' . parse_url(env('APP_URL'), PHP_URL_HOST) : ''
)));

'expiration' => 60 * 24, // 令牌過期時間 (分鐘),null 為永不過期
'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''),

// 發送帶有能力的令牌
$token = $user->createToken('api-token', ['read', 'write'])->plainTextToken;

// 在路由上驗證能力
Route::middleware('auth:sanctum')->group(function () {
    Route::get('/orders', function () {
        // 使用者必須擁有 'read' 能力
        abort_unless(Auth::user()->tokenCan('read'), 403);
        // ...
    })->middleware('abilities:read');

    Route::post('/orders', function () {
        // 使用者必須擁有 'write' 能力
        abort_unless(Auth::user()->tokenCan('write'), 403);
        // ...
    })->middleware('abilities:write');
});

密碼安全性

// config/hashing.php
// 預設為 bcrypt。Argon2id 更強大。
'bcrypt' => [
    'rounds' => env('BCRYPT_ROUNDS', 12), // 增加以強化雜湊
],

'argon' => [
    'memory' => 65536,
    'threads' => 4,
    'time' => 4,
],

// RegisterRequest 中的密碼驗證
public function rules(): array
{
    return [
        'password' => [
            'required',
            'confirmed',
            Password::min(12)
                ->letters()
                ->mixedCase()
                ->numbers()
                ->symbols()
                ->uncompromised(), // 檢查 haveibeenpwned
        ],
    ];
}

// 限制登入嘗試次數
// App\Http\Controllers\Auth\AuthenticatedSessionController
protected function authenticated(Request $request, $user)
{
    if ($user->wasRecentlyLockedOut()) {
        // 通知使用者有可疑登入
        $user->notify(new SuspiciousLoginNotification($request->ip()));
    }
}

工作階段管理

// config/session.php
'driver' => env('SESSION_DRIVER', 'database'), // database/redis 優於 file
'lifetime' => env('SESSION_LIFETIME', 120),
'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false),
'encrypt' => env('SESSION_ENCRYPT', false),

// 登入時重新生成工作階段
// App\Http\Controllers\Auth\AuthenticatedSessionController
public function store(LoginRequest $request): RedirectResponse
{
    $request->authenticate();
    $request->session()->regenerate(); // 關鍵:防止工作階段固定攻擊
    return redirect()->intended(RouteServiceProvider::HOME);
}

// 登出時使工作階段失效
public function destroy(Request $request): RedirectResponse
{
    Auth::guard('web')->logout();
    $request->session()->invalidate();
    $request->session()->regenerateToken();
    return redirect('/');
}

授權

Gates

// App\Providers\AuthServiceProvider
use App\Models\Post;
use App\Models\User;
use Illuminate\Support\Facades\Gate;

public function boot(): void
{
    Gate::define('update-post', function (User $user, Post $post): bool {
        return $user->id === $post->user_id;
    });

    Gate::define('publish-post', function (User $user): bool {
        return $user->role === 'editor' || $user->role === 'admin';
    });

    // 使用 before() 進行超級管理員覆寫
    Gate::before(function (User $user, string $ability): ?bool {
        if ($user->role === 'super-admin') {
            return true; // 授予所有能力
        }
        return null; // 交由一般檢查處理
    });
}

// 在控制器中使用
public function update(Request $request, Post $post): RedirectResponse
{
    Gate::authorize('update-post', $post);
    // 或:$this->authorize('update-post', $post);
    // 或:abort_unless(Auth::user()->can('update-post', $post), 403);
    // ...
}

Policies

// App\Policies\PostPolicy
class PostPolicy
{
    use HandlesAuthorization;

    public function viewAny(?User $user): bool
    {
        return true; // 公開列表
    }

    public function view(?User $user, Post $post): bool
    {
        return $post->is_published || ($user && $user->id === $post->user_id);
    }

    public function create(User $user): bool
    {
        return $user->hasVerifiedEmail(); // 必須先驗證電子郵件
    }

    public function update(User $user, Post $post): bool
    {
        return $user->id === $post->user_id;
    }

    public function delete(User $user, Post $post): bool
    {
        return $user->id === $post->user_id && $post->created_at->diffInDays(now()) <= 30;
    }

    public function restore(User $user, Post $post): bool
    {
        return $user->role === 'admin';
    }

    public function forceDelete(User $user, Post $post): bool
    {
        return $user->role === 'super-admin';
    }
}

// 在 AuthServiceProvider 中註冊
protected $policies = [
    Post::class => PostPolicy::class,
];

// 控制器中使用
public function show(Post $post): View
{
    $this->authorize('view', $post);
    return view('posts.show', compact('post'));
}

// Blade 中使用
@can('update', $post)
    <a href="{{ route('posts.edit', $post) }}">編輯</a>
@endcan

@cannot('update', $post)
    <span>您無法編輯此文章</span>
@endcannot

中介層授權

// 在路由中使用中介層
Route::put('/posts/{post}', [PostController::class, 'update'])
    ->middleware('can:update,post');

Route::get('/posts/create', [PostController::class, 'create'])
    ->middleware('can:create,App\Models\Post');

// 自訂授權中介層
// app/Http/Middleware/CheckRole.php
class CheckRole
{
    public function handle(Request $request, Closure $next, string $role): mixed
    {
        if (!$request->user() || $request->user()->role !== $role) {
            abort(403, '未經授權。此區域需要角色:' . $role);
        }
        return $next($request);
    }
}

// 在 Kernel 中註冊
protected $routeMiddleware = [
    'role' => \App\Http\Middleware\CheckRole::class,
];

// 路由使用
Route::middleware(['auth', 'role:admin'])->group(function () {
    Route::get('/admin', [AdminController::class, 'index']);
});

Eloquent 安全性

大量指派保護

// 危險:$guarded = [] 允許所有欄位被大量指派
// 絕不要在生产环境中使用 $guarded = []

// 良好:白名單 fillable 屬性
final class User extends Authenticatable
{
    protected $fillable = [
        'name',
        'email',
        'phone',
        'avatar',
    ];
    // 絕不要加入 'role', 'is_admin', 'is_verified'
}

// 良好:在請求中明確控制哪些欄位可以被填充
public function store(StoreUserRequest $request): RedirectResponse
{
    $user = User::create($request->safe()->only([
        'name', 'email', 'phone', 'avatar'
    ]));
    // $request->safe() 僅使用驗證過的資料
    // $request->only() 若無驗證規則,本身並不安全
}

// 危險:直接用請求資料建立使用者
User::create($request->all()); // 易受大量指派攻擊!

// 較好:使用 DTO 進行建立
$user = User::create($request->validated()); // 僅使用驗證過的欄位

SQL 注入防範

// 良好:Eloquent 自動參數化查詢
User::where('email', $userInput)->first();
User::whereRaw('email = ?', [$userInput])->first();

// 良好:查詢建構器也會參數化
DB::table('users')->where('email', $userInput)->first();
DB::select('SELECT * FROM users WHERE email = ?', [$userInput]);

// 危險:原始字串插值
DB::select("SELECT * FROM users WHERE email = '{$userInput}'"); // 易受攻擊!
User::whereRaw("email = '{$userInput}'")->first(); // 易受攻擊!

// 危險:未跳脫輸入的 whereRaw/orderByRaw
User::orderByRaw($userInput); // 易受攻擊!
User::groupByRaw($userInput); // 易受攻擊!

// 危險:使用字串拼接的 DB::statement
DB::statement("INSERT INTO users (email) VALUES ('{$userInput}')"); // 易受攻擊!

屬性型別轉換

final class User extends Authenticatable
{
    protected $casts = [
        'email_verified_at' => 'datetime',
        'is_admin' => 'boolean', // 轉為布林可防止字串注入
        'settings' => 'array', // 自動 json_encode/json_decode
        'metadata' => 'encrypted:array', // Laravel 11+ 加密型別轉換
        'password' => 'hashed', // Laravel 10+ 設定時自動雜湊
    ];
}

模型安全性

final class User extends Authenticatable
{
    // 從 JSON/API 回應中隱藏敏感屬性
    protected $hidden = [
        'password',
        'remember_token',
        'two_factor_secret',
        'two_factor_recovery_codes',
    ];

    // 僅附加安全的計算屬性
    protected $appends = ['full_name']; // 安全
    // 絕不要附加敏感計算資料
}

final class Post extends Model
{
    // 全域範圍過濾軟刪除記錄
    use SoftDeletes;

    // 透過限制惰性載入來防止 N+1 問題 (選擇性嚴格模式)
    // AppServiceProvider::boot()
    // Model::preventLazyLoading(!app()->isProduction());
}

CSRF 防護

預設防護

// Laravel 透過 VerifyCsrfToken 中介層預設啟用 CSRF
// app/Http/Kernel.php (protected $middlewareGroups['web'])

// 所有 POST/PUT/PATCH/DELETE 表單都必須包含 @csrf
<form method="POST" action="/posts">
    @csrf
    <input type="text" name="title">
    <button type="submit">建立</button>
</form>

排除路由 (謹慎使用)

// app/Http/Middleware/VerifyCsrfToken.php
class VerifyCsrfToken extends Middleware
{
    // 僅排除那些已有外部 CSRF 防護的路由 (如 Webhook)
    protected $except = [
        'stripe/*', // Stripe Webhooks 使用自己的簽名驗證
        // 避免使用籠統的 'api/*' — 有狀態的 Sanctum 路由需要 CSRF。
        // 僅排除特定的無狀態 Webhook/端點路由。
    ];
}

使用 JavaScript 的 CSRF

<meta name="csrf-token" content="{{ csrf_token() }}">

<script>
// Axios 範例 (Laravel 內建 Axios)
axios.defaults.headers.common['X-CSRF-TOKEN'] = document.querySelector(
    'meta[name="csrf-token"]'
).getAttribute('content');

// Fetch 範例
fetch('/posts', {
    method: 'POST',
    headers: {
        'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
        'Content-Type': 'application/json',
    },
    body: JSON.stringify(data),
});
</script>

XSS 防範

Blade 模板安全性

{{-- 安全:會由 Blade 自動跳脫 --}}
{{ $userInput }}

{{-- 危險:原始輸出 — 絕不要對使用者輸入使用 --}}
{!! $userInput !!}

{{-- 安全:僅對您控制的受信任內容使用 {!! !!} --}}
{!! $trustedHtmlFromYourServer !!}

{{-- 良好:使用特定的跳脫指令 --}}
@js($data) {{-- 為 JavaScript 進行 JSON 編碼 --}}
@json($data) {{-- 在模板中進行 JSON 編碼 --}}

{{-- 危險:直接在原始 HTML 中使用使用者輸入 --}}
<div>{!! $user->bio !!}</div> {{-- 若使用者提供 bio 則有風險 --}}

安全 HTML 處理

// 當您必須允許部分 HTML 時,請使用白名單方法
use HTMLPurifier; // 需要:composer require ezyang/htmlpurifier

public function sanitizeHtml(string $dirty): string
{
    $config = \HTMLPurifier_Config::createDefault();
    $config->set('HTML.Allowed', 'p,b,i,a[href],ul,ol,li,br');
    $config->set('URI.AllowedSchemes', ['http', 'https', 'mailto']);
    $purifier = new \HTMLPurifier($config);
    return $purifier->purify($dirty);
}

// 在 Blade 中使用:
<div>{!! $sanitizedDescription !!}</div>

API 安全性

速率限制

// app/Http/Kernel.php
protected $middlewareGroups = [
    'api' => [
        'throttle:api',
        \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        // ...
    ],
];

// 在路由中使用自訂速率限制
Route::middleware(['auth:sanctum', 'throttle:100,1'])->group(function () {
    Route::get('/orders', [OrderController::class, 'index']);
});

// 定義速率限制器
// App\Providers\AppServiceProvider
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;

protected function configureRateLimiting(): void
{
    RateLimiter::for('api', function (Request $request) {
        return Limit::perMinute(100)->by($request->user()?->id ?: $request->ip());
    });

    RateLimiter::for('login', function (Request $request) {
        return Limit::perMinute(5)->by($request->input('email') . '|' . $request->ip());
    });
}

輸入驗證

// 對所有 API 端點使用 FormRequest
// app/Http/Requests/StoreOrderRequest.php
class StoreOrderRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true; // 在控制器中處理授權
    }

    public function rules(): array
    {
        return [
            'items' => 'required|array|min:1',
            'items.*.product_id' => 'required|integer|exists:products,id',
            'items.*.quantity' => 'required|integer|min:1|max:1000',
            'shipping_address' => 'required|string|max:500',
            'payment_method' => 'required|in:credit_card,paypal,stripe',
        ];
    }

    public function messages(): array
    {
        return [
            'items.*.product_id.exists' => '所選產品不存在。',
        ];
    }
}

// 在控制器中使用
public function store(StoreOrderRequest $request): JsonResponse
{
    $validated = $request->validated(); // 僅包含驗證過的資料
    $order = Order::create($validated);
    return response()->json($order, 201);
}

部署安全設定

伺服器配置

# .htaccess — 防止存取敏感檔案
<FilesMatch "\.(env|log|sql|sqlite)$">
    Require all denied
</FilesMatch>

<Files artisan>
    Require all denied
</Files>
# nginx 配置 — 隱藏 PHP 版本
server_tokens off;

# 防止存取 .env、儲存體等
location ~* \.(env|log|sql|sqlite)$ {
    deny all;
}

location /storage {
    # 僅允許存取上傳的檔案
    try_files $uri =404;
    location ~* \.php$ {
        deny all;
    }
}

# 安全標頭
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

安全性標頭中介層

// app/Http/Middleware/SecurityHeaders.php
class SecurityHeaders
{
    public function handle(Request $request, Closure $next): Response
    {
        $response = $next($request);

        $response->headers->set('X-Frame-Options', 'SAMEORIGIN');
        $response->headers->set('X-Content-Type-Options', 'nosniff');
        $response->headers->set('X-XSS-Protection', '1; mode=block');
        $response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin');

        // 內容安全性政策 (CSP)
        $response->headers->set('Content-Security-Policy', "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;");

        // 僅在必要時嚴格傳輸安全性 (HSTS) — 請先了解其影響
        if (app()->environment('production')) {
            $response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
        }

        return $response;
    }
}

// 在 Kernel 中註冊
protected $middleware = [
    \App\Http\Middleware\SecurityHeaders::class,
];

常見漏洞

不安全的重導向

// 危險:開放重導向
return redirect($request->input('redirect_url')); // 可能被導向到惡意網站

// 安全:限制重導向到應用程式內的 URL
return redirect()->intended('/dashboard'); // 僅允許驗證過的應用程式內路徑

// 安全:白名單重導向目標
$allowedDomains = ['example.com', 'app.example.com'];
$redirectTo = $request->input('redirect_url');
$host = parse_url($redirectTo, PHP_URL_HOST);

if (in_array($host, $allowedDomains, true)) {
    return redirect($redirectTo);
}

return redirect('/');

檔案上傳漏洞

// app/Http/Requests/UploadFileRequest.php
class UploadFileRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'avatar' => [
                'required',
                'image',
                'mimes:jpeg,png,jpg,gif,svg',
                'max:2048', // 最大 2MB
                function ($attribute, $value, $fail) {
                    // 驗證實際內容類型
                    $finfo = finfo_open(FILEINFO_MIME_TYPE);
                    $mimeType = finfo_file($finfo, $value->path());
                    finfo_close($finfo);

                    $allowedMimes = ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml'];
                    if (!in_array($mimeType, $allowedMimes)) {
                        $fail('檔案類型無效。');
                    }
                },
            ],
        ];
    }

    public function store(UploadFileRequest $request): RedirectResponse
    {
        // 以安全名稱儲存並防止覆寫
        $path = $request->file('avatar')->store('avatars', 'public');

        // 或使用自訂名稱
        $filename = time() . '_' . Str::random(10) . '.' . $request->file('avatar')->extension();
        $path = $request->file('avatar')->storeAs('avatars', $filename, 'public');

        auth()->user()->update(['avatar' => $path]);

        return back()->with('status', '頭像已更新!');
    }
}

除錯頁面暴露

// .env 檔案
APP_DEBUG=false // 生產環境:永遠為 false
APP_ENV=production

// bootstrap/app.php 中的原本檢查
$app->loadEnvironmentFrom('.env');
$app->withFacades();
$app->withEloquent();

// 當 APP_DEBUG 為 true 時,安全地記錄錯誤,但使用自訂例外處理器
// app/Exceptions/Handler.php
public function register(): void
{
    $this->reportable(function (Throwable $e) {
        // 記錄到您偏好的服務
        // Log::channel('slack')->report($e);
    });

    $this->renderable(function (NotFoundHttpException $e, Request $request) {
        if ($request->expectsJson()) {
            return response()->json(['message' => '記錄未找到。'], 404);
        }
        return response()->view('errors.404', [], 404);
    });
}

資料庫安全性

// 在 Schema 中使用唯讀資料庫使用者 (如適用)
// config/database.php
'connections' => [
    'mysql' => [
        'driver' => 'mysql',
        'read' => [
            'host' => env('DB_READ_HOST', env('DB_HOST', '127.0.0.1')),
        ],
        'write' => [
            'host' => env('DB_WRITE_HOST', env('DB_HOST', '127.0.0.1')),
        ],
        'sticky' => env('DB_STICKY', false),
        'database' => env('DB_DATABASE', 'forge'),
        'username' => env('DB_USERNAME', 'forge'),
        'password' => env('DB_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8mb4',
        'collation' => 'utf8mb4_unicode_ci',
        'prefix' => '',
        'prefix_indexes' => true,
        'strict' => true,
        'engine' => 'InnoDB', // 支援交易與外部鍵
        'options' => extension_loaded('pdo_mysql') ? array_filter([
            PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
        ]) : [],
    ],
],

// 遷移中的外部鍵約束
// database/migrations/create_posts_table.php
Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained()->onDelete('cascade');
    $table->string('title');
    $table->text('body');
    $table->timestamps();
});

// 資料層級安全性:永遠不要直接對使用者暴露 ID
// 對公開 ID 使用 UUID
Schema::create('posts', function (Blueprint $table) {
    $table->uuid('id')->primary();
    $table->foreignId('user_id')->constrained();
    $table->string('title');
    $table->text('body');
    $table->timestamps();
});

工具與資源

安全套件

# Laravel 專用安全工具
composer require --dev spatie/laravel-backtrace # 更好的例外處理
composer require --dev beyondcode/laravel-query-detector # N+1 查詢偵測
composer require --dev therobfonz/laravel-mandrill-errors # 郵件錯誤通知

# Laravel Debugbar (僅開發環境)
composer require --dev barryvdh/laravel-debugbar

# 授權審查
composer require --dev spatie/laravel-permission # 角色與權限管理

安全掃描

# 相依性安全檢查
composer audit # Laravel 10+/Composer 2.4+

# 使用本地安全掃描工具
composer require --dev enlightn/enlightn
php artisan enlightn

# 安全建議檢查
composer require --dev spatie/security-advisories

建議文章

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

相關技能