Skip to content

Expand credential file scanning to cover infostealer target paths #9

@MikeeBuilds

Description

@MikeeBuilds

Summary

The forensic analysis documents that traditional malware families (RedLine, Lumma, Vidar) have adapted their search routines to specifically target OpenClaw's unique directory structures. These infostealers now look for:

  • ~/.openclaw/credentials.json (API keys, session tokens)
  • ~/.openclaw/wallet.json (crypto wallet data)
  • ~/.openclaw/.env (environment secrets)
  • ~/.clawdbot/.env (legacy path from pre-rebrand era)
  • ~/.clawdbot/credentials.json (legacy path)

Currently, scan_secrets.py scans ~/.openclaw/ but does not check:

  1. Legacy ~/.clawdbot/ paths (from the Clawdbot/Moltbot rebrand era)
  2. credentials.json specifically
  3. wallet.json specifically
  4. Signal messenger pairing credentials (found in the O'Reilly scan)

Gap Analysis

Current scan_secrets.py scans these paths:

~/.openclaw/openclaw.json           -- CHK-SEC-001
~/.openclaw/exec-approvals.json     -- CHK-SEC-002
~/.openclaw/.clawtasks/             -- CHK-SEC-003
~/.openclaw/skills/                 -- CHK-SEC-003
~/.openclaw/cron/jobs.json          -- CHK-SEC-004
~/Library/LaunchAgents/*.plist      -- CHK-SEC-005
~/.openclaw/.env                    -- CHK-SEC-006

Missing paths (high-value infostealer targets):

~/.openclaw/credentials.json        -- Contains API keys for Anthropic, OpenAI, Slack
~/.openclaw/wallet.json             -- Contains cryptocurrency wallet data
~/.clawdbot/.env                    -- Legacy path, may still contain live secrets
~/.clawdbot/credentials.json        -- Legacy path
~/.clawdbot/config.json             -- Legacy path
~/.moltbot/.env                     -- Moltbot-era legacy path
~/.moltbot/credentials.json         -- Moltbot-era legacy path
~/.openclaw/signal/                 -- Signal pairing credentials (O'Reilly scan)
/tmp/openclaw-*                     -- Temporary files with secrets (O'Reilly scan)

Proposed Changes

1. Add check_credentials_json() -- CHK-SEC-009

def check_credentials_json(config_dir: str, findings: Findings):
    """CHK-SEC-009: Credentials file with API keys."""
    for fname in ("credentials.json", "creds.json"):
        fp = os.path.join(config_dir, fname)
        if os.path.isfile(fp):
            check_file_permissions(fp, findings, "CHK-SEC-009")
            scan_json_file(fp, findings, "CHK-SEC-009", "critical", fname)

2. Add check_wallet_json() -- CHK-SEC-010

def check_wallet_json(config_dir: str, findings: Findings):
    """CHK-SEC-010: Cryptocurrency wallet data."""
    fp = os.path.join(config_dir, "wallet.json")
    if os.path.isfile(fp):
        findings.add(
            "CHK-SEC-010", "critical",
            "Cryptocurrency wallet file found",
            f"File {fp} exists in the OpenClaw config directory. "
            "Wallet files should never be stored alongside agent configuration.",
            f"file={fp}",
            "Move wallet data to a hardware wallet or encrypted vault.",
        )

3. Add check_legacy_paths() -- CHK-SEC-011

LEGACY_DIRS = [
    os.path.expanduser("~/.clawdbot"),   # Original Clawdbot
    os.path.expanduser("~/.moltbot"),     # Moltbot rebrand era
]

def check_legacy_paths(findings: Findings):
    """CHK-SEC-011: Legacy config directories with live secrets."""
    for legacy_dir in LEGACY_DIRS:
        if os.path.isdir(legacy_dir):
            findings.add(
                "CHK-SEC-011", "warn",
                f"Legacy config directory exists: {legacy_dir}",
                f"Directory {legacy_dir} is from a previous OpenClaw rebrand. "
                "It may contain stale API keys and credentials that are still valid.",
                f"directory={legacy_dir}",
                f"Audit {legacy_dir} for secrets, rotate any found, then remove the directory.",
            )
            # Also scan for secrets within
            for fname in (".env", "credentials.json", "creds.json", "config.json"):
                fp = os.path.join(legacy_dir, fname)
                if os.path.isfile(fp):
                    scan_json_file(fp, findings, "CHK-SEC-011", "critical", f"legacy {fname}")

4. Add check_temp_files() -- CHK-SEC-012

def check_temp_files(findings: Findings):
    """CHK-SEC-012: Temporary files with potential secrets."""
    import tempfile
    tmp_dir = tempfile.gettempdir()
    for pattern in ("openclaw-*", "clawdbot-*", "moltbot-*"):
        for fpath in globmod.glob(os.path.join(tmp_dir, pattern)):
            if os.path.isfile(fpath):
                fstat = os.stat(fpath)
                mode = fstat.st_mode
                if mode & (stat.S_IROTH | stat.S_IWOTH):
                    findings.add(
                        "CHK-SEC-012", "critical",
                        f"World-readable temp file: {os.path.basename(fpath)}",
                        f"Temporary file {fpath} is readable by all users. "
                        "The O'Reilly scan found Signal credentials in such files.",
                        f"file={fpath} mode={oct(mode & 0o777)}",
                        f"Remove the file or restrict permissions: chmod 600 {fpath}",
                    )

Infostealer Target Matrix

File Path Targeted By Data Exposed Priority
~/.openclaw/credentials.json RedLine, Lumma, Vidar API keys, OAuth tokens Critical
~/.openclaw/wallet.json Vidar, custom stealers Crypto private keys Critical
~/.clawdbot/.env Lumma (legacy path scan) All env secrets Critical
~/.openclaw/signal/ Custom exfil tools Signal pairing creds High
/tmp/openclaw-* Opportunistic scanners Session tokens, temp keys High
~/.moltbot/ Legacy path scanners Pre-rebrand credentials Medium

References

  • Forensic analysis: "Malware Evolution: Adapting to Agentic Structures"
  • O'Reilly internet scan: "Signal messenger pairing credentials found in globally readable temporary files"
  • malicious-patterns.json clawhavoc_indicators.file_targets already lists ~/.openclaw/credentials.json
  • Forensic analysis: "Domain and brand churn" creating legacy path exposure

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestsecuritySecurity-related issue

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions