Skip to main content

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.

The configuration scanner examines Laravel’s config/*.php files for hardcoded secrets, insecure defaults, and missing security flags that could compromise your application.

What it checks

The config-scanner performs 13 security checks across 8 configuration files:

All checks

Check IDFileIssueSeverity
CFG-001app.phpDebug mode hardcoded to trueHigh
CFG-002app.phpNon-standard encryption cipherMedium
CFG-003auth.phpPassword reset token expiry too longLow
CFG-004session.phpSession cookie missing HttpOnly flagHigh
CFG-005session.phpSession cookie missing Secure flagMedium
CFG-006session.phpSession cookie SameSite set to noneMedium
CFG-007session.phpSession lifetime excessively longLow
CFG-008mail.phpMail password hardcoded in configHigh
CFG-009cors.phpCORS allows all originsMedium
CFG-010cors.phpCORS allows credentials with wildcard originHigh
CFG-011database.phpDatabase password hardcoded in configHigh
CFG-012broadcasting.phpBroadcasting secret/key hardcodedMedium
CFG-013logging.phpSlack webhook URL hardcodedMedium

Implementation details

Extracted from internal/scanner/configscan/scanner.go:

Config files scanned

// scanner.go:31-43
checks := []struct {
    file  string
    check func(string) []models.Finding
}{
    {"app.php", s.checkApp},
    {"auth.php", s.checkAuth},
    {"session.php", s.checkSession},
    {"mail.php", s.checkMail},
    {"cors.php", s.checkCORS},
    {"database.php", s.checkDatabase},
    {"broadcasting.php", s.checkBroadcasting},
    {"logging.php", s.checkLogging},
}

Pattern matching

The scanner uses regex to find problematic configurations:
// scanner.go:66-79 - Debug mode check
if line, n := findPattern(lines, `'debug'\s*=>\s*true`); n > 0 {
    findings = append(findings, models.Finding{
        ID:          "CFG-001",
        Title:       "Debug mode hardcoded to true in app.php",
        Description: "config/app.php has 'debug' => true instead of reading from env().",
        Severity:    models.SeverityHigh,
        File:        "config/app.php",
        Line:        n,
        CodeSnippet: line,
        Remediation: "Use: 'debug' => env('APP_DEBUG', false),",
    })
}

Hardcoded credential detection

For mail, database, and broadcasting configs, Ward detects hardcoded credentials:
// scanner.go:205-221 - Mail password check
if line, n := findPattern(lines, `'password'\s*=>\s*'[^']{4,}'`); n > 0 {
    // Make sure it's not env()
    if !strings.Contains(line, "env(") {
        findings = append(findings, models.Finding{
            ID:          "CFG-008",
            Title:       "Mail password hardcoded in config",
            Description: "A mail password is hardcoded in config/mail.php instead of using env().",
            Severity:    models.SeverityHigh,
            Category:    "Secrets",
            CodeSnippet: strings.Replace(line, line, maskConfigValue(line), 1),
            Remediation: "Use: 'password' => env('MAIL_PASSWORD'),",
        })
    }
}

Critical checks

Session security (CFG-004, CFG-005, CFG-006)

Session cookies without proper flags are vulnerable to theft:
Without HttpOnly, JavaScript can access the session cookie via document.cookie, enabling theft through XSS attacks.
config/session.php
// Bad
'http_only' => false,

// Good
'http_only' => true,
Without Secure, the cookie is sent over plain HTTP, allowing session hijacking via network sniffing.
config/session.php
// Bad
'secure' => false,

// Good
'secure' => env('SESSION_SECURE_COOKIE', true),
Setting SameSite to ‘none’ allows the cookie to be sent with cross-site requests, weakening CSRF protection.
config/session.php
// Bad
'same_site' => 'none',

// Good
'same_site' => 'lax',  // or 'strict' for maximum protection

CORS misconfiguration (CFG-009, CFG-010)

Allowing all origins is dangerous, especially with credentials:
config/cors.php
// Bad - allows any website to make requests
'allowed_origins' => ['*'],
'supports_credentials' => true,  // CRITICAL: This combination is very dangerous

// Good - specify exact origins
'allowed_origins' => [env('FRONTEND_URL')],
'supports_credentials' => true,
Why it’s dangerous: Any malicious website can make authenticated requests to your API and steal user data.

Example findings

{
  "id": "CFG-004",
  "title": "Session cookie missing HttpOnly flag",
  "severity": "high",
  "category": "Configuration",
  "file": "config/session.php",
  "line": 145,
  "code_snippet": "'http_only' => false,",
  "remediation": "Set: 'http_only' => true,",
  "references": ["https://cwe.mitre.org/data/definitions/1004.html"]
}

Remediation guide

Move credentials to .env

config/database.php
// Before
'password' => 'my_secret_password',

// After
'password' => env('DB_PASSWORD', ''),
.env
DB_PASSWORD=my_secret_password

Fix session security

config/session.php
return [
    'http_only' => true,
    'secure' => env('SESSION_SECURE_COOKIE', true),
    'same_site' => 'lax',
    'lifetime' => 120,  // 2 hours
];

Fix CORS configuration

config/cors.php
return [
    'allowed_origins' => explode(',', env('CORS_ALLOWED_ORIGINS', 'https://example.com')),
    'allowed_methods' => ['GET', 'POST', 'PUT', 'DELETE'],
    'supports_credentials' => true,
];

Disabling checks

To disable specific config checks:
~/.ward/config.yaml
rules:
  disable:
    - CFG-007  # Allow long session lifetime
    - CFG-003  # Allow long password reset expiry