1 · Static audit — code, dependencies, git
Objective — run the fast, deterministic checks that need no browser (project structure, Composer security audit, git hygiene, code-quality/secrets scan) so later audits start from a known-clean base.
Steps at a glance:
- Verify project structure — Confirm the 9 core Laravel directories,
bootstrap/cache/, and required files exist; identify CodeCanyon custom directories (Modules/,packages/,uploads/) forZaj-CUSTOMIZATIONS.md. - Composer security audit — Validate the manifest, scan for advisories, confirm autoload.
- Audit git hygiene —
vendor/andnode_modules/must NOT be tracked; lock files MUST be. - Scan code quality & secrets — PHP syntax, hardcoded secrets,
APP_DEBUG,.htaccessheaders,env()usage. - Review & commit fixes — Stage deliberately, confirm no
.env/credentials are staged, commit with a descriptive message, push. - Run the SHOULD companions — Two SHOULD companions deepen this: database migration analysis (count
migrations, confirm core tables, map custom-table vendor dependencies) and storage FVDUT classification
(categorize every storage path so
deploy.phpshared_dirsnever overwrites real user uploads).
Background
Section titled “Background”These are the fast, deterministic checks that need no browser. Run them first so later audits (security, performance, functional QA) start from a known-clean base — a passing static audit is what makes every deep audit downstream trustworthy.
For the authoritative debug + git-history secret scan (word-boundary dd(), git log value patterns), use the staging deep pass on Phase 5 · Deep codebase audit — this page is the pre-launch re-verify, not a weaker duplicate.
flowchart LR Static[Static audit this page] --> Sec[Security audit] Sec --> Perf[Performance audit] Perf --> Func[Functional QA] Func --> Sign[Launch sign-off]1. Verify project structure
Section titled “1. Verify project structure”Confirm the 9 core Laravel directories, bootstrap/cache/, and required files exist; identify CodeCanyon custom directories (Modules/, packages/, uploads/) for Zaj-CUSTOMIZATIONS.md.
-
Check every core directory and create the cache dir if missing.
Terminal window for dir in app bootstrap config database public resources routes storage tests; do[ -d "$dir" ] && echo "OK $dir/" || echo "MISSING $dir/"done[ -d "bootstrap/cache" ] || mkdir -p bootstrap/cache && chmod 775 bootstrap/cache# Expected: "OK" for each core dir; bootstrap/cache exists at 775- ✅ Each core directory prints
OK;bootstrap/cache/exists; custom dirs noted forZaj-CUSTOMIZATIONS.md.
- ✅ Each core directory prints
2. Composer security audit
Section titled “2. Composer security audit”Validate the manifest, scan for advisories, confirm autoload.
-
Validate the manifest, scan advisories, flag abandoned packages, and confirm autoload.
Terminal window composer validate --no-interaction --strict # Expected: composer.json is validif composer audit --help >/dev/null 2>&1; thencomposer audit --no-interaction --format=json --abandoned=report > /tmp/composer-audit.jsonjq '.advisories | length, (.abandoned // {}) | length' /tmp/composer-audit.jsoncomposer audit --no-interaction --abandoned=failelseecho "SKIP: composer audit needs Composer 2.4+ — upgrade Composer or run: composer require --dev roave/security-advisories:dev-latest"fi[ -f vendor/autoload.php ] || composer dump-autoload# Expected: manifest valid, zero advisories, zero abandoned packages, autoload present- ✅
composer.jsonis valid, no security advisories, no abandoned packages,vendor/autoload.phppresent.
- ✅
-
Re-verify the vendor seam is still clean — a pre-launch backdoor re-scan of the live
vendor/tree, in case a latercomposer require/updatere-pulled a tampered package or a restore hook re-introduced a stripped beacon. This re-runs the same signature scan from Phase 2 · Extract & snapshot §5 as a verification, not a first pass.Terminal window # Backdoor-signature re-scan over the live vendor/ (focus on the framework core first)grep -rEl 'getCourant|HeaderCodec|envato\.|verify\.js' \vendor/laravel/framework vendor/symfony vendor/illuminate 2>/dev/null \&& echo "🔴 CRITICAL: backdoor signature present in vendor core — do NOT launch; re-clean per Phase 2 §5.5" \|| echo "OK no backdoor signature in vendor core"grep -rEln 'chr\([0-9]|gzinflate|gzuncompress|str_rot13\(|\$\.getScript|->name *== *["'\'']\s*(login|register)' \vendor/laravel/framework vendor/symfony 2>/dev/null \| head -10 || echo "OK no obfuscation/injection signatures in vendor core"# Expected: both print OK. Any hit = a tampered package survived → clean upstream before launch.- ✅ No backdoor/obfuscation/injection signature survives in
vendor/core; any hit is cleaned viacomposer reinstall(notcomposer install) and re-scanned toOK.
- ✅ No backdoor/obfuscation/injection signature survives in
3. Audit git hygiene
Section titled “3. Audit git hygiene”vendor/ and node_modules/ must NOT be tracked; lock files MUST be.
-
Confirm dependency trees are untracked and lock files are tracked.
Terminal window git ls-files vendor/ node_modules/ # Expected: emptygit ls-files composer.lock package-lock.json # Expected: both listed- ✅
vendor//node_modules/print nothing;composer.lock+package-lock.jsonare listed.
- ✅
-
Verify the 12 framework
.gitignorefiles exist, and auto-create any that are missing (so emptystorage//cachedirs persist across a clean clone).Terminal window GITIGNORE_FILES=(".gitignore""database/.gitignore""bootstrap/cache/.gitignore""storage/app/.gitignore""storage/app/public/.gitignore""storage/framework/.gitignore""storage/framework/cache/.gitignore""storage/framework/cache/data/.gitignore""storage/framework/sessions/.gitignore""storage/framework/testing/.gitignore""storage/framework/views/.gitignore""storage/logs/.gitignore")for file in "${GITIGNORE_FILES[@]}"; do[ -f "$file" ] && echo "OK $file" || echo "MISSING $file"done# Idempotent auto-create for the storage/* set (safe to re-run)for dir in storage/app storage/app/public storage/framework \storage/framework/cache storage/framework/cache/data \storage/framework/sessions storage/framework/testing \storage/framework/views storage/logs; doif [ ! -f "$dir/.gitignore" ]; thenmkdir -p "$dir"printf '*\n!.gitignore\n' > "$dir/.gitignore"echo "Created $dir/.gitignore"fidone- ✅ All 12
.gitignorefiles printOK(any missing storage-dir ignore is auto-created).
- ✅ All 12
-
Sweep storage tracking and ignore rules. CodeCanyon apps often ship upload/log/cache folders inside
storage/; only intentional seed/demo assets should be tracked.Terminal window git ls-files storage/ bootstrap/cache/ public/storage/ public/uploads/find storage -maxdepth 3 -name .gitignore -print -exec sed -n '1,40p' {} \;# Expected: no live logs/cache/uploads tracked; .gitignore keeps folders but ignores mutable contents- ✅ No live user uploads, logs, cache files, or symlink targets are tracked; folder-keeper
.gitignorefiles are intentional.
- ✅ No live user uploads, logs, cache files, or symlink targets are tracked; folder-keeper
-
Confirm the per-env symlinks and install marker stay out of Git.
public/storage(andpublic/packagesfor in-tree module apps) are per-env symlinks rebuilt byphp artisan storage:link/ the packages link — vendors frequently shippublic/storageas an absolute symlink to a dead server path (/var/www/...), which breaks/storage/*on every other environment.storage/installedis per-env runtime state (like.env): it exists on each installed env, but a repo-baked marker pre-seeds a fresh server and silently skips the installer.Terminal window # These must be gitignored, never tracked:git ls-files public/storage public/packages storage/installed \&& echo "⚠️ a per-env symlink or install marker is TRACKED — untrack + gitignore it" \|| echo "OK per-env symlinks / install marker untracked"# Spot the dead-absolute-symlink trap on the live tree:[ -L public/storage ] && { tgt=$(readlink public/storage); case "$tgt" in/var/www/*|/home/*/*) echo "⚠️ public/storage → '$tgt' (likely a dead server path — relink: rm public/storage && php artisan storage:link)";;*) echo "OK public/storage → '$tgt'";; esac; }# Expected: nothing tracked; public/storage resolves to this env's storage/app/public, not a foreign server path.- ✅
public/storage,public/packages, andstorage/installedare absent from Git and gitignored;public/storageresolves to this env’sstorage/app/public(not a foreign/var/www/...path).
- ✅
4. Scan code quality & secrets
Section titled “4. Scan code quality & secrets”PHP syntax, hardcoded secrets, APP_DEBUG, .htaccess headers, env() usage.
-
Compile routes, scan source + history for secrets, and assert debug is off.
Terminal window php artisan route:list > /dev/null 2>&1 && echo "OK routes compile"# Real config/code — not just .env.example placeholdersgrep -rEn "(sk_live_|sk_test_[a-zA-Z0-9]{20,}|base64:[A-Za-z0-9+/=]{20,})" app/ config/ --include="*.php" \| grep -vE 'example|placeholder|YOUR_' || true # Expected: emptygrep -rqE '\bdd\s*\(' app/ Modules/ packages/ --include="*.php" \&& echo "WARN: dd() found in source" || echo "OK no dd()"grep -q '^APP_DEBUG=false' .env.example && echo "OK .env.example debug off"git log --all -p -- ':!.env.example' -- '*.env*' '*.yml' '*.yaml' '*.json' '*.sh' \| grep -Ei '(sk_live_|password\s*=\s*[^Y<]|api[_-]?key\s*=\s*[a-zA-Z0-9]{16,})' \&& echo "WARN: possible secret in history" || echo "OK history scan clean"- ✅ Routes compile; no live secret patterns in
app//config/; nodd()in source;.env.exampleshipsAPP_DEBUG=false; history scan is clean (or findings are triaged).
- ✅ Routes compile; no live secret patterns in
5. Review & commit fixes
Section titled “5. Review & commit fixes”Stage deliberately, confirm no .env/credentials are staged, commit with a descriptive message, push.
-
Review the staged diff, then commit and push the fixes.
Terminal window git status && git diff --staged --statgit commit -m "audit: apply code-quality & security fixes"# Expected: no .env or credentials staged; a clean descriptive commit- ✅ No
.env/credentials are staged; the audit commit lands and is pushed.
- ✅ No
6. Run the SHOULD companions
Section titled “6. Run the SHOULD companions”Two SHOULD companions deepen this: database migration analysis (count migrations, confirm core tables, map custom-table vendor dependencies) and storage FVDUT classification (categorize every storage path so deploy.php shared_dirs never overwrites real user uploads).
-
Run the migration analysis and the FVDUT classification, recording both.
- ✅ Migrations counted, core tables confirmed, custom-table vendor dependencies mapped.
- ✅ Every storage path classified F/V/D/U/T, with the U paths flagged for
shared_dirs.
Checklist
Section titled “Checklist”Do not mark this step done until every box below is checked.
- 🤖 Project structure verified — 9 core dirs +
bootstrap/cache/present; custom dirs noted. - 🤖 Composer audit clean — manifest valid, no advisories, autoload present.
- 🤖 Vendor seam re-verified — backdoor-signature re-scan over live
vendor/core returnsOK; any hit cleaned viacomposer reinstall(notinstall) and re-scanned. - 🤖 Git hygiene confirmed —
vendor//node_modules/absent from Git; lock files present in Git;public/storage/public/packages/storage/installedabsent from Git + gitignored (no dead-absolute symlink). - 🤖 Secrets scan clean — routes compile, no leaked secrets,
APP_DEBUG=falsein.env.example. - 🤖 Fixes committed — staged diff reviewed, no credentials staged, commit pushed.
- 🤖 SHOULD companions done — migration analysis recorded and storage FVDUT classified.