How to Self-Audit Your PrestaShop Store — Free Security Scan Module
Check your PrestaShop store for vulnerable modules, exposed files, weak hardening and malware signs with a private local scan that runs inside your own shop.
Two ways to check your store
For a quick read in seconds, use our public Security Scanner: enter your store URL and it passively fingerprints your PrestaShop and PHP versions, checks whether that version is publicly exposed or end-of-life, and inspects your HTTPS security headers — no install, nothing to configure. It reads only what any visitor already sees.
That is also its limit. A public check can't tell which module versions you actually run, what your file permissions are, whether debug mode is on, or whether a backup .sql is sitting in your webroot — and that last category is most of what actually gets PrestaShop shops hacked. For that, install the free Security Scan module: it scans your shop from the inside, where consent is built in because it's your shop. This guide shows you how to run it, how to read the report, and — with real commands — how to fix what it finds. For the deep hardening reference, our companion PrestaShop Security Hardening checklist goes further.
What a local scan checks
The report is grouped by area — the confirmed checks first (versions, exposed files), then the heuristic ones (malware and code), which are clearly marked. Each finding tells you what was found, why it matters, and how to fix it.
| Group | What it looks at |
|---|---|
| Version & known vulnerabilities | Your PrestaShop core, every installed module, and PHP, matched against a curated advisory list (seeded from the Friends of Presta security cell). Flags EOL and modules with published CVEs. |
| Exposed files & endpoints | Things that should never be reachable from the web — confirmed against your own public URLs: .git, backup .sql/.zip, /install, phpinfo, directory listing, weak .htaccess, world-writable folders, readable parameters.php. |
| Malware & integrity (heuristic) | Web-shell / injected-loader signatures and PHP hiding in image folders. |
| Code-level static scan (heuristic) | Patterns in module code that can indicate unsafe input handling — flagged privately for your review, never as a public accusation. |
| Hardening & configuration | SSL forced everywhere, secure cookie flags, admin folder protection, CSRF token, brute-force lockout, stale modules, recently-created admin accounts. |
The malware and code groups are heuristic on purpose — educated guesses that will occasionally flag something harmless. We'd rather show you a false positive you can dismiss in ten seconds than quietly miss a web shell.
Every finding is verifiable. Each version and CVE match links straight to the official advisory — the CVE record or the vendor’s GitHub Security Advisory — and carries a confidence level, so you can check every flag yourself instead of taking our word for it. Where the scanner can only infer something, or can’t confirm a setting from the outside, it says so plainly and scores it low. It is built to be accurate, not alarmist.
How to run it
Install and enable the free Security Scan module, then open Configure → Security Scan → Scan & Report and click Run scan now. A typical scan takes a few seconds. The checks only read your shop's files, configuration, database and your own public URLs; the module only writes its own scan-history record, so it never modifies shop files, settings, products, orders or customers — safe on a live store.
Prefer the command line, or automating it? You can trigger the same local scan from a bootstrapped PrestaShop context (the guard keeps it from running over the web if you leave the file behind):
<?php
// scan-now.php — run from the CLI only; delete the file if you place it in the shop root
if (PHP_SAPI !== 'cli') {
http_response_code(403);
exit;
}
require __DIR__ . '/config/config.inc.php';
require __DIR__ . '/modules/mprsecurityscan/vendor/autoload.php';
$run = \MPRSecurityScan\Service\ScanRunner::runAndStore('manual');
printf("Score %d/100 (grade %s) — %d issues\n",
$run['result']['score'], $run['result']['grade'], $run['result']['problem_count']);How to read your score
You get a single number out of 100 and a letter grade. The score starts at 100 and loses points per real problem, weighted by severity — a critical issue costs far more than a low one. Passed checks are shown too, so you can see what was actually verified.
- Critical −30 each — exploitable now, or a confirmed exposure. Fix today.
- High −15 — serious; fix this week.
- Medium −7 — meaningful hardening or hygiene gaps.
- Low −3 — minor improvements.
That rolls up into a grade — A 90+, B 75+, C 60+, D 40+, F below 40. Treat the score as a prioritisation tool, not a guarantee: a high score means the scanner found no known problems in what it can see.
Worked example: an exposed .git directory
This is one of the most common — and most dangerous — findings. If you deployed by git clone or git pull into your webroot, the whole .git folder (with your full source history and any secrets ever committed) may be downloadable. The scanner confirms it by actually requesting /.git/HEAD over HTTP and checking the response looks like VCS metadata.
Critical — VCS metadata is publicly reachable. The scanner confirmed that /.git/HEAD returns VCS metadata over HTTP.
Fix it in two steps. First, from your shop root, back up the metadata and remove it (the guards make sure nothing is deleted unless the backup succeeded):
# run from your shop root
set -eu
paths=()
[ -d .git ] && paths+=(.git)
[ -d .svn ] && paths+=(.svn)
if [ "${#paths[@]}" -gt 0 ]; then
tar czf "$HOME/vcs-metadata-backup-$(date +%F-%H%M%S).tgz" "${paths[@]}"
rm -rf "${paths[@]}"
fiThen make sure the web server refuses dot-directories even if one reappears. Apache (.htaccess or vhost) — this denies dot-files and dot-directory paths like /.git/HEAD, while keeping /.well-known/:
<FilesMatch "^\.">
Require all denied
</FilesMatch>
RedirectMatch 404 "(^|/)\.(?!well-known(?:/|$))"Or nginx:
location ^~ /.well-known/ {
try_files $uri =404;
}
location ~ /\.(?!well-known(?:/|$)) {
return 404;
}Re-run the scan; the finding should clear (the URL now returns 403/404). If any secret ever lived in that history, rotate it.
What to fix first (with the commands)
Work the report top-down. Here are the fixes for the findings you'll see most often.
Backup archives in the webroot
A store.sql or backup.zip next to index.php is a full copy of your shop, one guess away. List them, then move every match out of the docroot (mv -n never overwrites):
# review the list first
find . -maxdepth 2 -type f \
\( -name '*.sql' -o -name '*.sql.gz' -o -name '*.zip' -o -name '*.tar.gz' -o -name '*.bak' \) -ls
# then move every match out of the webroot
mkdir -p "$HOME/private-backups"
find . -maxdepth 2 -type f \
\( -name '*.sql' -o -name '*.sql.gz' -o -name '*.zip' -o -name '*.tar.gz' -o -name '*.bak' \) \
-exec mv -n -- {} "$HOME/private-backups/" \;Leftover /install directory
PrestaShop tells you to delete this after setup. Rather than delete outright, quarantine it (run from your shop root):
# run from your shop root
set -eu
test -f config/config.inc.php
backup="$HOME/prestashop-install-dirs-$(date +%F-%H%M%S)"
mkdir -p "$backup"
[ -d install ] && mv install "$backup/"
[ -d install-dev ] && mv install-dev "$backup/"Debug mode left on
Developer mode leaks stack traces and paths to visitors. Edit the existing line in config/defines.inc.php (or config/defines_custom.inc.php) — don't add a second one below it:
<?php
// change the EXISTING _PS_MODE_DEV_ line to false (never true on a live shop)
define('_PS_MODE_DEV_', false);World-writable folders (0777)
The scanner flags directories at 0777. Restore least-privilege perms — never chmod 777, and keep the secret config files unreadable (leaving parameters.php world-readable is itself a finding). Run from your shop root:
# run from your shop root; set these to your real PHP-FPM/web user + group
WEB_USER=www-data
WEB_GROUP=www-data
find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;
# lock down the secret config files: owned by the web user, readable by owner+group only
# (never world-readable — but still readable by the PHP process). Adjust owner/group above.
for f in app/config/parameters.php config/settings.inc.php; do
[ -f "$f" ] || continue
chown "$WEB_USER:$WEB_GROUP" "$f"
chmod 640 "$f"
done
# only the writable dirs need to be owned by the web user
for dir in var/cache var/logs img upload download; do
[ -d "$dir" ] || continue
chown -R "$WEB_USER:$WEB_GROUP" "$dir"
find "$dir" -type d -exec chmod 775 {} \;
find "$dir" -type f -exec chmod 664 {} \;
doneWeak or missing .htaccess
Regenerate PrestaShop's protective rules from the Back Office (Shop Parameters → Traffic & SEO → Regenerate .htaccess), then confirm sensitive files are blocked and directory listing is off. A minimal guard:
<FilesMatch "(?i)(parameters\.php|settings\.inc\.php|\.env|composer\.(json|lock))$">
Require all denied
</FilesMatch>
Options -IndexesDetection-only limits
Being honest about the limits is part of using any security tool well: it detects problems, it doesn't fix them for you; the heuristic checks can flag harmless things (verify before deleting); advisory coverage is curated, not exhaustive; and it is not a penetration test. For the full remediation reference — server hardening, admin lockdown, database and monitoring — follow the Security Hardening checklist.
When to stop scanning and get help
Some findings mean it's time for a person, not a tool. Malware-like files, anything that looks like a payment skimmer, admin accounts you don't recognise, exposed credentials, or repeat re-infection — that's an incident. If you'd rather hand it to us, book a security audit.
When automatic fixes make sense
The free scanner is deliberately one-and-done: you run it, you read it, you fix things by hand. Perfect for an occasional check-up. If you'd rather not do it manually — or you want to stay fixed — Security Revolution applies one-click fixes, hardens your store, monitors core-file integrity, alerts you when something changes, and manages a whole fleet of stores from one dashboard. Same findings; it just acts on them and keeps watching.
FAQ
Does the scan send my data anywhere? For a standalone dashboard or CLI scan, no — the report stays on your server, and the only outbound requests are self-checks to your own public URLs, guarded against internal-address (SSRF) access. If you explicitly enrol the optional fleet connector, scan results are sent — over a signed channel — to the hub you configured.
Does it fix issues automatically? No — this module is detection-only. Automatic fixes and monitoring are in Security Revolution.
Is it safe on a live store? Yes. It reads your files, configuration and database and writes only its own scan-history record — it never modifies shop content, settings, products, orders or customers.
How often should I scan? After every PrestaShop or module update, and at least monthly. The History page tracks your score over time.
Can it replace a developer? No. It's a fast, useful first pass that catches common, well-known risks. Deep audits and real incidents still need a human.
Related reading
- PrestaShop Security Hardening: The Complete Checklist — the remediation companion to this page.
- Security Scan — the free module described here.
- Security Revolution — automatic fixes, hardening and file-integrity monitoring.