Source audit (Code Scan)
The second engine: SiteCMD walks your linked project folder and audits the source for the issues a live-site scan can't see.
Most “site health” tools see only what you shipped. They can tell you a meta tag is broken; they can’t tell you that the template generating it has a typo. They can tell you a page is slow; they can’t tell you a React effect is running on every render.
SiteCMD’s source audit runs against your project folder, locally, and surfaces the issues that don’t appear in a live-site scan. It’s the second engine that runs when you click Run Scan, provided you’ve linked a source folder.
When it runs
Link a project folder when you create the project (or any time after, from project settings), and the source audit runs as part of every scan. If no folder is linked, this stage is skipped automatically.
Everything happens locally:
- The audit reads files from the linked folder
- The analysis runs on your machine
- Results are written to the local SiteCMD database
- Nothing about your source code leaves your machine
The one exception is dependency lookups: the supply-chain stage queries public registries (npm, PyPI, packagist, crates.io) for known-bad versions. Those requests send package names and versions only, never your source.
What the audit looks for
The audit runs in five phases, each focused on a different class of problem.
1. Collect files
SiteCMD walks your project root. It needs at least one recognizable marker:
package.jsonsrc/app/pages/functions/schema/config/
If none of those exist, the audit stops and asks you to point at a different folder. This guards against accidentally running against a download folder, a desktop, or some other location that isn’t actually a project root.
The walker is filesystem-bounded: it canonicalizes the path, then verifies the result stays under your home directory. Symlinks that try to redirect the walk into system paths are rejected. The audit cannot be tricked into reading files outside the project folder you linked.
2. Analyze source
Per-file static analysis, looking for:
- Vibe-code anti-patterns. Code that smells AI-generated: variables named
xyz, the same useEffect copy-pasted seven times, error handling that just swallows the exception, fetch calls in render bodies, magic numbers everywhere. - AI-generated code issues. Patterns specific to AI-written code: stale comments that no longer match the code, function names that don’t reflect what the function does, half-finished implementations marked TODO that ship anyway.
- Exposed secrets. API keys hard-coded as string literals, JWTs committed to source, database connection strings with credentials in them.
- Unsafe queries. SQL string concatenation, raw-HTML rendering with non-trivial input, eval’d input, command injection patterns.
- Auth gaps. Routes that should be auth-gated but aren’t, password-handling code that doesn’t hash properly, session cookies missing
HttpOnlyorSecure. - Missing observability. Error throw paths with no logging, async functions with no error handler, fetch failures silently swallowed.
This phase is where most findings come from on the first scan of a real project.
3. Supply chain
Dependency lockfile analysis across ecosystems:
| Ecosystem | Lockfile |
|---|---|
| npm | package-lock.json, yarn.lock, pnpm-lock.yaml |
| Python (pip) | requirements.txt, Pipfile.lock, poetry.lock |
| Composer (PHP) | composer.lock |
| Cargo (Rust) | Cargo.lock |
| Go | go.sum |
| Ruby | Gemfile.lock |
| Drupal | composer.json with Drupal markers |
| WordPress | wp-includes/version.php and plugin headers |
Each package version is checked against the relevant public registry. Findings include:
- Known-bad versions with security advisories
- Major releases behind current (with the gap quantified)
- Abandoned packages (no release in 2+ years)
- Packages flagged by the maintainer as deprecated
The registry lookups send package names and versions only. Your package.json itself, your source files, your lock contents — none of those are uploaded.
4. Operations
Project-level checks that look at how the codebase is set up:
- Deploy config. Missing
Procfile,vercel.json,netlify.toml, or whatever your hosting platform needs. Misconfigured environment variables. - Error handling. Global error handlers present, unhandled promise rejection paths, missing
try/catcharound critical sections. - Operational gaps. No
.env.examplefor new developers, noREADMEof any kind, hard-coded URLs that should be env vars. - Database safety. Migration files that drop columns without backfill, schema drift between models and migrations.
- Framework-specific risks. Things like Next.js API routes without rate limiting, Django middleware missing auth checks, Rails controllers using strong parameters incorrectly.
5. Finalize
After all four analysis phases, the results are normalized:
- Severities are unified across detectors (so a “high” from one detector means the same thing as a “high” from another)
- Findings are sorted by severity, then by file path, then by title
- Duplicates are removed (same finding ID matched in multiple ways)
- Framework-specific overrides apply (e.g., a Next.js auth check that’s actually handled by middleware doesn’t fire as a finding)
The final list lands in the Issues view, merged with the live-site findings into one ranked list.
Risk categories
Source-audit findings get classified into risk categories that overlap with live-site findings but include some source-specific ones:
| Category | What it covers |
|---|---|
| Security | Exposed secrets, auth gaps, unsafe queries |
| Database | Schema drift, unsafe migrations, query risks |
| Dependencies | Lockfile findings, abandoned packages, CVEs |
| AI safety | Patterns suggesting unverified AI-generated code in critical paths |
| Architecture | Half-finished implementations, dead code in production paths, tight coupling that breaks fast |
| Reliability | Missing error handling, missing observability, operational gaps |
These line up with the categories shown in The SiteCMD Score.
Findings by tier
The source audit runs on every tier. What changes with tier:
- Free: Score, count, severity distribution. You see how many critical/high/medium/low findings there are; you don’t see the details.
- Core and above: Full issue detail, fix guides, AI fix prompts, and the ability to mirror findings to GitHub Issues or Jira.
This means Free is useful for “is my project in good shape or in trouble?” but Core is needed to actually work through the findings.
Big projects
For a small project (a few thousand source files), the audit finishes in seconds. For a large monorepo, it takes proportionally longer because the walk is doing real file I/O.
If your audit is slow on a monorepo where you only care about one app’s source, link the specific subdirectory rather than the monorepo root. The audit’s project-root detection accepts any folder that has the marker files; you don’t have to point at the top level.
What the audit does not do
- It does not run your code. This is static analysis. SiteCMD doesn’t spawn your build, doesn’t execute scripts, doesn’t run your tests.
- It does not modify your files. The audit is read-only. No code is rewritten, no files are created in your project (other than what
sitecmd initadds with your consent for CLI usage). - It does not replace a security audit. Some checks overlap with what a security review would catch, but the audit is not a substitute for actual review of an application that handles sensitive data.
- It does not depend on a git repo. SiteCMD walks the filesystem, not git history. If your project isn’t tracked in git (or is in a different VCS), the audit still works.