Oleksiy Mazhelis

52 papers B 4C 7Misc 2Journal 13Unranked 25
YearRankTypeTitle / Venue / Authors
2018 conf
ICSOB
Eetu Luoma, Gabriella Laatikainen, Oleksiy Mazhelis
2017 C conf
WEBIST
Aleksei Romanov, Alexander Semenov, Oleksiy Mazhelis, Jari Veijalainen
2016 J jnl
Comput. Commun.
Julien Mineraud, Oleksiy Mazhelis, Xiang Su, Sasu Tarkoma
2016 J jnl
Int. J. Innov. Digit. Econ.
Tapio Levä, Mahya Ilaghi, Vilen Looga, Miika Komu, Nicklas Beijar, Oleksiy Mazhelis
2016 J jnl
J. Syst. Softw.
Gabriella Laatikainen, Oleksiy Mazhelis, Pasi Tyrväinen
2016 conf
ISC2
Oleksiy Mazhelis, Antti Hämäläinen, Tomi Asp, Pasi Tyrväinen
2015 J jnl
CoRR
Julien Mineraud, Oleksiy Mazhelis, Xiang Su, Sasu Tarkoma
2015 J jnl
CoRR
Julien Mineraud, Oleksiy Mazhelis, Xiang Su, Sasu Tarkoma
2015 C conf
ICIS
Gabriella Laatikainen, Oleksiy Mazhelis, Pasi Tyrväinen
2015 conf
ICSOB
Teemu Toivanen, Oleksiy Mazhelis, Eetu Luoma
2014 conf
WF-IoT
Oleksiy Mazhelis, Pasi Tyrväinen
2014 J jnl
Decis. Support Syst.
Tapio Levä, Oleksiy Mazhelis, Henna Suomi
2014 J jnl
Decis. Support Syst.
Gabriella Laatikainen, Oleksiy Mazhelis, Pasi Tyrväinen
2013 conf
ISNN (1)
Fengyu Cong, Hannu Hautakangas, Jukka Nieminen, Oleksiy Mazhelis, Mikko Perttunen, Jukka Riekki, Tapani Ristaniemi
2013 conf
ICSOB
Gabriella Laatikainen, Arto Ojala, Oleksiy Mazhelis
2013 conf
AIMS
Oleksiy Mazhelis, Martin Waldburger, Guilherme Sperb Machado, Burkhard Stiller, Pasi Tyrväinen
2013 J jnl
Inf. Softw. Technol.
Oleksiy Mazhelis, Pasi Tyrväinen, Lauri Frank
2012 conf
ICSOB
Oleksiy Mazhelis, Eetu Luoma, Arto Ojala
2012 conf
ICSOB
Oleksiy Mazhelis
2012 conf
NEW2AN
Oleksiy Mazhelis, Eetu Luoma, Henna Warma
2012 J jnl
Inf. Syst. Frontiers
Oleksiy Mazhelis, Pasi Tyrväinen
2012 C conf
CLOSER
Yrjö Raivio, Oleksiy Mazhelis, Koushik Annapureddy, Ramasivakarthik Mallavarapu, Pasi Tyrväinen
2012 conf
IEEE CLOUD
Oleksiy Mazhelis, Gabriella Fazekas, Pasi Tyrväinen
2012 ch.
Telecommunication Economics
Lauri Frank, Eetu Luoma, Oleksiy Mazhelis, Mirja Pulkkinen, Pasi Tyrväinen
2011 B conf
Discovery Science
Oleksiy Mazhelis, Indre Zliobaite, Mykola Pechenizkiy
2011 C conf
CLOSER
Oleksiy Mazhelis, Pasi Tyrväinen, Tan Kuan Eeik, Jari Hiltunen
2011 C conf
UIC
Mikko Perttunen, Oleksiy Mazhelis, Fengyu Cong, Mikko Kauppila, Teemu Leppänen, Jouni Kantola, Jussi Collin, Susanna Pirttikangas, Janne Haverinen, Tapani Ristaniemi, Jukka Riekki
2011 B conf
Intelligent Vehicles Symposium
Oleksiy Mazhelis
2011 conf
EUROMICRO-SEAA
Oleksiy Mazhelis, Pasi Tyrväinen
2010 conf
INC
Oleksiy Mazhelis, Hannakaisa Isomäki
2010 conf
ICSOB
Oskari Miettinen, Oleksiy Mazhelis, Eetu Luoma
2010 conf
ICSOB
Eetu Luoma, Oleksiy Mazhelis, Pertti Paakkolanvaara
2010 conf
ITSC
Oleksiy Mazhelis
2008 conf
ICSOFT (SE/MUSE/GSDCA)
Oleksiy Mazhelis, Pasi Tyrväinen, Jarmo Matilainen
2008 conf
INC
Oleksiy Mazhelis, Hannakaisa Isomäki
2007 J jnl
Comput. Secur.
Oleksiy Mazhelis, Seppo Puuronen
2007 B conf
ARES
Oleksiy Mazhelis, Seppo Puuronen
2007 J jnl
ARIMA J.
Oleksiy Mazhelis
2007 conf
WEBIST (3)
Mirja Pulkkinen, Oleksiy Mazhelis, Pentti Marttiin, Jouni Meriluoto
2006 conf
HICSS
Oleksiy Mazhelis, Jari A. Lehto, Jouni Markkula, Mirja Pulkkinen
2006 C conf
ICICS
Oleksiy Mazhelis, Seppo Puuronen, Mika Raento
2006 Misc conf
SEC
Oleksiy Mazhelis, Seppo Puuronen, Mika Raento
2006 J jnl
South Afr. Comput. J.
Oleksiy Mazhelis
2006 conf
WOSIS
Oleksiy Mazhelis, Anton Naumenko
2005 J jnl
Inf. Manag. Comput. Security
Oleksiy Mazhelis, Jouni Markkula, Jari Veijalainen
2005 B conf
PROFES
Oleksiy Mazhelis, Jouni Markkula, Markus Jakobsson
2004 conf
IICIS
Oleksiy Mazhelis, Seppo Puuronen
2004 conf
ICEIS (4)
Oleksiy Mazhelis, Seppo Puuronen
2004 C conf
ICICS
Oleksiy Mazhelis, Seppo Puuronen, Jari Veijalainen
2002 conf
Certification and Security in E-Services
Oleksiy Mazhelis, Alexandr Seleznyov, Seppo Puuronen
2002 Misc conf
SAC
Alexandr Seleznyov, Oleksiy Mazhelis
2001 conf
MMM-ACNS
Alexandr Seleznyov, Oleksiy Mazhelis, Seppo Puuronen
redb/extractors/malcontent.py
← Index redb/extractors/malcontent.py python
import inspect
import json
import subprocess
from typing import Any
from datetime import datetime, timezone

from redb.extractors.enum import Tag
from redb.models.dataclasses import Malcontent
from redb.extractors.extractor import Extractor
from dotenv import load_dotenv
import os

load_dotenv(override=True)


class MalcontentExtractor(Extractor):
    """
    Extractor for malcontent tool from chainguard-dev/malcontent.

    Malcontent discovers supply-chain compromises through context, differential
    analysis, and 14,000+ YARA rules. It analyzes binaries and code to detect
    malicious content and suspicious behavioral patterns.

    Binary can be extracted from Docker image:
        docker cp $(docker create cgr.dev/chainguard/malcontent:latest):/usr/bin/mal /usr/local/bin/mal

    Stores full JSON output for materialized view extraction.
    """

    # Cache version at class level to avoid repeated subprocess calls
    _cached_version = None

    def __init__(
        self,
        filepath,
        log,
        exporters=None,
        index_prefix=None,
        elastic_index=None,
        known_benign=False,
        known_malicious=False,
    ):
        super().__init__(
            filepath,
            log,
            exporters,
            index_prefix,
            elastic_index,
            known_benign,
            known_malicious
        )
        self.malcontent = None

    @classmethod
    def _get_malcontent_version(cls, log) -> str:
        """Get malcontent version, cached at class level."""
        if cls._cached_version is not None:
            return cls._cached_version

        malcontent_path = os.getenv("MALCONTENT_PATH", "/usr/local/bin/mal")
        try:
            result = subprocess.run(
                [malcontent_path, "--version"],
                capture_output=True,
                text=True,
                timeout=10
            )
            version_output = result.stdout.strip()
            if result.returncode == 0 and version_output:
                # Parse "malcontent version v1.21.5" -> "1.21.5"
                if version_output.startswith("malcontent version v"):
                    version_output = version_output[len("malcontent version v"):]
                elif version_output.startswith("malcontent version "):
                    version_output = version_output[len("malcontent version "):]
                cls._cached_version = version_output
            else:
                cls._cached_version = "unknown"
        except Exception as e:
            log.warning(f"Could not get malcontent version: {e}")
            cls._cached_version = "unknown"

        return cls._cached_version

    def _extract_malcontent(self):
        self.log.debug(inspect.currentframe().f_code.co_name)
        TIMEOUT = int(os.getenv("MALCONTENT_TIMEOUT", "300"))
        malcontent_path = os.getenv("MALCONTENT_PATH", "/usr/local/bin/mal")

        malcontent_command = [malcontent_path, "analyze", "--format=json", self.filepath]

        import signal

        try:
            process = subprocess.Popen(
                malcontent_command,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
                preexec_fn=os.setsid
            )

            try:
                stdout, stderr = process.communicate(timeout=TIMEOUT)
                if process.returncode != 0:
                    self.log.error(f"Error running malcontent, return code: {process.returncode}, stderr: {stderr}")
                    return {}
            except subprocess.TimeoutExpired:
                self.log.warning(f"The malcontent command timed out after {TIMEOUT} seconds, terminating process group")
                try:
                    os.killpg(process.pid, signal.SIGTERM)
                    try:
                        process.wait(timeout=3)
                    except subprocess.TimeoutExpired:
                        self.log.warning("Process didn't terminate with SIGTERM, sending SIGKILL")
                        os.killpg(process.pid, signal.SIGKILL)
                    process.wait()
                except (ProcessLookupError, OSError) as e:
                    self.log.warning(f"Error while killing process: {e}")
                return {}

            try:
                malcontent_output = json.loads(stdout)
            except json.JSONDecodeError as e:
                self.log.error(f"Error parsing malcontent output: {e}")
                return {}

            # Unwrap the Files/<path> structure to get the inner content
            # Structure is: {"Files": {"/path/to/file": {<actual content>}}}
            files_dict = malcontent_output.get("Files", {})
            if not files_dict:
                self.log.warning("Malcontent output has no 'Files' key")
                return {}

            # Get the first (and only) file's content
            file_content = next(iter(files_dict.values()), {})
            if not file_content:
                self.log.warning("Malcontent output has empty file content")
                return {}

            # Extract risk score and level from the unwrapped content
            risk_score = file_content.get("RiskScore", 0)
            risk_level = file_content.get("RiskLevel", "")

            version = self._get_malcontent_version(self.log)

            self.malcontent = Malcontent(
                malcontent_dump=json.dumps(file_content),
                version=version,
                risk_score=risk_score,
                risk_level=risk_level
            )
            self.log.debug(f"Malcontent analysis complete, version={version}, risk={risk_level}({risk_score})")

        except Exception as e:
            self.log.error(f"Unexpected error in malcontent extraction: {str(e)}")
            if 'process' in locals() and process.poll() is None:
                try:
                    os.killpg(process.pid, signal.SIGKILL)
                    process.wait()
                except:
                    pass
            return {}

    def prepare_export_data(self, exporter_type: str) -> Any:
        if exporter_type == "ClickHouseExporter":
            current_time = datetime.now(timezone.utc)

            data = [[
                self.sha256,
                current_time,
                self.malcontent.version,
                self.malcontent.risk_score,
                self.malcontent.risk_level,
                self.malcontent.malcontent_dump
            ]]

            column_names = [
                'sha256', 'analysis_date',
                'malcontent_version', 'malcontent_risk_score', 'malcontent_risk_level',
                'malcontent_json'
            ]

            column_type_names = [
                'FixedString(64)',
                'DateTime64(3, \'UTC\')',
                'LowCardinality(String)', 'UInt8', 'LowCardinality(String)',
                'JSON'
            ]

            return (data, column_names, column_type_names)

    def get_clickhouse_table(self) -> str:
        return "redb_malcontent"

    def extract(self):
        self.log.debug(inspect.currentframe().f_code.co_name)
        try:
            self._extract_malcontent()
            return self.malcontent
        except Exception as e:
            self.log.error(f"Error extracting malcontent: {e}")
            return None

    def tag(self):
        return Tag.MALCONTENT.value