agentsclimarketplace

Shared hosting recon

Skill OmarEltak/legacy-prod-survival-kit/skills/shared-hosting-recon

Claude Code skills for the solo engineer who just inherited a 17-year-old production system. Audit, deploy, monitor, and report — without a DevOps team.

Install
npx -y skills add OmarEltak/legacy-prod-survival-kit --skill shared-hosting-recon

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use at the START of any engagement on a shared cPanel / Plesk / DirectAdmin host. Discovers disabled PHP functions, available APIs, /tmp permissions, security holes, file-system surprises, and host-side quirks BEFORE making architecture decisions. Especially valuable when you have no shell access. Surfaces everything that will surprise you 4 hours from now.

SKILL.md

14.1 KB, ~3.6k tokens by cl100k_base, as published. Nobody here has run it

Shared-hosting reconnaissance

When to use this

You're about to do engineering work on a production system hosted on shared hosting (cPanel, Plesk, DirectAdmin, etc.) where you don't have SSH/shell access. Before you write a deploy script, before you choose an architecture, before you trust anything: you do reconnaissance.

This skill is a checklist. Walk through it once, completely, at the start. The findings will inform every architectural decision you make for the next 8 hours.

Specifically use this when:

  • You inherited a hosting account and need to know what's possible.
  • A standard tool isn't working and you don't know why.
  • You're considering using a PHP function or library and need to confirm it exists.
  • You're about to commit to a deploy mechanism (cPanel Git VC, FTP, GitHub Actions over SSH) and need to know if it'll work.

Do NOT use this for:

  • Cloud-native environments (AWS, GCP, Azure, Fly.io, Railway, Vercel) — they don't have these constraints.
  • Dedicated servers / VPS where you have root — use standard sysadmin tooling.
  • "I just want to deploy a small static site" — overkill.

The recon checklist

Walk through every section. Don't skip any. The ones you skip are the ones that will surprise you later.

A. PHP capabilities (most important — affects everything)

Upload a small _recon.php to the document root with this content. Run it once. Note every output. Delete it afterwards.

<?php
header('Content-Type: text/plain');

echo "=== PHP ===\n";
echo "version: " . PHP_VERSION . "\n";
echo "sapi: " . php_sapi_name() . "\n";
echo "uname: " . php_uname() . "\n";
echo "os: " . PHP_OS . "\n";

echo "\n=== INI ===\n";
$inis = ['memory_limit', 'max_execution_time', 'allow_url_fopen', 'allow_url_include',
         'open_basedir', 'safe_mode', 'disable_functions', 'disable_classes',
         'upload_max_filesize', 'post_max_size', 'max_input_time', 'session.save_path',
         'date.timezone', 'short_open_tag', 'display_errors', 'log_errors',
         'error_log'];
foreach ($inis as $k) echo "$k: " . ini_get($k) . "\n";

echo "\n=== Functions (commonly disabled on shared hosting) ===\n";
$fns = ['exec','passthru','shell_exec','system','popen','proc_open','proc_close',
        'curl_exec','curl_multi_exec','escapeshellarg','escapeshellcmd',
        'file_get_contents','fopen','fsockopen','pfsockopen','stream_socket_client',
        'mail','dl','phpinfo','getmypid','posix_getpwuid','posix_kill',
        'symlink','link','readlink','chmod','chown','chgrp'];
foreach ($fns as $f) {
    echo str_pad("$f:", 32) . (function_exists($f) ? 'AVAILABLE' : 'DISABLED') . "\n";
}

echo "\n=== Classes (commonly relied on for deploy/zip work) ===\n";
$classes = ['ZipArchive','PharData','Phar','SplFileObject','RecursiveDirectoryIterator',
            'RecursiveIteratorIterator','PDO','mysqli','SoapClient','DOMDocument'];
foreach ($classes as $c) {
    echo str_pad("$c:", 32) . (class_exists($c) ? 'AVAILABLE' : 'MISSING') . "\n";
}

echo "\n=== Extensions ===\n";
echo implode(', ', get_loaded_extensions()) . "\n";

echo "\n=== Filesystem ===\n";
$paths = ['/tmp', sys_get_temp_dir(), getcwd(), dirname(__FILE__),
          $_SERVER['DOCUMENT_ROOT'] ?? '?',
          dirname($_SERVER['DOCUMENT_ROOT'] ?? '/')];
foreach (array_unique(array_filter($paths)) as $p) {
    $perms = file_exists($p) ? sprintf('%04o', fileperms($p) & 0777) : 'MISSING';
    $w = is_writable($p) ? 'W' : '-';
    $r = is_readable($p) ? 'R' : '-';
    $link = is_link($p) ? ' -> ' . @readlink($p) : '';
    echo str_pad($p, 50) . " mode=$perms $r$w$link\n";
}

echo "\n=== Server ===\n";
foreach (['SERVER_SOFTWARE','GATEWAY_INTERFACE','DOCUMENT_ROOT','SERVER_ADDR',
          'HTTP_HOST','HTTPS'] as $k) {
    echo str_pad("$k:", 24) . ($_SERVER[$k] ?? '(unset)') . "\n";
}

Critical things to look for:

OutputWhat it meansWhat to do
passthru: DISABLEDNo shell-out from PHPCannot use tar, rsync, git from PHP. Build deploy in pure PHP using ZipArchive or PharData.
curl_exec: DISABLEDcURL functions disabledUse file_get_contents() with stream_context_create() for HTTP requests. Confirm allow_url_fopen=1.
allow_url_fopen: 0Cannot fetch URLs from PHPMajor problem for any deploy that pulls from GitHub. Check if fsockopen works as fallback.
ZipArchive: AVAILABLEZip extraction worksGood — can use GitHub zipball API for deploys.
ZipArchive: MISSINGNo zip libTry PharData instead (uses tar.gz).
open_basedir: <something>Can only access listed pathsNote the constraint. Cannot read/write outside it.
/tmp mode=0755 (instead of 1777)Cannot write temp files as userCritical: breaks cPanel's own deploy task runner. Build your deploy outside of any tooling that needs /tmp.
/home/<user>/tmp -> /tmpSymlink to broken /tmpSame as above.
disable_functions: includes escapeshellargEven arg-escaping disabledStrong signal hosting locked down hard. Plan for pure-PHP everything.

B. cPanel / control panel API capabilities

If on cPanel, test the UAPI (User API). Hit each in the browser while logged into cPanel:

/cpsess<session>/execute/Fileman/list_files?dir=/home/<user>
/cpsess<session>/execute/Fileman/get_file_content?dir=/home/<user>&file=test.txt
/cpsess<session>/execute/Fileman/save_file_content (POST)
/cpsess<session>/execute/VersionControl/list_repositories

Check which functions return {"status":1} and which return {"errors":["The system could not find the function..."]}. Different cPanel versions expose different UAPI surfaces.

Functions commonly missing on older cPanel:

  • Fileman/compress
  • Fileman/chmod
  • Fileman/remove_files
  • Fileman/rename_file
  • Fileman/move_files_to_trash
  • Fileman/empty_trash

If most of these are missing, you're stuck with: list, read, write. You'll need to do anything else (delete, chmod, rename) via the File Manager UI by clicking, OR by uploading PHP that does it.

C. cPanel session token / "security token" rules

cPanel URLs have a cpsess<digits> segment. This is per-session. If your session is invalidated:

  • All cached cPanel URLs become invalid.
  • The Fileman API returns 401 with "Invalid Security Token."
  • Fix: log in fresh, get a new cpsess value, replay the request.

If you're scripting via a browser tool, always extract the cpsess fresh from the current URL rather than caching it. We learned this the hard way.

D. cPanel Git Version Control (if present)

In cPanel → Git Version Control:

  1. Note: warning at top says "Your system administrator must enable shell access to allow you to view clone URLs." This is misleading — it's only about the SSH clone URL display, not deploys themselves.
  2. Try clicking "Create" → enter a clone URL with embedded credentials (https://user:[email protected]/...). cPanel rejects this with "The clone URL cannot include a password." Workaround: write ~/.git-credentials and ~/.gitconfig first via the Fileman API, then use plain HTTPS clone URL.
  3. Try clicking "Deploy HEAD Commit." Watch the result. Then immediately read ~/.cpanel/logs/user_task_runner.log. The cPanel UI sometimes reports "complete" when the underlying task failed. The log file is the source of truth.
  4. Common deploy failure: Permission denied creating /home/<user>/tmp/...tmp.... This means /tmp is mode 0755 instead of 1777 (server-wide misconfig). cPanel's deploy is broken on this host. You need a custom PHP-based deploy.

E. Disk usage and quota

cPanel → Disk Usage (or directly: /cpsess<>/frontend/paper_lantern/diskusage/)

Note:

  • Total disk used.
  • Per-top-dir breakdown (often hidden — sort by size).
  • Look for unidentified large files at the document root. We found 37 GB of mystery binary files (zikqEi0T, ziCYIb3s, etc.) — old account-transfer artifacts, probably, but they were publicly downloadable.

F. Security audit (the bare minimum)

Walk the document root looking for these — they are surprisingly common on legacy hosting:

File / patternRiskAction
phpinfo.php, info.php, pinfo.phpInformation disclosure (PHP version, env, paths)Delete immediately.
mysqldumper.php, adminer.php, phpmyadmin.php (outside phpmyadmin/)Public DB admin toolMove outside web root or delete.
*.sql, dump.sql, db.sql.gz at web rootDB contents downloadableMove out of web root.
*.zip, backup.tar.gz at web rootBackup downloadableMove out of web root.
_old.php, *.bak, *.origOld code accessibleAudit; delete or rename.
.git, .svn directories at web rootSource code leakBlock via .htaccess or remove.
Random binary files with no extension and no obvious purposeUnknown — investigateRun file (if shell) or check magic bytes via Fileman/get_file_content.
WordPress wp-config.php~, wp-config.php.bakCredentials leakDelete.

G. PHP error log location

echo ini_get('error_log');

Note the path. Tail it to see what's actually happening on your prod. You will be amazed at how many silent errors are happening that nobody knows about.

If error_log is empty (i.e., logs go to Apache's), check ~/access-logs/ or ~/logs/ or the cPanel Errors page.

H. Existing cron jobs

cPanel → Cron Jobs

List everything currently scheduled. You inherit these. Some may be:

  • Backup scripts written by the previous developer.
  • Cleanup scripts that run mysteriously.
  • Calls to deprecated services.

Read each cron command. If it's incomprehensible, find the script and read it. Don't disable any cron until you know what it does.

I. Database snapshot

cPanel → phpMyAdmin → Export → SQL → Save

Take a one-time DB dump as part of recon. Even if you do nothing else with it, you have a recovery point that's not the host's responsibility.

J. DNS and SSL

cPanel → Zone Editor (or DNS Zone Editor)
cPanel → SSL/TLS Status

Confirm:

  • The domain points where you think it does.
  • SSL certs aren't expiring in the next 7 days.
  • AAAA records make sense (or don't exist if you don't want IPv6).

K. Existing repos / version control state

If cPanel → Git Version Control shows existing repositories, list them with their paths. Don't delete them — they may be legitimate or may be the previous developer's experiments. Just note they exist.

Output format

Produce a structured Markdown document with these sections:

# Shared-hosting reconnaissance: <hostname>
Date: <YYYY-MM-DD>

## PHP capabilities
- Version: ...
- Disabled functions: ... (highlight: passthru, exec, etc.)
- Available classes: ZipArchive, PharData, ...
- Critical INI settings: ...
- Filesystem: /tmp mode=..., ...

## cPanel API surface
- Working: list_files, save_file_content, get_file_content
- Missing: compress, chmod, ...

## /tmp situation
- /home/<user>/tmp -> /tmp (mode 0755) ⚠️ BROKEN
- Implication: cPanel deploys will fail silently. Custom PHP deploy required.

## Disk usage breakdown
- Total: ... GB
- public_html: ... GB (which is ... % code, ... % media)
- Mystery files at web root: ...

## Security findings
- ⚠️ admin/phpinfo.php (info disclosure) — DELETE
- ⚠️ test/admin/mysqldumper.php (public DB tool) — MOVE OUT OF WEB ROOT
- ⚠️ Database dump downloadable at /db.sql — MOVE
- 4 unidentified binary files totalling 37 GB at web root — INVESTIGATE

## Pre-existing automation
- 3 cron jobs found: <list with descriptions>
- 1 git repository in ~/repositories/<name>: <last update, purpose>

## Architectural implications
- Cannot use cPanel's native deploy (broken /tmp).
- Cannot shell out from PHP (disabled functions).
- Have ZipArchive + PharData + allow_url_fopen → can fetch + extract zips.
- Recommended deploy mechanism: <X>.

## What to fix immediately (before any other work)
1. Delete <list of security holes>
2. Take a DB backup
3. Document existing cron jobs

## What to defer
- <list of nice-to-haves>

This document becomes your reference for the rest of the engagement. Every architectural decision should cite a specific line from it.

Common mistakes to avoid

  • Skipping section A. "I'll just check disabled functions when I need them." No — knowing the full list upfront saves you from designing around a function that turns out not to exist.
  • Trusting the cPanel UI. It often reports success when the underlying task failed. The log files are the source of truth.
  • Assuming standard Linux conventions hold. On legacy shared hosts, /tmp may be wrong. /home/<user>/tmp may be a symlink. /usr/bin/tar may not be reachable from PHP. Test, don't assume.
  • Not taking a DB snapshot. It's free, takes 5 minutes, and is the one thing you'll regret skipping.

Why this skill exists

In one engagement, the order of discovery was:

  1. Try cPanel's native Git deploy. It "succeeds."
  2. Site doesn't update. Confused.
  3. Read ~/.cpanel/logs/user_task_runner.log. See Permission denied: /home/reg/tmp/....
  4. Investigate /home/reg/tmp. Discover it's a symlink to /tmp.
  5. Discover /tmp is mode 0755 instead of 1777.
  6. Realize cPanel's deploy is fundamentally broken on this host.
  7. Plan custom PHP deploy.
  8. Try passthru('tar ...'). Returns empty.
  9. Try system. Same.
  10. Read disable_functions. See: passthru, exec, shell_exec, system, popen, proc_open, curl_exec, escapeshellarg, ....
  11. Realize need pure-PHP deploy with no shell.
  12. Check if ZipArchive is available. It is. Build around that.

Each of those discoveries took 5–30 minutes in the moment, with bewildered "why is this happening" energy. This skill compresses the entire chain into one upfront pass: 30 minutes of recon and you know everything you needed to know.

The skill is short. The pain it prevents is not.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.