Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Eljakani/ward/llms.txt
Use this file to discover all available pages before exploring further.
Scanner Overview
Ward includes 4 built-in scanner types that run independently during the Scanners stage of the pipeline. Each scanner focuses on a specific security domain:env-scanner
.env files for misconfigurations and leaked secretsconfig-scanner
config/*.php for hardcoded credentials and insecure settingsdependency-scanner
rules-scanner
How Scanners Work
All scanners implement the same interface and follow a consistent pattern: Source:internal/models/scanner.go
Scanner Execution
- Receive shared context — Scanners get the
ProjectContextbuilt by resolvers - Perform checks — Each scanner runs its domain-specific security analysis
- Emit findings — Real-time via callback for TUI updates
- Return results — All findings as a slice
- Independence — Scanners don’t depend on each other; if one fails, others continue
env-scanner
Source:internal/scanner/env/scanner.go
Description
Checks.env and .env.example files for security misconfigurations, weak credentials, and accidentally committed secrets.
Checks Performed (8 rules)
ENV-001: Missing .env file
ENV-001: Missing .env file
.env file exists in the project root.Why it matters: While valid in containerized deployments, missing .env may indicate misconfiguration.Remediation:ENV-002: APP_DEBUG is enabled
ENV-002: APP_DEBUG is enabled
APP_DEBUG=true in .env.Why it matters: Debug mode exposes stack traces, database queries, and environment variables to end users. Critical information disclosure in production.Code check:ENV-003: Empty or missing APP_KEY
ENV-003: Empty or missing APP_KEY
APP_KEY is missing or empty.Why it matters: Laravel uses APP_KEY to encrypt cookies, sessions, and passwords. Without it, all encrypted data is insecure.Remediation:ENV-004: Weak or default APP_KEY
ENV-004: Weak or default APP_KEY
base64:AAAAAAA..., SomeRandomString, or keys shorter than 20 characters.Code check:ENV-005: Non-production APP_ENV
ENV-005: Non-production APP_ENV
APP_ENV set to local, development, or dev.Why it matters: Non-production environments may skip optimizations and enable debugging features.Remediation:ENV-006: Empty database password
ENV-006: Empty database password
DB_PASSWORD= (empty value).Why it matters: While valid for local development with trust authentication, it’s a risk in production.ENV-007: File sessions in production
ENV-007: File sessions in production
SESSION_DRIVER=file when APP_ENV=production.Why it matters: File sessions don’t scale across multiple servers and are slower than Redis/Memcached.Remediation:ENV-008: Real credentials in .env.example
ENV-008: Real credentials in .env.example
.env.example for sensitive keys:DB_PASSWORDMAIL_PASSWORDAWS_SECRET_ACCESS_KEYREDIS_PASSWORDPUSHER_APP_SECRET
.env.example is typically committed to version control. Real credentials here are exposed in Git history.Code check:Implementation Details
File parsing:config-scanner
Source:internal/scanner/configscan/scanner.go
Description
Analyzes allconfig/*.php files for hardcoded credentials, insecure defaults, and missing security flags.
Files Analyzed
Checks Performed (13 rules)
CFG-001: Debug mode hardcoded to true
CFG-001: Debug mode hardcoded to true
config/app.phpPattern: 'debug' => trueWhy it matters: Bypasses the .env setting, forcing debug mode even in production.Remediation:CFG-002: Non-standard encryption cipher
CFG-002: Non-standard encryption cipher
config/app.phpPattern: 'cipher' => '(?!AES-256-CBC)...'Remediation:CFG-003: Password reset token expiry too long
CFG-003: Password reset token expiry too long
config/auth.phpPattern: 'expire' => \d{3,} (≥100 minutes)Remediation:CFG-004: Session cookie missing HttpOnly flag
CFG-004: Session cookie missing HttpOnly flag
CFG-005: Session cookie missing Secure flag
CFG-005: Session cookie missing Secure flag
CFG-006: Session cookie SameSite set to none
CFG-006: Session cookie SameSite set to none
CFG-007: Session lifetime excessively long
CFG-007: Session lifetime excessively long
config/session.phpPattern: 'lifetime' => \d{4,} (≥1000 minutes)CFG-008: Mail password hardcoded
CFG-008: Mail password hardcoded
config/mail.phpPattern: 'password' => '[^']{4,}' (not using env())Code check:CFG-009: CORS allows all origins
CFG-009: CORS allows all origins
config/cors.phpPattern: 'allowed_origins' => ['*']Remediation:CFG-010: CORS credentials with wildcard origin
CFG-010: CORS credentials with wildcard origin
config/cors.phpWhy it matters: Combining supports_credentials => true with wildcard origins allows any website to make authenticated requests to your API.Remediation: Never use wildcard origins with credentials enabled.CFG-011: Database password hardcoded
CFG-011: Database password hardcoded
config/database.phpPattern: 'password' => '[^']{4,}' (not using env())CFG-012: Broadcasting secret/key hardcoded
CFG-012: Broadcasting secret/key hardcoded
config/broadcasting.phpPattern: '(secret|key)' => '[a-zA-Z0-9]{10,}' (not using env())CFG-013: Slack webhook URL hardcoded
CFG-013: Slack webhook URL hardcoded
config/logging.phpPattern: hooks.slack.com/services (not using env())Implementation Details
Pattern matching:dependency-scanner
Source:internal/scanner/dependency/scanner.go
Description
Performs live CVE database lookups via OSV.dev for all packages incomposer.lock. This scanner requires network access.
How It Works
Read composer.lock
ProjectContext.InstalledPackages map (populated by the Package Resolver).Identify vulnerable packages
Fetch full vulnerability details
- CVE ID and aliases
- Severity (Critical, High, Medium, Low)
- Affected version ranges
- Fixed version
- Advisory URLs
Finding Format
Example finding:Severity Mapping
Source:dependency/scanner.go:306-319
Performance Optimizations
Batch Queries
Two-Phase Lookup
Version Normalization
dev-main) that OSV.dev can’t match:Timeout Protection
Network Requirements
rules-scanner
Source:internal/scanner/rules/scanner.go
Description
Executes pattern-based security checks defined in YAML rule files. Ward ships with 40 default rules and supports custom rules.Rule Execution
Load rules
~/.ward/rules/*.yaml(default rules)- Custom directories specified in config
Resolve targets
target field:Predefined targets:php-files→ All.phpfiles (recursive, skipsvendor/)blade-files→resources/views/**/*.blade.phpconfig-files→config/*.phpenv-files→.env,.env.*routes-files→routes/*.phpmigration-files→database/migrations/*.phpjs-files→resources/js/**/*.{js,ts,jsx,tsx}
Scan files
- Read line by line
- Match against the pattern (regex or substring)
- Exclude lines matching
exclude_patternif specified - Record line number and code snippet
Handle negative patterns
negative: true, the rule triggers when the pattern is NOT found (useful for “must have X” checks).Pattern Types
- regex
- contains
- file-exists
DB::raw().Negative Patterns
Use case: Enforce that certain code patterns must be present. Example:Exclude Patterns
Use case: Reduce false positives by excluding safe contexts. Example:Implementation Details
File walking with exclusions:Default Rules Summary
Ward ships with 40 rules across 7 categories:Secrets (7 rules)
Secrets (7 rules)
- Hardcoded passwords in code
- AWS credentials
- API keys and tokens
- JWT secrets
- Database credentials
Injection (6 rules)
Injection (6 rules)
- SQL injection via
DB::raw()with interpolation - Command injection via
exec(),shell_exec() - Code injection via
eval() - Unsafe deserialization with
unserialize()
XSS (4 rules)
XSS (4 rules)
- Unescaped Blade output
{!! $var !!} - JavaScript injection in Blade
echowith user input
Debug (6 rules)
Debug (6 rules)
dd()anddump()callsvar_dump(),print_r()phpinfo()- Laravel Debugbar in production
Crypto (5 rules)
Crypto (5 rules)
- MD5/SHA1 for password hashing
rand()instead ofrandom_bytes()- Deprecated
mcryptfunctions - Base64 mistaken for encryption
Security Config (7 rules)
Security Config (7 rules)
- CORS wildcards
- SSL verification disabled
- CSRF middleware missing
- Mass assignment
$guarded = [] - Unsafe file upload extensions
Auth (5 rules)
Auth (5 rules)
- Missing authentication middleware
- Missing rate limiting
loginUsingId()without validation- Hardcoded admin checks
Scanner Configuration
Disable Scanners
File:~/.ward/config.yaml
Disable Individual Rules
Override Rule Severity
Add Custom Rule Directories
Scanner Independence
- Reliability: If one scanner fails, others continue
- Parallelization: Scanners could run concurrently (future enhancement)
- Modularity: Easy to add/remove scanners without affecting others
- Testing: Each scanner can be unit tested in isolation
Shared Dependencies
Scanners only depend on:- The immutable
ProjectContext(built by resolvers) - The
emitcallback (for real-time updates) - The
context.Context(for cancellation)
- Other scanners’ results
- Filesystem state (all paths are in
ProjectContext.RootPath) - Global state