Fast, static, heuristic-based. Scan a Laravel project for insecure patterns, risky config, exposed secrets, and vulnerable dependencies — then ship a SARIF report to your CI pipeline.
Why lsec
Static analysis that understands Laravel conventions — fast enough to run on every commit.
Compiled Rust binary. No interpreter, no JVM warmup, no Docker pull. Scan a large Laravel app in seconds.
Rules understand Eloquent models, middleware stacks, config conventions, route definitions, and Blade templates.
Deterministic exit codes, SARIF output for GitHub Code Scanning, and baseline suppression for managing legacy findings.
Confidence scoring per finding. Filter out noise with --min-confidence or tune thresholds per rule in config.
Rule coverage
Each category targets a distinct security surface area of a Laravel application.
Installation
Grab the latest pre-built binary for your platform from GitHub Releases and drop it on your path — no runtime dependencies required.
# Linux (x86_64)
curl -L https://github.com/AfaanBilal/lsec/releases/latest/download/lsec-linux-x86_64.tar.gz | tar -xz
sudo mv lsec /usr/local/bin/
# Linux (ARM64)
curl -L https://github.com/AfaanBilal/lsec/releases/latest/download/lsec-linux-arm64.tar.gz | tar -xz
sudo mv lsec /usr/local/bin/
# macOS (Apple Silicon)
curl -L https://github.com/AfaanBilal/lsec/releases/latest/download/lsec-macos-arm64.tar.gz | tar -xz
sudo mv lsec /usr/local/bin/
# macOS (Intel)
curl -L https://github.com/AfaanBilal/lsec/releases/latest/download/lsec-macos-x86_64.tar.gz | tar -xz
sudo mv lsec /usr/local/bin/
# Windows — download lsec-windows-x86_64.zip from GitHub Releases and add to PATH
Requires a Rust toolchain.
git clone https://github.com/AfaanBilal/lsec
cd lsec
cargo build --release
cp target/release/lsec /usr/local/bin/lsec
# Or run directly without installing
cargo run -- scan /path/to/laravel-app
Usage
Run a scan, list rules, or manage baselines. All options can also be set in lsec.toml.
Scan completed. No findings at or above the configured failure threshold.
--ci was enabled and at least one finding met or exceeded --fail-on.
CLI or runtime error (invalid path, bad config, etc).
Used for --fail-on. Each level includes all levels above it.
Output formats
Switch between human-readable output, machine-parseable JSON, and SARIF for tooling integration.
Color-coded severity badges, two-column layout with location, explanation, remediation, and snippet context. Starts and ends with tabular summaries by severity and category.
lsec scan .
Machine-readable output with scan root, severity counts, category counts, and a full findings array including remediation text and confidence score. Ideal for custom tooling.
lsec scan . --format json \
--output report.json
Industry-standard format for security tool integrations. Supports GitHub Code Scanning, Azure DevOps, and IDE extensions. Includes tool metadata, rule definitions, and source locations.
lsec scan . --format sarif \
--output report.sarif
Configuration
Drop an lsec.toml in your project root to persist scan settings. Override with --config <path>.
# lsec.toml
[scan]
exclude_paths = ["vendor/", "tests/", "node_modules/", ".git/", "storage/logs/"]
fail_on = "high" # CI failure threshold: critical | high | medium | low | info
min_confidence = 0.7 # Global confidence floor (0.0 – 1.0)
[rules]
skip = ["logging"] # Skip entire categories
skip_ids = ["logging.debug-artifact"] # Skip specific rule IDs
# Per-rule confidence overrides (inline table — must stay on one line)
min_confidence_overrides = { "auth.missing-route-authorization" = 0.8, "logging.auth-failure-missing" = 0.55 }
# Custom secret detection patterns (regex)
custom_secrets_patterns = [
"(?i)internal_token\\s*=\\s*['\"][A-Za-z0-9_-]{20,}['\"]",
"(?i)acme_live_[A-Za-z0-9]{24,}"
]
exclude_paths — path prefixes excluded from the project walk.
fail_on — default CI severity threshold.
min_confidence — global confidence floor before reporting.
skip — suppress entire categories.
skip_ids — suppress individual rules by exact ID.
custom_secrets_patterns — add your own regex patterns for secret detection.
min_confidence_overrides — per-rule confidence floors.
CI Integration
Wire lsec into your pipeline in four steps. Works with GitHub Actions, GitLab CI, Bitbucket Pipelines, and any CI that supports shell commands.
Point it at the Laravel root. Use --ci to enable non-zero exit on findings.
Use --baseline ci/lsec-baseline.json to suppress accepted findings without silencing new ones.
Upload report.sarif as a build artifact or to GitHub Code Scanning for inline PR annotations.
Exit code 1 when any finding meets or exceeds --fail-on. Exit code 0 on clean scan.
# Full CI command
lsec scan . \
--ci \
--fail-on high \
--min-confidence 0.7 \
--baseline ci/lsec-baseline.json \
--format sarif \
--output lsec.sarif
Add this workflow to your Laravel project to get lsec findings as inline annotations on pull requests and in the repository's Security tab. Requires security-events: write permission. The upload step runs with if: always() so findings are visible even when the scan fails the job.
# .github/workflows/lsec.yml
name: lsec
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
security-events: write
jobs:
scan:
name: Security scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Download lsec
run: |
curl -fsSL https://github.com/AfaanBilal/lsec/releases/latest/download/lsec-linux-x86_64.tar.gz \
| tar -xz
chmod +x lsec
- name: Run lsec
run: |
./lsec scan . \
--ci \
--fail-on high \
--format sarif \
--output lsec.sarif
- name: Upload to GitHub Code Scanning
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: lsec.sarif
Baseline management
Baseline files let you acknowledge legacy issues without silencing future ones. Each entry is fingerprinted by rule, file, and line.
Captures all current findings into a JSON file. Future scans suppress any finding whose fingerprint appears in the baseline.
lsec baseline write .
# or during scan:
lsec scan . --write-baseline
After fixing findings, prune removes fingerprints that no longer match any active finding, keeping the baseline file clean.
lsec baseline prune .
Commit the baseline and reference it in your pipeline. New findings always surface; acknowledged ones stay quiet.
lsec scan . \
--baseline ci/lsec-baseline.json