Overview
EcomScan is a realtime detection & response platform for ecommerce storefronts. It deploys as a lightweight CLI agent on your server, scans your codebase for Magecart skimmers, webshells, backdoors, and obfuscated malware, then streams results to a central dashboard with alerting, MITRE ATT&CK mapping, and AI-powered remediation.
Architecture
┌─────────────┐ ┌──────────────┐ ┌────────────────┐
│ Storefront │ │ ecomscan │ │ Dashboard │
│ /var/www/ │──────▶│ CLI agent │──────▶│ + API │
│ │ scan │ │ POST │ │
└─────────────┘ └──────────────┘ └────────────────┘
│ Signature engine │ Alerts
│ Hash engine │ Incidents
│ YARA rules │ Threat intel
│ Heuristic engine │ Compliance
│ Delta detection │ Webhooks
│ Attack chain └────────────────
└──────────────
Install the CLI
The ecomscan CLI runs on Linux (x86_64 / arm64), macOS, and WSL. Install with a single command:
# Install ecomscan CLI $ curl -fsSL https://api.hbgdevlab.com/api/v1/cli/install.sh | sh -s -- --key=ec_key_xxxxx # Or with wget $ wget -qO- https://api.hbgdevlab.com/api/v1/cli/install.sh | sh -s -- --key=ec_key_xxxxx
Manual install
# Download binary directly $ wget https://api.hbgdevlab.com/releases/ecomscan-linux-amd64 $ chmod +x ecomscan-linux-amd64 $ sudo mv ecomscan-linux-amd64 /usr/local/bin/ecomscan $ ecomscan --version
Verify installation
$ ecomscan --version ecomscan v1.0.4 (build: 2026-05-13, commit: a8f3c2d) $ ecomscan status CLI: v1.4.2 API: connected (https://api.hbgdevlab.com) License: EC-GROW-**** (Growth tier) Auth: authenticated as user@company.com
Quick start
Step 1: Authenticate
$ ecomscan auth login Email: user@company.com Password: ******** ✓ Authenticated. Token saved to ~/.ecomscan/credentials.json
Step 2: Run a local scan
$ ecomscan scan --path /var/www/html --platform magento ▸ Scanning /var/www/html (magento) ▸ 15,241 files scanned in 12.3s ▸ Engines: signature ✓ hash ✓ heuristic ✓ YARA ✓ delta ✓ ┌─────────────────────────────────────────────────────────┐ │ RISK SCORE: 78/100 (CRITICAL) │ │ Findings: 2 critical · 3 high · 1 medium · 0 low │ └─────────────────────────────────────────────────────────┘ CRITICAL Magecart · KeepUp.v3 /checkout/js/bundle.min.js CRITICAL PHP webshell · WSO 4.0 /pub/media/.thumbs/x.php HIGH Obfuscated eval chain /app/code/local/helper.php HIGH Exfil POST to 185.234.72.19 /skin/frontend/loader.js HIGH XOR-encoded payload /var/tmp/.cache.php MEDIUM Unsigned 3rd-party script /checkout/head.phtml
Step 3: Upload to dashboard
Uploading scan results requires an agent secret (ec_key_...), not your login JWT. Create one from the dashboard (API Keys → Create key) or during install:
# Create an API key from the dashboard (API Keys → Create key) # Then scan + upload using the agent secret $ ecomscan --key=ec_key_xxxxx scan \ --path /var/www/html \ --platform magento \ --upload ✓ 6 findings uploaded to dashboard ✓ 2 alerts created (CRITICAL, HIGH)
ecomscan auth login gives you a JWT for CLI commands (keys, whoami). Scan upload uses the --key flag with an ec_key_... token scoped to a specific store.Step 4: Start continuous monitoring
# Watch for file changes in real time $ ecomscan monitor --path /var/www/html --platform magento ▸ Baseline created: 15,241 files hashed ▸ Watching /var/www/html for changes... ▸ Next scheduled scan: 6h0m0s ▸ Heartbeat: every 60s → api.hbgdevlab.com
License activation
After purchasing a plan you receive a license key. The prefix determines your tier:
| Prefix | Tier | Stores | Features |
|---|---|---|---|
| EC-STAR-**** | Starter | 1 | Scan, monitor, alerts |
| EC-GROW-**** | Growth | up to 10 | + YARA, IOC feed, API |
| EC-AGCY-**** | Agency | Unlimited | + Multi-tenant, white-label |
| EC-ENTR-**** | Enterprise | Unlimited | + SSO, RBAC, custom MITRE |
# Install with your API key — license is validated automatically $ curl -fsSL https://api.hbgdevlab.com/api/v1/cli/install.sh | sh -s -- --key=ec_key_xxxxx ✓ Binary installed to ~/.ecomscan/bin/ecomscan ✓ API key saved to ~/.ecomscan/credentials.json ✓ Background monitoring active (systemd: ecomscan-agent)
Your first scan
What happens during a scan:
| Time | Phase | What happens |
|---|---|---|
| 0-2s | Discovery | Walk filesystem, filter by extension, skip excludes |
| 2-8s | Signature + hash | Match against 500+ signatures and known-bad hashes |
| 8-12s | YARA + heuristics | YARA rules fire, then behavioral analysis on every file |
| 12-15s | Delta + scoring | Compare against baseline, compute risk score per finding |
| 15s | Report | Generate unified report with family classification, MITRE mapping |
Routing alerts
Every detection produces an alert. Configure destinations in the dashboard under Integrations:
- Slack — channel per severity with rich alert cards.
- Webhook — signed payload (HMAC-SHA256), retried with exponential backoff.
- Email — per-incident alerts via SMTP or SendGrid.
Config file
The CLI reads config from ~/.ecomscan/config.yaml (or /etc/ecomscan/config.yaml for system-wide). All fields are optional — sensible defaults are applied.
# ~/.ecomscan/config.yaml agent: store_id: "550e8400-e29b-41d4-a716-446655440000" secret_key: "ec_key_xxxxx" api: endpoint: "https://api.hbgdevlab.com" timeout: 30s retry_max: 3 scanner: store_paths: - /var/www/html platform: magento scan_interval: 6h max_concurrency: 4 enable_heuristics: true enable_yara: true extensions: - .php - .phtml - .js - .html - .xml exclude_paths: - node_modules - vendor - .git monitor: enabled: true heartbeat_interval: 60s change_detection: true
Manage config via CLI
$ ecomscan config show # View current config $ ecomscan config set scan.concurrency 8 # Update a value $ ecomscan config reset # Reset to defaults
Environment variables
Every config key can be set as an env var with the ECOMSCAN_ prefix. Env vars override the config file.
# Required for agent mode export ECOMSCAN_AGENT_STORE_ID="your-store-uuid" export ECOMSCAN_AGENT_SECRET_KEY="ec_key_xxxxx" export ECOMSCAN_API_ENDPOINT="https://api.hbgdevlab.com" # Optional overrides export ECOMSCAN_SCANNER_PLATFORM="magento" export ECOMSCAN_SCANNER_STORE_PATHS=""/var/www/html""
Agent daemon mode
The agent daemon runs continuously — scanning on a schedule, monitoring file changes, and sending heartbeats to the API.
# Start the agent daemon $ ecomscan monitor \ --path /var/www/html \ --platform magento \ --scan-interval 6h # What the daemon does: 1. Creates filesystem baseline (SHA256 per file) 2. Watches for file modifications via fsnotify 3. Runs full scan every 6h (configurable) 4. Sends heartbeat to API every 60s 5. Picks up "Run scan" commands from dashboard 6. Uploads findings + change events automatically
Data flow
Agent daemon API server ──────────── ────────── Heartbeat (60s) ──────────────────▶ POST /api/v1/agents/heartbeat Scan results ──────────────────▶ POST /api/v1/scans/results File changes ──────────────────▶ POST /api/v1/events/file-change Auth header: X-Agent-Secret: ec_key_xxxxx
Deploy as a service
systemd (Linux)
# /etc/systemd/system/ecomscan.service [Unit] Description=ecomscan agent After=network.target [Service] Type=simple User=ecomscan ExecStart=/usr/local/bin/ecomscan monitor --path /var/www/html --platform magento Restart=always RestartSec=10 Environment=ECOMSCAN_AGENT_SECRET_KEY=ec_key_xxxxx Environment=ECOMSCAN_AGENT_STORE_ID=your-store-uuid [Install] WantedBy=multi-user.target
$ sudo systemctl enable --now ecomscan $ sudo systemctl status ecomscan $ sudo journalctl -u ecomscan -f # tail logs
Magento & Adobe Commerce
$ ecomscan scan --path /var/www/html --platform magentoAutomatically scans: app/code, app/design, pub/static, pub/media, var, generated. Understands Magento module structure, detects admin path obfuscation, and monitors env.php changes.
WooCommerce
$ ecomscan scan --path /var/www/html --platform woocommerceScans wp-content/plugins, wp-content/themes, wp-includes. Monitors wp-config.php, .htaccess, and detects unauthorized plugins.
Shopware
$ ecomscan scan --path /var/www/html --platform shopwareSupports Shopware 5 and 6. Scans custom plugins, themes, and public/ assets.
Headless storefronts
$ ecomscan scan --path /app/dist --platform other \
--extensions .js,.ts,.jsx,.tsxFor headless/custom builds, use --platform other and specify extensions. Heuristic and YARA engines work on any codebase.
How detection works
Every file passes through 6 detection engines in sequence. The unified pipeline normalizes, deduplicates, and scores all findings:
File │ ├──▶ 1. Signature engine 500+ regex patterns (webshells, skimmers, backdoors) ├──▶ 2. Hash engine Known-bad MD5/SHA256 database ├──▶ 3. YARA engine Community + ecomscan YARA rules ├──▶ 4. IOC matcher Domain, IP, hash indicators from threat feeds ├──▶ 5. Heuristic engine 40+ behavioral signals (entropy, obfuscation, exfil) ├──▶ 6. Delta detector Baseline diff — what changed since last scan? │ ▼ Unified Detection │ ├──▶ Family classification Match to 100+ known malware families ├──▶ Confidence calibration Engine reliability × context × rule override ├──▶ Risk scoring Evidence-weighted, path-aware, exploit-chain amplified ├──▶ MITRE ATT&CK mapping Technique + tactic assignment └──▶ Attack chain Kill-chain reconstruction across files
Magecart family detection
EcomScan tracks 28+ known Magecart families by fingerprint, plus behavioral classes:
- KeepUp.v3 — Image pixel exfiltration, card form hooks
- Inter / Inter2 — Injected via compromised 3rd-party scripts
- Grelos — Payment form overlay with data interception
- MakeFrame — Iframe-based card capture
- FormJacker — Form submit intercept + exfil
Unknown skimmers are caught via co-occurrence scoring: if a JS file on a checkout page has 3+ signals (form listener + card selector + beacon exfil), it's flagged even with no known signature.
File integrity monitoring
The integrity engine builds a SHA-256 baseline of every file under the monitored paths. On each scan, it compares the current filesystem against the baseline and flags:
- New files — unexpected files in web-accessible directories
- Modified files — changed content, especially in checkout/payment paths
- Deleted files — removed security controls or config files
- Permission changes — files made world-writable or executable
# Create a baseline after a clean deploy $ ecomscan baseline --path /var/www/html ✓ Baseline created: 15,241 files tracked ✓ Saved to: ~/.ecomscan/baseline.json
Heuristic engine
The heuristic engine scores 40+ behavioral indicators without signatures:
| Signal | Score | Catches |
|---|---|---|
| eval() + base64_decode chain | +0.50 | Obfuscated PHP backdoors |
| Shannon entropy > 5.5 | +0.20 | Packed/encrypted payloads |
| XOR cipher loops | +0.35 | XOR-encoded malware |
| sendBeacon / fetch POST | +0.35 | JS exfiltration (Magecart) |
| Hidden iframes | +0.45 | Drive-by injection |
| exec/system + $_GET/$_POST | +0.50 | Remote code execution |
| Suspicious TLD (.su .xyz .tk) | +0.40 | C2 domain communication |
| Low whitespace ratio (<2%) | +0.20 | Minified/obfuscated code |
Verdict: score ≥ 0.70 = malicious, ≥ 0.35 = suspicious, < 0.35 = clean.
Delta detection
Compares each scan against the previous baseline. These file changes are auto-flagged at HIGH confidence even with zero signature matches:
- PHP file added to
/uploads/or/media/— executable in unexpected location - Checkout JavaScript modified since last scan — potential skimmer injection
- Core config changed (
wp-config.php,env.php,.htaccess) - New cron job file — persistence mechanism
MITRE ATT&CK mapping
Every detection is mapped to MITRE ATT&CK techniques. The attack chain reconstructor builds kill-chain narratives across multiple findings:
Initial Access ──▶ Execution ──▶ Persistence ──▶ Collection ──▶ Exfiltration T1195.002 T1059.007 T1505.003 T1056.003 T1041 Supply chain JavaScript Web shell Form capture C2 channel
CLI reference
# Scanning ecomscan scan --path <dir> # Scan directory for malware ecomscan scan --path <dir> --upload # Scan + upload to dashboard ecomscan scan --path <dir> --report X # Generate incident report ecomscan scan --path <dir> --email X # Scan + email report via API ecomscan scan --path <dir> --db-scan # Include WordPress DB scan ecomscan scan --path <dir> --full # Force full rescan (skip cache) # Monitoring (daemon mode) ecomscan monitor --path <dir> # File watching + scheduled scans + dashboard commands # Auth ecomscan auth login # Email/password login ecomscan auth logout # Clear credentials ecomscan auth whoami # Show current user # API keys ecomscan keys list # List API keys ecomscan keys create --name "prod" # Create agent API key ecomscan keys revoke --key-id <id> # Revoke API key # Other ecomscan version # Print version + YARA status
Scan command flags
| Flag | Default | Description |
|---|---|---|
| --path <dir> | (required) | Directory to scan |
| --platform <type> | other | magento | woocommerce | prestashop | shopware | opencart | other |
| --severity <level> | low | Minimum severity to report: critical | high | medium | low |
| --format <type> | table | Output format: table | json | csv |
| --output <file> | stdout | Write report to file |
| --upload | false | Upload results to API |
| --store-id <uuid> | Store ID (required with --upload) | |
| --exclude <patterns> | Comma-separated glob patterns to skip | |
| --max-size <MB> | 10 | Max file size in MB |
| --concurrency <N> | CPU count | Parallel scan workers |
| --verbose | false | Debug logging |
| --json | false | Force JSON output (alias for --format json) |
| --no-color | false | Disable colored output |
Report format
When using --format json, the scan produces this structure:
{
"id": "scan-uuid",
"store_id": "store-uuid",
"started_at": "2026-05-13T04:18:00Z",
"completed_at": "2026-05-13T04:18:12Z",
"duration": "12.3s",
"platform": "magento",
"total_files": 15241,
"scanned_files": 14800,
"findings": [
{
"path": "/checkout/js/bundle.min.js",
"severity": "critical",
"confidence": 97,
"type": "magecart",
"family": "KeepUp.v3",
"mitre": "T1056.003",
"matches": [
{
"signature_name": "Magecart_KeepUp_v3_Loader",
"line": 42,
"matched_text": "addEventListener('change'...)",
"remediation": "Remove injected script, block exfil domain at edge"
}
],
"heuristic": {
"verdict": "malicious",
"score": 0.92,
"indicators": ["form-hook", "beacon-exfil", "card-selector"]
}
}
],
"summary": {
"critical": 2,
"high": 3,
"medium": 1,
"low": 0,
"risk_score": 78
}
}API
The EcomScan REST API uses two authentication modes:
Authentication
| Mode | Header | Used by |
|---|---|---|
| User JWT | Authorization: Bearer <jwt> | Dashboard, CLI (ecomscan auth login), user-facing endpoints |
| Agent secret | X-Agent-Secret: <ec_key_...> | Deployed agents: heartbeat, scan upload, file-change events |
| Public | (none) | Auth routes (/auth/login, /auth/signup), license validation, health check |
User JWT endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/stores | List all stores |
| POST | /api/v1/stores | Register a new store |
| GET | /api/v1/stores/:id | Get store details |
| GET | /api/v1/stores/:id/scans | List scans for a store |
| POST | /api/v1/stores/:id/scans | Trigger a scan |
| GET | /api/v1/scans | List all scans (cross-store) |
| GET | /api/v1/scans/:id | Get scan detail |
| GET | /api/v1/scans/:id/findings | Get scan findings |
| GET | /api/v1/dashboard/summary | Dashboard summary stats |
| GET | /api/v1/incidents | List incidents |
| GET | /api/v1/incidents/:id | Get incident detail |
| GET | /api/v1/alerts | List alerts |
| POST | /api/v1/alerts/:id/ack | Acknowledge an alert |
| GET | /api/v1/keys | List agent API keys |
| POST | /api/v1/keys | Create agent API key |
| GET | /api/v1/auth/me | Current user profile |
| GET | /api/v1/settings | Workspace settings |
| GET | /api/v1/compliance/summary | Compliance score |
Agent secret endpoints
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/scans/results | Upload scan results |
| POST | /api/v1/agents/heartbeat | Agent heartbeat (returns pending commands) |
| POST | /api/v1/events/file-change | File change event |
| GET | /api/v1/threat-intel/feed | Download signed threat intelligence bundle |
| POST | /api/v1/threat-intel/telemetry | Report signature match telemetry |
Example
# List critical incidents $ curl https://api.hbgdevlab.com/api/v1/incidents?severity=critical \ -H "Authorization: Bearer ec_sk_..." { "data": [ { "id": "INC-2391", "store_id": "acmegear.com", "title": "Magecart KeepUp.v3 on /checkout", "severity": "critical", "risk_score": 78 } ] }
Webhooks
Subscribe to events in Dashboard → Integrations → Webhook. Payloads are signed with HMAC-SHA256 using your shared secret.
Events: scan.completed, alert.created, incident.opened, incident.resolved, store.compromised, agent.offline, integrity.diff.
Verify the signature:
expected = HMAC-SHA256(shared_secret, request_body) actual = request.headers["X-Ecomscan-Signature"] valid = constant_time_compare(expected, actual)
Troubleshooting
Agent not connecting
# Check connectivity $ ecomscan status # Test API directly $ curl -s https://api.hbgdevlab.com/healthz # Verify credentials $ cat ~/.ecomscan/credentials.json # Run with debug logging $ ecomscan scan --path /var/www/html --verbose
High false positive rate
- Exclude vendor directories:
--exclude node_modules,vendor,.git - Raise severity threshold:
--severity high - Framework files are automatically down-weighted (×0.6 confidence)
- Create a baseline after a clean deploy:
ecomscan baseline --path /var/www/html
Scan too slow
- Increase concurrency:
--concurrency 8 - Skip large files:
--max-size 5(5 MB limit) - Exclude non-critical paths:
--exclude var/log,var/cache,media/catalog
Common errors
| Error | Fix |
|---|---|
| NOAUTH: credentials not found | Run ecomscan auth login |
| license expired | Renew at ecom.hbgdevlab.com/billing |
| permission denied: /var/www/html | Run as the web server user or use sudo |
| upload failed: store not found | Verify --store-id matches a store in your dashboard |
| YARA: rules compilation failed | Update CLI: ecomscan update (rules ship with binary) |
community.ecomscan.io or reach out to support@ecomscan.io. Enterprise customers get a dedicated Slack channel.