symfony-security-auditor
AI-powered multi-agent security auditor for Symfony applications using LLMs to detect business logic flaws, broken access control, and complex vulnerabilities
How do I install this agent skill?
npx skills add https://github.com/reason-machines/security-skills --skill symfony-security-auditorIs this agent skill safe to install?
- Gen Agent Trust Hubpass
The skill provides an AI-powered security auditing tool that scans project source code and configuration files. It involves downloading third-party PHP packages and transmitting project data to external LLM providers (Anthropic, OpenAI, or Google) for analysis. While this is necessary for the skill's primary function, it results in the exposure of intellectual property to third-party services. Additionally, the tool is susceptible to indirect prompt injection, where malicious instructions hidden in audited code could potentially deceive the AI auditor.
- Socketpass
No alerts
- Snykpass
Risk: LOW · No issues
What does this agent skill do?
Symfony Security Auditor Skill
Skill by ara.so — Security Skills collection.
What It Does
symfony-security-auditor is an AI-powered multi-agent security auditor for Symfony applications that catches vulnerabilities traditional SAST tools miss:
- Business logic flaws — authorization bypasses, workflow violations
- Broken access control — missing
#[IsGranted], missing Voters, IDOR - Complex injection chains — multi-file SQL injection, XSS, deserialization
- Mass assignment — unsafe
MapRequestPayload, form handling - Symfony-specific issues — firewall misconfigurations, unsafe Twig, Messenger handler flaws
Uses a three-stage pipeline:
- Ingestion — scans
.php,.twig,.yaml,.xmlrecursively - Mapping — classifies Controllers, Entities, Voters, Forms, Routes
- Audit — adversarial Attacker agent finds issues, skeptical Reviewer agent eliminates false positives over up to 3 iterations
Outputs to console, JSON, SARIF (GitHub Code Scanning / GitLab Security Dashboard), or HTML.
Provider-agnostic via symfony/ai — works with Claude, GPT, Gemini, Mistral, Llama, DeepSeek, Ollama.
Installation
With Symfony Flex (automatic setup)
composer require --dev vinceamstoutz/symfony-security-auditor
Flex automatically:
- Registers the bundle in
config/bundles.phpfordevandtestenvironments - Creates
config/packages/symfony_security_auditor.yamlwith defaults
Install an AI platform bridge
# Anthropic Claude (recommended)
composer require symfony/ai-anthropic-platform
# Or OpenAI GPT
composer require symfony/ai-openai-platform
# Or Google Gemini
composer require symfony/ai-google-gemini-platform
# Or Mistral
composer require symfony/ai-mistral-platform
# Or Ollama (local)
composer require symfony/ai-ollama-platform
Configure the AI platform
Create or edit config/packages/ai.yaml:
# Anthropic Claude
ai:
platform:
anthropic:
api_key: '%env(ANTHROPIC_API_KEY)%'
# Or OpenAI GPT
ai:
platform:
openai:
api_key: '%env(OPENAI_API_KEY)%'
# Or Google Gemini
ai:
platform:
google_gemini:
api_key: '%env(GOOGLE_GEMINI_API_KEY)%'
# Or Ollama (local, no API key)
ai:
platform:
ollama:
base_url: 'http://localhost:11434'
Set environment variables in .env.local:
ANTHROPIC_API_KEY=sk-ant-api03-...
# Or
OPENAI_API_KEY=sk-proj-...
# Or
GOOGLE_GEMINI_API_KEY=...
Manual setup (without Flex)
Register bundles in config/bundles.php:
return [
// ...
Symfony\AI\AiBundle\AiBundle::class => ['all' => true],
VinceAmstoutz\SymfonySecurityAuditor\SymfonySecurityAuditorBundle::class => ['dev' => true, 'test' => true],
];
Create config/packages/symfony_security_auditor.yaml:
symfony_security_auditor:
model: 'claude-opus-4-8'
profile: 'balanced' # fast, balanced, or thorough
Configuration
Basic configuration
Edit config/packages/symfony_security_auditor.yaml:
symfony_security_auditor:
# Model name (provider-specific)
model: 'claude-opus-4-8' # or 'gpt-4o', 'gemini-2.0-flash-exp', etc.
# One-knob preset: fast, balanced (default), or thorough
profile: 'balanced'
# Manual tuning (overrides profile)
max_review_iterations: 2
enable_attacker_tools: true
enable_reviewer_tools: false
enable_poc_generation: false
enable_concurrent_review: false
enable_escalation: false
chunk_token_limit: 8000
enable_lean_prescan: false
Split-model configuration (cost optimization)
Use a powerful model for attack, cheap model for review:
symfony_security_auditor:
attacker_model: 'claude-opus-4-8'
reviewer_model: 'claude-haiku-4'
Cuts cost ~20× while maintaining high detection rate.
Rate limiting
symfony_security_auditor:
rate_limit:
requests_per_minute: 50
tokens_per_minute: 80000
Profiles explained
# Fast: minimal iterations, no tools, no PoC (~$0.50/project)
profile: 'fast'
# Balanced: 2 iterations, attacker tools, selective PoC (~$2-5/project)
profile: 'balanced'
# Thorough: 3 iterations, all tools, PoC for all high-severity (~$10-20/project)
profile: 'thorough'
Key Commands
Run security audit
# Audit current directory
bin/console audit:run
# Audit specific project
bin/console audit:run /path/to/project
# Dry run (estimate cost, no actual audit)
bin/console audit:run --dry-run
# Output formats
bin/console audit:run --format console # human-readable (default)
bin/console audit:run --format json --output report.json
bin/console audit:run --format sarif --output report.sarif
bin/console audit:run --format html --output report.html
# Diff mode (audit only changed files since branch)
bin/console audit:run --since=main
# Baseline suppression
bin/console audit:run --generate-baseline # creates baseline.json
bin/console audit:run --baseline baseline.json # suppress known findings
# Verbose output
bin/console audit:run -v # show progress
bin/console audit:run -vv # show API calls
bin/console audit:run -vvv # debug mode
Exit codes
0— no vulnerabilities found1— vulnerabilities found2— audit failed (error)
Real-World Usage Examples
Example 1: Basic security audit
# Install
composer require --dev vinceamstoutz/symfony-security-auditor
composer require symfony/ai-anthropic-platform
# Configure (add to .env.local)
echo "ANTHROPIC_API_KEY=sk-ant-api03-..." >> .env.local
# Run
bin/console audit:run
# Output:
# ┌─────────────────────────────────────────────────────────
# │ HIGH: Missing Authorization Check in Delete Action
# ├─────────────────────────────────────────────────────────
# │ File: src/Controller/PostController.php:42
# │ Category: Broken Access Control
# │
# │ The delete() method allows any authenticated user to
# │ delete any post without checking ownership.
# │
# │ Recommendation:
# │ Add #[IsGranted('POST_DELETE', 'post')] or create a Voter
# └─────────────────────────────────────────────────────────
Example 2: CI integration with SARIF output
# Generate SARIF for GitHub Code Scanning
bin/console audit:run \
--format sarif \
--output symfony-security.sarif \
--since=main
# Upload to GitHub
gh api repos/{owner}/{repo}/code-scanning/sarifs \
-F sarif=@symfony-security.sarif \
-F commit_sha=$(git rev-parse HEAD) \
-F ref=refs/heads/main
Example 3: Split-model configuration for cost savings
# config/packages/symfony_security_auditor.yaml
symfony_security_auditor:
attacker_model: 'claude-opus-4-8' # powerful, expensive
reviewer_model: 'claude-haiku-4' # fast, cheap
profile: 'balanced'
bin/console audit:run --dry-run
# Estimated cost: $2.34 (vs $45.67 with single Opus model)
bin/console audit:run
Example 4: Baseline workflow for existing projects
# First run: generate baseline of known issues
bin/console audit:run --generate-baseline
# This creates baseline.json with all findings
# Review and accept known issues, then commit baseline.json
# Subsequent runs: only report new issues
bin/console audit:run --baseline baseline.json
# Exit code 0 if only baseline findings
# Exit code 1 if new findings detected
Example 5: HTML report for stakeholders
bin/console audit:run \
--format html \
--output security-report-$(date +%Y%m%d).html
# Generates self-contained HTML report with:
# - Executive summary
# - Findings grouped by severity
# - File/line locations
# - Recommendations
# - PoCs (if enabled)
Common Patterns
Pattern 1: GitHub Actions workflow
Create .github/workflows/security-audit.yml:
name: Security Audit
on:
schedule:
- cron: '0 2 * * *' # nightly at 2 AM
workflow_dispatch:
jobs:
audit:
runs-on: ubuntu-latest
permissions:
security-events: write # for SARIF upload
contents: read
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
- run: composer install --no-dev
- uses: vinceamstoutz/symfony-security-auditor@1.10.0
with:
format: sarif
output: symfony-security.sarif
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: symfony-security.sarif
category: symfony-security-auditor
Pattern 2: GitLab CI pipeline
Create .gitlab-ci.yml:
security_audit:
stage: test
image: php:8.3
script:
- composer install --dev
- bin/console audit:run --format sarif --output symfony-security.sarif
artifacts:
reports:
sast: symfony-security.sarif
variables:
ANTHROPIC_API_KEY: $ANTHROPIC_API_KEY
only:
- schedules
Pattern 3: Pull request diff audit
# .github/workflows/pr-audit.yml
name: PR Security Audit
on: pull_request
jobs:
audit-diff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history for --since
- uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
- run: composer install --dev
- name: Audit changed files
run: |
bin/console audit:run \
--since=origin/${{ github.base_ref }} \
--format json \
--output audit.json
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
- name: Comment on PR
if: failure()
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const audit = JSON.parse(fs.readFileSync('audit.json'));
const comment = `## 🔒 Security Audit Found Issues\n\n${audit.summary}`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
Pattern 4: Programmatic usage in PHP
<?php
namespace App\Service;
use VinceAmstoutz\SymfonySecurityAuditor\Application\Service\AuditOrchestrator;
use VinceAmstoutz\SymfonySecurityAuditor\Domain\ValueObject\AuditOptions;
class SecurityAuditService
{
public function __construct(
private AuditOrchestrator $orchestrator
) {}
public function auditProject(string $projectPath): array
{
$options = new AuditOptions(
projectPath: $projectPath,
format: 'json',
dryRun: false,
since: null,
baseline: null
);
$result = $this->orchestrator->execute($options);
return [
'vulnerabilities' => $result->getVulnerabilities(),
'summary' => $result->getSummary(),
'cost' => $result->getCost(),
];
}
}
Pattern 5: Custom vulnerability filters
<?php
namespace App\Security;
use VinceAmstoutz\SymfonySecurityAuditor\Domain\Model\Vulnerability;
class VulnerabilityFilter
{
public function filterCritical(array $vulnerabilities): array
{
return array_filter(
$vulnerabilities,
fn(Vulnerability $v) => $v->getSeverity() === 'CRITICAL'
);
}
public function filterByCategory(array $vulnerabilities, string $category): array
{
return array_filter(
$vulnerabilities,
fn(Vulnerability $v) => $v->getCategory() === $category
);
}
public function excludeAccepted(array $vulnerabilities, array $acceptedIds): array
{
return array_filter(
$vulnerabilities,
fn(Vulnerability $v) => !in_array($v->getId(), $acceptedIds)
);
}
}
Troubleshooting
Issue: "Model not found" error
Cause: Incorrect model name for the provider.
Solution: Check provider-specific model names:
# Anthropic Claude
model: 'claude-opus-4-8' # or 'claude-sonnet-4', 'claude-haiku-4'
# OpenAI
model: 'gpt-4o' # or 'gpt-4-turbo', 'gpt-3.5-turbo'
# Google Gemini
model: 'gemini-2.0-flash-exp' # or 'gemini-1.5-pro'
# Mistral
model: 'mistral-large-latest' # or 'mistral-small-latest'
# Ollama (local)
model: 'llama3.1' # or 'codellama', 'deepseek-coder'
Issue: High API costs
Solution 1: Use split-model configuration:
symfony_security_auditor:
attacker_model: 'claude-opus-4-8'
reviewer_model: 'claude-haiku-4' # ~20× cheaper
Solution 2: Enable lean prescan to drop low-risk files:
symfony_security_auditor:
enable_lean_prescan: true
Solution 3: Use fast profile for initial scans:
symfony_security_auditor:
profile: 'fast'
Solution 4: Audit only changed files:
bin/console audit:run --since=main
Issue: Rate limit errors (429)
Solution: Configure rate limits:
symfony_security_auditor:
rate_limit:
requests_per_minute: 50 # adjust per provider limits
tokens_per_minute: 80000
Issue: Too many false positives
Solution 1: Use baseline suppression:
bin/console audit:run --generate-baseline
# Review baseline.json, remove false positives
bin/console audit:run --baseline baseline.json
Solution 2: Increase review iterations:
symfony_security_auditor:
max_review_iterations: 3 # more iterations = fewer false positives
Solution 3: Use a stronger reviewer model:
symfony_security_auditor:
reviewer_model: 'claude-opus-4-8' # instead of haiku
Issue: Missing vulnerabilities
Solution 1: Enable all detection features:
symfony_security_auditor:
profile: 'thorough'
enable_attacker_tools: true
enable_reviewer_tools: true
Solution 2: Increase chunk token limit for complex files:
symfony_security_auditor:
chunk_token_limit: 16000 # default is 8000
Solution 3: Disable lean prescan:
symfony_security_auditor:
enable_lean_prescan: false
Issue: Audit runs slowly
Solution 1: Enable concurrent review:
symfony_security_auditor:
enable_concurrent_review: true
Solution 2: Use faster models:
symfony_security_auditor:
model: 'claude-haiku-4' # or 'gpt-4o-mini', 'gemini-2.0-flash-exp'
Solution 3: Reduce review iterations:
symfony_security_auditor:
max_review_iterations: 1
Issue: SARIF upload fails on GitHub
Cause: Missing security-events: write permission.
Solution: Add permission to workflow:
permissions:
security-events: write
contents: read
Issue: Ollama connection refused
Cause: Ollama server not running.
Solution: Start Ollama server:
ollama serve
# In another terminal, pull model
ollama pull llama3.1
# Then run audit
bin/console audit:run
Issue: "No findings" on project with known vulnerabilities
Cause: Model not sophisticated enough, or context window too small.
Solution: Use a more powerful model:
symfony_security_auditor:
model: 'claude-opus-4-8' # best detection rate
profile: 'thorough'
Issue: Cost estimation is inaccurate
Cause: Provider doesn't support prompt caching, or cache not warm.
Solution: Run --dry-run twice:
# First run: no cache
bin/console audit:run --dry-run
# Estimated: $12.50
# Second run: cache warm (Anthropic only)
bin/console audit:run --dry-run
# Estimated: $1.80 (90% input tokens cached)
Advanced Features
Enable PoC generation for high-severity findings
symfony_security_auditor:
enable_poc_generation: true
poc_severity_threshold: 'HIGH' # HIGH or CRITICAL
Output includes concrete reproduction steps:
{
"poc": {
"type": "curl",
"command": "curl -X DELETE https://app.example.com/api/posts/123 -H 'Authorization: Bearer USER_TOKEN'",
"expected": "Post deleted without ownership check"
}
}
Custom advisory feeds
Implement AdvisoryProviderInterface:
<?php
namespace App\Security;
use VinceAmstoutz\SymfonySecurityAuditor\Domain\Service\AdvisoryProviderInterface;
class CustomAdvisoryProvider implements AdvisoryProviderInterface
{
public function lookup(string $package, string $version): ?array
{
// Query your internal vulnerability database
return [
'id' => 'INTERNAL-2024-001',
'title' => 'Custom vulnerability',
'severity' => 'HIGH',
];
}
}
Register in services.yaml:
services:
App\Security\CustomAdvisoryProvider:
decorates: VinceAmstoutz\SymfonySecurityAuditor\Domain\Service\AdvisoryProviderInterface
Content-hash caching
Automatically enabled — identical code chunks skip LLM:
# First run
bin/console audit:run
# 50 chunks analyzed, cost: $5.00
# No code changes
bin/console audit:run
# 50 chunks cached, cost: $0.00
Cache stored in var/cache/dev/symfony_security_auditor/.
Tip: For best results, combine this auditor with PHPStan (type safety), Psalm Security (taint analysis), and Dependabot (dependency CVEs). This auditor excels at business logic flaws that static analysis cannot detect.
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/reason-machines/security-skills/symfony-security-auditor">View symfony-security-auditor on skillZs</a>