| name | symfony-security-auditor |
| description | AI-powered multi-agent security auditor for Symfony applications using LLMs to detect business logic flaws, broken access control, and complex vulnerabilities |
| triggers | ["audit my Symfony application for security vulnerabilities","run Symfony security audit with AI","check for broken access control in Symfony","scan Symfony project for OWASP vulnerabilities","detect business logic flaws in my Symfony app","generate security report for Symfony using LLMs","find missing Voters and authorization issues","perform AI-powered penetration testing on Symfony"] |
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, .xml recursively
- 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.php for dev and test environments
- Creates
config/packages/symfony_security_auditor.yaml with defaults
Install an AI platform bridge
composer require symfony/ai-anthropic-platform
composer require symfony/ai-openai-platform
composer require symfony/ai-google-gemini-platform
composer require symfony/ai-mistral-platform
composer require symfony/ai-ollama-platform
Configure the AI platform
Create or edit config/packages/ai.yaml:
ai:
platform:
anthropic:
api_key: '%env(ANTHROPIC_API_KEY)%'
ai:
platform:
openai:
api_key: '%env(OPENAI_API_KEY)%'
ai:
platform:
google_gemini:
api_key: '%env(GOOGLE_GEMINI_API_KEY)%'
ai:
platform:
ollama:
base_url: 'http://localhost:11434'
Set environment variables in .env.local:
ANTHROPIC_API_KEY=sk-ant-api03-...
OPENAI_API_KEY=sk-proj-...
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'
Configuration
Basic configuration
Edit config/packages/symfony_security_auditor.yaml:
symfony_security_auditor:
model: 'claude-opus-4-8'
profile: 'balanced'
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
profile: 'fast'
profile: 'balanced'
profile: 'thorough'
Key Commands
Run security audit
bin/console audit:run
bin/console audit:run /path/to/project
bin/console audit:run --dry-run
bin/console audit:run --format console
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
bin/console audit:run --since=main
bin/console audit:run --generate-baseline
bin/console audit:run --baseline baseline.json
bin/console audit:run -v
bin/console audit:run -vv
bin/console audit:run -vvv
Exit codes
0 — no vulnerabilities found
1 — vulnerabilities found
2 — audit failed (error)
Real-World Usage Examples
Example 1: Basic security audit
composer require --dev vinceamstoutz/symfony-security-auditor
composer require symfony/ai-anthropic-platform
echo "ANTHROPIC_API_KEY=sk-ant-api03-..." >> .env.local
bin/console audit:run
Example 2: CI integration with SARIF output
bin/console audit:run \
--format sarif \
--output symfony-security.sarif \
--since=main
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
symfony_security_auditor:
attacker_model: 'claude-opus-4-8'
reviewer_model: 'claude-haiku-4'
profile: 'balanced'
bin/console audit:run --dry-run
bin/console audit:run
Example 4: Baseline workflow for existing projects
bin/console audit:run --generate-baseline
bin/console audit:run --baseline baseline.json
Example 5: HTML report for stakeholders
bin/console audit:run \
--format html \
--output security-report-$(date +%Y%m%d).html
Common Patterns
Pattern 1: GitHub Actions workflow
Create .github/workflows/security-audit.yml:
name: Security Audit
on:
schedule:
- cron: '0 2 * * *'
workflow_dispatch:
jobs:
audit:
runs-on: ubuntu-latest
permissions:
security-events: write
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
name: PR Security Audit
on: pull_request
jobs:
audit-diff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- 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:
model: 'claude-opus-4-8'
model: 'gpt-4o'
model: 'gemini-2.0-flash-exp'
model: 'mistral-large-latest'
model: 'llama3.1'
Issue: High API costs
Solution 1: Use split-model configuration:
symfony_security_auditor:
attacker_model: 'claude-opus-4-8'
reviewer_model: 'claude-haiku-4'
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
tokens_per_minute: 80000
Issue: Too many false positives
Solution 1: Use baseline suppression:
bin/console audit:run --generate-baseline
bin/console audit:run --baseline baseline.json
Solution 2: Increase review iterations:
symfony_security_auditor:
max_review_iterations: 3
Solution 3: Use a stronger reviewer model:
symfony_security_auditor:
reviewer_model: 'claude-opus-4-8'
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
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'
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
ollama pull llama3.1
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'
profile: 'thorough'
Issue: Cost estimation is inaccurate
Cause: Provider doesn't support prompt caching, or cache not warm.
Solution: Run --dry-run twice:
bin/console audit:run --dry-run
bin/console audit:run --dry-run
Advanced Features
Enable PoC generation for high-severity findings
symfony_security_auditor:
enable_poc_generation: true
poc_severity_threshold: 'HIGH'
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
{
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:
bin/console audit:run
bin/console audit:run
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.