Every time I inherit a legacy PHP app — a CodeIgniter admin panel, an old Laravel service, a WordPress site someone's cousin built — day one is the same ritual: grep for password, squint at config.php, wonder if display_errors is on in prod, and hope there isn't a hardcoded API key waiting to ruin my week.
So I built a tool to do that first pass for me, in one command, offline. It's called Observer, it's a single Go binary, and it's free and MIT.
observer analyze ./your-app --out report.html
Point it at a folder, get one self-contained HTML report. No server, no account, no instrumentation, nothing sent anywhere.
What it actually found
I ran it against a real CodeIgniter 3 admin app I'd picked up. A few seconds later:
Project: admin-panel
Language: PHP
Framework: CodeIgniter 3 [High]
Database: MySQL [High]
Security score: 81/100 (B) Code health: 100/100 (A)
Static analysis: issues across secrets, config & dependencies
[High] application/config/firebase.php Hardcoded Google API key
[High] index.php display_errors enabled
[Med ] composer.json End-of-life PHP version
None of these are exotic. That's the point — the boring, high-impact stuff is exactly what gets missed on a handover, and it's what an attacker finds first. A hardcoded key in a config file that's sitting in the repo is a bad afternoon waiting to happen.
It doesn't just flag — it shows the fix
This is the part I care about most. Most free scanners hand you a wall of findings and leave you to Google each one. Every Observer finding carries a concrete before → after fix, right in the report — no AI key required, fully offline:
// Before
$db->query("SELECT * FROM users WHERE id = " . $id);
// After
$db->query("SELECT * FROM users WHERE id = ?", [$id]);
Each finding also gets a severity, a file:line, and a CWE/OWASP tag, so you can triage instead of just staring.
What it checks
- Security rules across PHP, JS/TS, Python, Java & Ruby — hardcoded secrets, SQL injection, XSS, command execution, insecure deserialization, weak crypto, dangerous config
-
Dependency CVEs via OSV.dev (
--cve) — Composer, npm, PyPI, Go - A Security score and a Code-Health score (A–F) plus an estimated fix effort
- SARIF / JSON / CSV output + a GitHub Action, so it drops into CI
- It also auto-detects Semgrep / PHPStan / Bandit / gosec if you already have them, and folds their findings into the same report
Offline by default (and provably so)
No telemetry, no phone-home. The only things that touch the network are explicitly opt-in (--cve, or --ai with your own OpenAI key). For regulated or client-confidential work there's a flag that makes it enforceable:
observer analyze ./client-app --assert-offline
# Offline mode: no network I/O.
It refuses any network-touching option and keeps the AI on a local heuristic. Handy when you're auditing someone else's code under NDA and the code genuinely cannot leave the machine.
What it's not
It's not trying to replace SonarQube, Snyk, or Sentry. Those go deep in one dimension and want a server, a cloud account, or instrumentation. Observer is the opposite shape: a zero-setup, offline snapshot for the moments those are too heavy — a legacy handover, a quick client audit, an air-gapped scan, or just "what's wrong with this thing I just cloned?" Run both; they answer different questions.
Try it / tell me what it misses
It's genuinely free and MIT — grab a binary and point it at any repo:
👉 https://github.com/sanks205/getobserver
There are a few optional one-time paid add-ons (branded PDF reports, scheduled scans, deeper framework rule packs), but the whole core scanner is free with no account.
This is early, and I'd really value feedback from people who work on older codebases: what did it flag that was noise? What rule would've actually saved you an afternoon? Drop a comment — that's what I'm building from next.
Top comments (0)