Skip to content
Docs · v2026.05

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.

3 minutes to first scan: install the CLI (1 min), activate your license (1 min), and run your first scan (1 min). Everything else is configuration.

Architecture


  ┌─────────────┐       ┌──────────────┐       ┌────────────────┐
  │  Storefront  │       │  korp         │       │   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 korp CLI runs on Linux (x86_64 / arm64), macOS, and WSL. Install with a single command:

# Install korp CLI
$ curl -fsSL https://github.com/ecomscan/korp/releases/latest | sh

# Or with wget
$ wget -qO- https://github.com/ecomscan/korp/releases/latest | sh

Manual install

# Download binary directly
$ wget https://github.com/ecomscan/korp/releases/latest/download/korp-linux-amd64.tar.gz
$ tar xzf korp-linux-amd64.tar.gz
$ sudo mv korp /usr/local/bin/
$ korp --version

Docker

$ docker run --rm -v /var/www/html:/scan ecomscan/korp scan /scan

Verify installation

$ korp --version
korp v1.0.4 (build: 2026-05-13, commit: a8f3c2d)

$ korp status
  CLI:        v1.4.2
  API:        connected (https://api.ecomscan.io)
  License:    EC-GROW-**** (Growth tier)
  Auth:       authenticated as user@company.com

Quick start

Step 1: Authenticate

$ korp auth login
  Email: user@company.com
  Password: ********
  ✓ Authenticated. Token saved to ~/.ecomscan/credentials.json

Step 2: Run a local scan

$ korp 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:

# Option A: Install registers an agent and saves the secret
$ korp install --license-key EC-GROW-XXXX-XXXX-XXXX \
    --tenant-id YOUR_TENANT_UUID \
    --store-id YOUR_STORE_UUID

# Option B: Create a key from the dashboard or CLI
$ korp keys create --name "prod-server" --store-id YOUR_STORE_UUID

# Then scan + upload using the agent secret (set via --token or env)
$ ECOMSCAN_TOKEN=ec_key_xxxxx korp scan \
    --path /var/www/html \
    --platform magento \
    --upload

  ✓ 6 findings uploaded to dashboard
  ✓ 2 alerts created (CRITICAL, HIGH)
Auth modes: korp auth login gives you a JWT for read-only CLI commands (status, check, report, keys). Scan upload uses the X-Agent-Secret header with an ec_key_... token scoped to a specific store.

Step 4: Start continuous monitoring

# Watch for file changes in real time
$ korp 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.ecomscan.io

License activation

After purchasing a plan you receive a license key. The prefix determines your tier:

PrefixTierStoresFeatures
EC-STAR-****Starter1Scan, monitor, alerts
EC-GROW-****Growthup to 10+ YARA, IOC feed, API
EC-AGCY-****AgencyUnlimited+ Multi-tenant, white-label
EC-ENTR-****EnterpriseUnlimited+ SSO, RBAC, custom MITRE
$ korp install --license-key=EC-GROW-XXXX-XXXX-XXXX

  ✓ License validated: Growth tier
  ✓ Agent registered: store-01-agent
  ✓ API key saved to ~/.ecomscan/credentials.json

Your first scan

What happens during a scan:

TimePhaseWhat happens
0-2sDiscoveryWalk filesystem, filter by extension, skip excludes
2-8sSignature + hashMatch against 500+ signatures and known-bad hashes
8-12sYARA + heuristicsYARA rules fire, then behavioral analysis on every file
12-15sDelta + scoringCompare against baseline, compute risk score per finding
15sReportGenerate 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; rich card with remediate buttons.
  • PagerDuty — auto-page on critical; service mapped per store.
  • Webhook — signed payload (HMAC-SHA256), retried with exponential backoff.
  • SIEM — Splunk HEC, Datadog, Elastic via native connectors.
  • MS Teams — adaptive cards with one-click actions.
  • Email — digest or per-incident, customizable templates.

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.ecomscan.io"
  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

$ korp config show                # View current config
$ korp config set scan.concurrency 8   # Update a value
$ korp 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.ecomscan.io"

# 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
$ korp 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. 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/korp.service

[Unit]
Description=korp agent
After=network.target

[Service]
Type=simple
User=ecomscan
ExecStart=/usr/local/bin/korp 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 korp
$ sudo systemctl status korp
$ sudo journalctl -u korp -f             # tail logs

Docker Compose

# docker-compose.yml
services:
  korp:
    image: ecomscan/korp:latest
    command: monitor --path /scan --platform magento
    volumes:
      - /var/www/html:/scan:ro
    environment:
      ECOMSCAN_AGENT_SECRET_KEY: ec_key_xxxxx
      ECOMSCAN_AGENT_STORE_ID: your-store-uuid
      ECOMSCAN_API_ENDPOINT: https://api.ecomscan.io
    restart: unless-stopped

Kubernetes

# Deploy as a DaemonSet on nodes with storefronts
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: ecomscan-agent
spec:
  selector:
    matchLabels:
      app: ecomscan
  template:
    spec:
      containers:
      - name: ecomscan
        image: ecomscan/korp:latest
        args: ["monitor", "--path", "/scan"]
        volumeMounts:
        - name: store
          mountPath: /scan
          readOnly: true
        envFrom:
        - secretRef:
            name: ecomscan-secrets

Magento & Adobe Commerce

$ korp scan --path /var/www/html --platform magento

Automatically 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

$ korp scan --path /var/www/html --platform woocommerce

Scans wp-content/plugins, wp-content/themes, wp-includes. Monitors wp-config.php, .htaccess, and detects unauthorized plugins.

Shopify Plus

Shopify storefronts are scanned via the checkout extensibility API. No agent install needed — connect via the dashboard Integrations → Shopify.

Shopware

$ korp scan --path /var/www/html --platform shopware

Supports Shopware 5 and 6. Scans custom plugins, themes, and public/ assets.

Headless storefronts

$ korp scan --path /app/dist --platform other \
    --extensions .js,.ts,.jsx,.tsx

For 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
$ korp 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:

SignalScoreCatches
eval() + base64_decode chain+0.50Obfuscated PHP backdoors
Shannon entropy > 5.5+0.20Packed/encrypted payloads
XOR cipher loops+0.35XOR-encoded malware
sendBeacon / fetch POST+0.35JS exfiltration (Magecart)
Hidden iframes+0.45Drive-by injection
exec/system + $_GET/$_POST+0.50Remote code execution
Suspicious TLD (.su .xyz .tk)+0.40C2 domain communication
Low whitespace ratio (<2%)+0.20Minified/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
korp scan --path <dir>              # Scan directory for malware
korp scan --path <dir> --upload     # Scan + upload to dashboard
korp scan --path <dir> --report     # Generate incident report
korp scan --path <dir> --email X    # Scan + email report
korp scan --path <dir> --db-scan    # Include WordPress DB scan
korp baseline --path <dir>          # Create file integrity baseline

# Monitoring
korp monitor --path <dir>           # Real-time file watching + scans

# Auth & setup
korp auth login                     # Email/password login
korp auth logout                    # Clear credentials
korp install --license-key=EC-...   # Activate license + register agent

# Management
korp keys list                      # List API keys
korp keys create --name "prod"       # Create API key (agent secret)
korp keys revoke --key-id <id>       # Revoke API key
korp check <domain>                 # Quick store health check
korp status                         # Agent + API status
korp report --scan-id=X             # Fetch scan report (JSON/CSV)
korp config show                    # View config
korp update                         # Update CLI binary
korp version                        # Print version

Scan command flags

FlagDefaultDescription
--path <dir>(required)Directory to scan
--platform <type>othermagento | woocommerce | prestashop | shopware | opencart | other
--severity <level>lowMinimum severity to report: critical | high | medium | low
--format <type>tableOutput format: table | json | csv
--output <file>stdoutWrite report to file
--uploadfalseUpload results to API
--store-id <uuid>Store ID (required with --upload)
--exclude <patterns>Comma-separated glob patterns to skip
--max-size <MB>10Max file size in MB
--concurrency <N>CPU countParallel scan workers
--verbosefalseDebug logging
--jsonfalseForce JSON output (alias for --format json)
--no-colorfalseDisable 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

ModeHeaderUsed by
User JWTAuthorization: Bearer <jwt>Dashboard, CLI (korp auth login), user-facing endpoints
Agent secretX-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

MethodEndpointDescription
GET/api/v1/storesList all stores
POST/api/v1/storesRegister a new store
GET/api/v1/stores/:idGet store details
GET/api/v1/stores/:id/scansList scans for a store
POST/api/v1/stores/:id/scansTrigger a scan
GET/api/v1/scansList all scans (cross-store)
GET/api/v1/scans/:idGet scan detail
GET/api/v1/scans/:id/findingsGet scan findings
GET/api/v1/dashboard/summaryDashboard summary stats
GET/api/v1/incidentsList incidents
GET/api/v1/incidents/:idGet incident detail
GET/api/v1/alertsList alerts
POST/api/v1/alerts/:id/ackAcknowledge an alert
GET/api/v1/keysList agent API keys
POST/api/v1/keysCreate agent API key
GET/api/v1/auth/meCurrent user profile
GET/api/v1/settingsWorkspace settings
GET/api/v1/compliance/summaryCompliance score

Agent secret endpoints

MethodEndpointDescription
POST/api/v1/scans/resultsUpload scan results
POST/api/v1/agents/heartbeatAgent heartbeat
POST/api/v1/events/file-changeFile change event

Example

# List critical incidents
$ curl https://api.ecomscan.io/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)

Terraform

The ecomscan Terraform provider lets you declare stores, alert routes, and integrity rules as code. Recommended for agencies with > 20 stores.

resource "ecomscan_store" "acmegear" {
  name     = "acmegear.com"
  url      = "https://acmegear.com"
  platform = "magento"

  scan_config {
    interval    = "6h"
    platform    = "magento"
    store_paths = ["/var/www/html"]
  }
}

resource "ecomscan_alert_route" "slack_critical" {
  store_id = ecomscan_store.acmegear.id
  provider = "slack"
  severity = "critical"
  channel  = "#security-alerts"
}

Troubleshooting

Agent not connecting

# Check connectivity
$ korp status

# Test API directly
$ curl -s https://api.ecomscan.io/healthz

# Verify credentials
$ cat ~/.ecomscan/credentials.json

# Run with debug logging
$ korp 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: korp 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

ErrorFix
NOAUTH: credentials not foundRun korp auth login
license expiredRenew at app.ecomscan.io/billing
permission denied: /var/www/htmlRun as the web server user or use sudo
upload failed: store not foundVerify --store-id matches a store in your dashboard
YARA: rules compilation failedUpdate CLI: korp update (rules ship with binary)
Need help? Join the community at community.ecomscan.io or reach out to support@ecomscan.io. Enterprise customers get a dedicated Slack channel.