2FA enforcement, HSTS in Magento, SAQ A vs A-EP scoping, monthly Adobe patch cadence, Vault tokens, GDPR vs PCI scope, FIM, security.txt, scoring <60 next steps, sharing reports with hosting, pentesting overlap, and how the score checker differs from the broader store health checklist.
Is admin 2FA really mandatory on Magento 2.4.x?
Yes — Magento has shipped built-in 2FA since 2.4.0 via the Magento_TwoFactorAuth module, and it’s enabled by default. The supported providers are Google Authenticator, Authy, Duo Security, and U2F hardware keys.
What the audit checks is whether every admin user is enforced to use it — not whether the module is installed. Two common gaps I see:
The module is enabled but admins can dismiss the setup prompt. Fix: php bin/magento config:set twofactorauth/general/force_providers google so the prompt is non-dismissible.
Some admins use IP-allowlist bypass tokens. The bypass token mechanism is fine for emergency access but should be 1-time-use and rotated quarterly — not standing entries.
The Adobe Commerce hosted edition adds SSO via SAML/OAuth, which counts as 2FA for the purposes of this audit (assuming your IdP enforces MFA). If you’re on Open Source self-hosted, the built-in TOTP is the baseline.
Cost: $0. Effort: ~2 hours to enforce + train the admin team. There is no excuse for a "No" on q1.
Was this helpful?
How do I enable HSTS on Magento (and what max-age?)
HSTS is set at the web-server layer, not in Magento itself. Three places:
nginx (most Magento hosting): add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; inside the SSL server block.
Apache: Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" in the SSL VirtualHost.
Cloudflare / Fastly / CDN edge: set the header at the edge; same value.
Magento Admin → Stores → Configuration → Web → Use Secure URLs On Storefront + Admin = Yes. This makes Magento generate https:// URLs everywhere — HSTS then enforces the protocol at the browser.
max-age guidance:
Testing: Start with max-age=300 (5 minutes) for the first hour, verify nothing breaks.
Staging: Move to max-age=86400 (1 day) and run a week of traffic.
Production: Set to max-age=31536000 (1 year) with includeSubDomains and preload.
HSTS Preload list: Submit at hstspreload.org after 90+ days of stable 1-year max-age. Removal takes months — only preload when you’re sure.
The audit’s q7 specifically rewards a 1-year max-age with includeSubDomains. Shorter values count as partial credit; missing entirely is a "No".
Was this helpful?
What’s the difference between PCI SAQ A and SAQ A-EP?
The PCI Self-Assessment Questionnaire scope determines how much compliance burden you carry. For Magento merchants:
SAQ A: You outsource all cardholder data handling. The full checkout (incl. iframe / redirect) lives on a PCI-validated third-party provider (Stripe Hosted, Braintree Drop-in, PayPal Hosted, Adyen HPP). Magento never touches the PAN. ~22 questions, low scope, the easiest path.
SAQ A-EP: Your site renders the payment page (or fragments) but the actual PAN entry goes to a PCI provider via JS SDK / iframe (Stripe Elements, Braintree Hosted Fields, Adyen Drop-in). You "could" potentially impact card data via XSS / JS injection, so you carry more responsibility. ~191 questions, full vulnerability scanning + penetration testing required quarterly.
SAQ D: You touch raw PAN in any way (logged, stored, processed in your app). ~329 questions, full PCI DSS audit by a QSA. Avoid at all costs.
The audit’s q12 specifically rewards being on SAQ A or SAQ A-EP. If you’re unsure which you are, your acquirer / payment gateway has a portal that tells you. The biggest mistake I see is merchants who think they’re on SAQ A but their checkout pulls a custom JS file from a non-PCI third party — that’s SAQ A-EP territory, sometimes SAQ D if it touches the form.
Was this helpful?
Why monthly Adobe patches instead of "set and forget"?
Adobe ships security patches on a roughly monthly cadence via the Adobe Security Center. Recent examples:
APSB24-40 (June 2024): 7 CVEs including a critical XXE injection (CVSS 9.1).
APSB24-61 (Aug 2024): Critical XSS in admin (CVSS 8.1) + 2 other highs.
APSB25-08 (Jan 2025): 9 CVEs, one of which was a critical pre-auth RCE.
The math: every month you delay patching, you carry the open-window risk for that month’s CVEs. Within 72 hours of a CVE disclosure, automated scanners + exploit kits start probing the affected versions. By day 30 post-disclosure, ~40% of unpatched stores show probing in their access logs.
The "set and forget" pattern is the single most common cause of breach in mid-market Magento stores. The audit’s q17 rewards a documented ≤30-day cadence from patch release to production deployment.
Pattern that works:
Subscribe to the Adobe Security Center RSS feed.
Within 24h of patch release: assess severity vs your env, queue for next deploy window.
Within 7 days: apply to staging, run full UAT.
Within 30 days: deploy to production. Document the date in a security log for audit trail.
Was this helpful?
What’s a Vault token and why does the audit care?
A Vault token (also called a "payment method token" or "card token") is an opaque reference string the payment gateway gives you in exchange for the customer’s real card number. The real card data lives in the gateway’s PCI-validated vault — you only ever see / store the token.
Example flow (Stripe):
Customer enters card on checkout via Stripe Elements (JS SDK).
Stripe.js sends the PAN directly to Stripe’s servers — it never touches your DOM, your nginx, your PHP.
Stripe returns a token like pm_1NqAbcXyZ.
Magento stores pm_1NqAbcXyZ in sales_order_payment.additional_information (never cc_number).
Future charges use the token: POST /charges {"payment_method": "pm_1NqAbcXyZ"}.
The audit&rsquo>s q13 checks that no raw PAN ever touches your DB. The check looks at:
Whether any extension stores cc_number, cc_cid, cc_exp_year in cleartext (legacy COD-style payment methods are notorious for this).
Whether your saved-cards feature uses gateway tokens (Stripe Vault, Braintree Vault, Adyen RecurringDetail) or a custom DB column.
Whether refunds + retries route through the gateway by token, not by re-asking for the PAN.
A breach where raw PANs are leaked has a 6-figure cost minimum in card-brand fines + customer remediation. Tokenization eliminates the worst case — the gateway carries the liability.
Was this helpful?
GDPR vs PCI — how do the scopes overlap?
They overlap in 3 places and diverge in the rest:
Overlap (both frameworks require these):
Encryption at rest: PCI mandates it for cardholder data; GDPR mandates it for any "special category" personal data — both effectively require database-at-rest encryption.
Access logging: PCI requires admin-access logs for ~12 months; GDPR requires audit trails for processing of personal data. One SIEM serves both.
Breach notification: PCI doesn’t mandate customer notification but card brands do (typically 30 days); GDPR mandates regulator notification within 72 hours of awareness.
PCI-only (not GDPR):
Specific cryptography requirements (e.g. TLS 1.2+ mandate).
Quarterly external vulnerability scans by an ASV.
Annual penetration testing for SAQ A-EP and higher.
Specific compensating controls + scoping rules.
GDPR-only (not PCI):
Right to data export (subject access request, 30-day SLA).
Right to be forgotten (data deletion, 30-day SLA).
Lawful basis documentation for every processing activity.
DPIA (Data Protection Impact Assessment) for high-risk processing.
Privacy by design + by default.
The audit’s q14 specifically checks for the GDPR-only data-export endpoint, because PCI doesn’t cover that and stores often miss it. If you sell to EU/UK customers, GDPR applies regardless of where your servers live.
Was this helpful?
What’s File Integrity Monitoring (FIM) and is it worth it?
FIM watches a defined set of files / directories and alerts when anything changes. For Magento the standard scope is app/, vendor/, pub/, and the web-server config dirs.
Why it matters: the #1 post-exploitation move on a breached Magento store is to drop a webshell into pub/media/wysiwyg/ or a backdoor into a custom module. FIM catches both within minutes — the difference between a 4-hour incident and a 4-month one.
Three implementation tiers:
Free / DIY: AIDE (Linux) or OSSEC. Cron-runs nightly, emails a diff. Good for solo stores; manual triage.
Mid-tier ($50–$200/mo): Wazuh, Tripwire OS. Centralised dashboard, real-time alerts. Good for stores with a small ops team.
Enterprise (commercial): CrowdStrike Falcon, SentinelOne. Full EDR + FIM + threat intel correlation. Worth it for stores doing $50M+ GMV.
Common false-positive sources to whitelist: Magento’s generated/ directory (PHP DI cache), var/cache/, var/log/, pub/static/ (recompiled on deploy). Anywhere else changes are a real alert.
The audit’s q21 rewards FIM at any tier. A "No" here is one of the most-skipped controls in mid-market Magento — install it before next quarter.
Was this helpful?
Is /.well-known/security.txt actually worth publishing?
Yes. RFC 9116 defines a standard text file at /.well-known/security.txt telling researchers + automated scanners where to report findings before they go public.
Researchers report responsibly: A good-faith researcher who finds an XSS bug will email security@ before tweeting it. Without security.txt they hunt for a contact, get frustrated, and often just disclose publicly.
Bug-bounty platforms find you: HackerOne, Bugcrowd, and Intigriti all check security.txt to know where to route reports for your domain.
Compliance frameworks credit it: ISO 27001, NIST CSF, and several PCI compensating controls reference a documented vulnerability-disclosure policy.
Cost: $0. Effort: 1 hour to write + deploy. The audit’s q22 rewards a current (non-expired) security.txt with at least a Contact and an Expires line. Update annually.
Was this helpful?
My score is under 60 — what should I do in the next 7 days?
A sub-60 score means at least one critical-severity control is failing. The 7-day stabilisation plan:
Day 1 (today):
Force-enable admin 2FA if it’s not (q1). 2-hour fix, eliminates the #1 attack vector.
Rotate all admin passwords. 1 hour.
Set the admin IP allowlist at nginx/WAF level (q3). 30 min.
Day 2-3:
Apply all outstanding Adobe security patches (q16, q17). 1 day including UAT.
If on TLS < 1.2, fix the load balancer config (q6). 30 min.
Enable HSTS with a short max-age (q7). 1 hour.
Day 4-5:
Take a fresh encrypted backup + verify the restore works (q11). 2 hours.
Verify no raw PAN is stored anywhere (q13). Query: SELECT * FROM sales_order_payment WHERE cc_number IS NOT NULL; — should return zero rows.
Check the PCI scope (q12) with your acquirer; if it’s SAQ D, move to a hosted/tokenized checkout.
Day 6-7:
Publish security.txt (q22). 1 hour.
Write a one-page IR plan (q24): who calls who, escalation tree, customer-notification thresholds. Even a 1-page draft beats nothing.
Re-run the audit. You should be over 70 by end of week.
If anything in the critical-severity list still scores "No" by day 7, that’s a deep-audit conversation. Book one.
Was this helpful?
Can I share the report with my hosting provider?
Yes — and you should. The audit covers controls that span the app layer (your responsibility) and the infrastructure layer (your hosting provider’s). The split:
Your hosting handles (typically):
q6 — TLS version + cipher suites on the load balancer.
I recommend forwarding the report to your hosting provider with a note: “Here’s our self-audit. Can you confirm the items I’ve marked as hosting-side are accurate, and quote remediation for any that scored ‘No’?” Good hosts respond with a written confirmation + timeline. If they push back or go silent, that’s a hosting-quality signal.
Was this helpful?
Do I still need an external penetration test on top of this?
Yes — the audit and a pentest serve different purposes.
The audit (this tool): A self-assessment of 25 controls based on what you know about your environment. Catches policy + config gaps. Fast (5 min). Free. Repeatable quarterly.
A penetration test: An external party tries to actively exploit your environment using the same techniques as a real attacker. Catches implementation bugs the policy review can’t see. Slow (1–3 weeks). Costs $4k–$30k depending on scope. Done annually.
You need both because:
An audit might show "WAF active = Yes" — but a pentest might find the WAF rules don’t catch obscure injection variants.
An audit might show "2FA enforced = Yes" — but a pentest might find a forgotten /staging/ subdomain with a 2FA-bypassable admin.
An audit might show "TLS 1.2+ = Yes" — but a pentest might find one legacy SOAP API endpoint still accepting TLS 1.0.
Compliance angle: PCI DSS v4 requires annual external + internal pentests for SAQ A-EP and SAQ D. SOC 2 Type II auditors expect to see a recent pentest report. ISO 27001 + NIST CSF reference one.
Sequencing: Run this audit + remediate everything you can — then commission the pentest. A pentest on a partially-fixed environment is money wasted on findings you already knew about.
For Magento-specific pentests, I work with two firms I trust (HackerOne-listed, Magento-experienced) and can refer. Or commission directly — ~$8k–$15k for a typical mid-market Magento scope.
Was this helpful?
How is this different from your /magento-store-health-checklist?
Different scope, different depth, complementary.
/magento-store-health-checklist:
Broader — covers SEO, performance, UX, content, conversion, accessibility, plus security.
Lighter on security — ~10 security questions out of ~60 total.
Static checklist with self-rating; no weighted scoring.
Best for: a quarterly "is everything still okay" review.
/magento-security-score-checker (this tool):
Narrower — security-only across 5 categories.
Deeper — 25 questions weighted by severity, server-scored, with a prioritized fix list.
Best for: pre-PCI-audit prep, post-incident review, or a focused security improvement sprint.
Recommended cadence:
Monthly: Run /magento-store-health-checklist as a 15-min overall posture review.
Quarterly: Run this security score checker as a 5-min focused security drill.
Annually: Commission a real external pentest + (if applicable) PCI assessment.
The two tools share their philosophy: free, anonymous, honest, severity-weighted, no upsell required. If the score checker surfaces a critical gap, the health checklist will usually agree — just less specifically.
Was this helpful?
Request a quote
I'll reply within 2-4 hours business with a written quote and timeline.