Skip to content
prod 352bb92
Browse

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:

  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.
  2. Composer security audit — Validate the manifest, scan for advisories, confirm autoload.
  3. Audit git hygienevendor/ and node_modules/ must NOT be tracked; lock files MUST be.
  4. Scan code quality & secrets — PHP syntax, hardcoded secrets, APP_DEBUG, .htaccess headers, env() usage.
  5. Review & commit fixes — Stage deliberately, confirm no .env/credentials are staged, commit with a descriptive message, push.
  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).

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]

Confirm the 9 core Laravel directories, bootstrap/cache/, and required files exist; identify CodeCanyon custom directories (Modules/, packages/, uploads/) for Zaj-CUSTOMIZATIONS.md.

  1. 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 for Zaj-CUSTOMIZATIONS.md.

Validate the manifest, scan for advisories, confirm autoload.

  1. Validate the manifest, scan advisories, flag abandoned packages, and confirm autoload.

    Terminal window
    composer validate --no-interaction --strict # Expected: composer.json is valid
    if composer audit --help >/dev/null 2>&1; then
    composer audit --no-interaction --format=json --abandoned=report > /tmp/composer-audit.json
    jq '.advisories | length, (.abandoned // {}) | length' /tmp/composer-audit.json
    composer audit --no-interaction --abandoned=fail
    else
    echo "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.json is valid, no security advisories, no abandoned packages, vendor/autoload.php present.
  2. Re-verify the vendor seam is still clean — a pre-launch backdoor re-scan of the live vendor/ tree, in case a later composer require/update re-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 via composer reinstall (not composer install) and re-scanned to OK.

vendor/ and node_modules/ must NOT be tracked; lock files MUST be.

  1. Confirm dependency trees are untracked and lock files are tracked.

    Terminal window
    git ls-files vendor/ node_modules/ # Expected: empty
    git ls-files composer.lock package-lock.json # Expected: both listed
    • vendor//node_modules/ print nothing; composer.lock + package-lock.json are listed.
  2. Verify the 12 framework .gitignore files exist, and auto-create any that are missing (so empty storage//cache dirs 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; do
    if [ ! -f "$dir/.gitignore" ]; then
    mkdir -p "$dir"
    printf '*\n!.gitignore\n' > "$dir/.gitignore"
    echo "Created $dir/.gitignore"
    fi
    done
    • ✅ All 12 .gitignore files print OK (any missing storage-dir ignore is auto-created).
  3. 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 .gitignore files are intentional.
  4. Confirm the per-env symlinks and install marker stay out of Git. public/storage (and public/packages for in-tree module apps) are per-env symlinks rebuilt by php artisan storage:link / the packages link — vendors frequently ship public/storage as an absolute symlink to a dead server path (/var/www/...), which breaks /storage/* on every other environment. storage/installed is 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, and storage/installed are absent from Git and gitignored; public/storage resolves to this env’s storage/app/public (not a foreign /var/www/... path).

PHP syntax, hardcoded secrets, APP_DEBUG, .htaccess headers, env() usage.

  1. 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 placeholders
    grep -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: empty
    grep -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/; no dd() in source; .env.example ships APP_DEBUG=false; history scan is clean (or findings are triaged).

Stage deliberately, confirm no .env/credentials are staged, commit with a descriptive message, push.

  1. Review the staged diff, then commit and push the fixes.

    Terminal window
    git status && git diff --staged --stat
    git 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.

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).

  1. 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.

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 returns OK; any hit cleaned via composer reinstall (not install) and re-scanned.
  • 🤖 Git hygiene confirmedvendor//node_modules/ absent from Git; lock files present in Git; public/storage/public/packages/storage/installed absent from Git + gitignored (no dead-absolute symlink).
  • 🤖 Secrets scan clean — routes compile, no leaked secrets, APP_DEBUG=false in .env.example.
  • 🤖 Fixes committed — staged diff reviewed, no credentials staged, commit pushed.
  • 🤖 SHOULD companions done — migration analysis recorded and storage FVDUT classified.