Neil P. Oxtoby

39 papers A* 1Journal 26Unranked 11
YearRankTypeTitle / Venue / Authors
2026 A* conf
AAAI
Alec Sargood, Lemuel Puglisi, James H. Cole, Neil P. Oxtoby, Daniele Ravì, Daniel C. Alexander
2026 J jnl
J. Open Source Softw.
Isaac Llorente-Saguer, Neil P. Oxtoby
2025 J jnl
NeuroImage
Vikram Venkatraghavan, Damiano Archetti, Pierrick Bourgeat, Chenyang Jiang, Mara ten Kate, Anna Catharina van Loenhoud, Rik Ossenkoppele, Charlotte E. Teunissen, Elsmarieke van de Giessen, Yolande A. L. Pijnenburg, Giovanni B. Frisoni, Béla Weiss, Zoltán Vidnyánszky, Tibor Auer, Stanley Durrleman, Alberto Redolfi, Simon M. Laws, Paul Maruff, Neil P. Oxtoby, André Altmann, Daniel C. Alexander, Wiesje M. van der Flier, Frederik Barkhof, Betty M. Tijms
2025 ed.
LDTM/MMMI/ML4MHD/ML-CDS@MICCAI
Anna Schroder, Xiang Li, Tanveer F. Syeda-Mahmood, Neil P. Oxtoby, Alexandra L. Young, Alessa Hering, Tejas Sudharshan Mathai, Pritam Mukherjee, Sven Kuckertz, Tiantian He, Isaac Llorente-Saguer, Andreas Maier, Satyananda Kashyap, Hayit Greenspan, Anant Madabhushi
2024 J jnl
Medical Image Anal.
Moucheng Xu, Yukun Zhou, Chen Jin, Marius de Groot, Daniel C. Alexander, Neil P. Oxtoby, Yipeng Hu, Joseph Jacob
2023 conf
MICCAI (8)
Tiantian He, Elinor Thompson, Anna Schroder, Neil P. Oxtoby, Ahmed Abdulaal, Frederik Barkhof, Daniel C. Alexander
2023 J jnl
CoRR
Tiantian He, Elinor Thompson, Anna Schroder, Neil P. Oxtoby, Ahmed Abdulaal, Frederik Barkhof, Daniel C. Alexander
2023 J jnl
CoRR
Mou-Cheng Xu, Yukun Zhou, Chen Jin, Marius de Groot, Daniel C. Alexander, Neil P. Oxtoby, Yipeng Hu, Joseph Jacob
2023 J jnl
Brain Informatics
Janice M. Ranson, Magda Bucholc, Donald Lyall, Danielle Newby, Laura Winchester, Neil P. Oxtoby, Michele Veldsman, Timothy Rittman, Sarah J. Marzi, Nathan G. Skene, Ahmad Al Khleifat, Isabelle F. Foote, Vasiliki Orgeta, Andrey Kormilitzin, Ilianna Lourida, David J. Llewellyn
2023 J jnl
IEEE Trans. Medical Imaging
Mou-Cheng Xu, Yukun Zhou, Chen Jin, Marius de Groot, Daniel C. Alexander, Neil P. Oxtoby, Joseph Jacob
2023 J jnl
NeuroImage
Hanyi Chen, Alexandra L. Young, Neil P. Oxtoby, Frederik Barkhof, Daniel C. Alexander, André Altmann
2022 J jnl
CoRR
Mou-Cheng Xu, Yukun Zhou, Chen Jin, Marius de Groot, Daniel C. Alexander, Neil P. Oxtoby, Yipeng Hu, Joseph Jacob
2022 conf
MICCAI (5)
Mou-Cheng Xu, Yukun Zhou, Chen Jin, Marius de Groot, Daniel C. Alexander, Neil P. Oxtoby, Yipeng Hu, Joseph Jacob
2022 J jnl
CoRR
Neil P. Oxtoby
2022 J jnl
Medical Image Anal.
Daniele Ravì, Stefano B. Blumberg, Silvia Ingala, Frederik Barkhof, Daniel C. Alexander, Neil P. Oxtoby
2022 conf
MIDL
Mou-Cheng Xu, Yukun Zhou, Chen Jin, Stefano B. Blumberg, Frederick J. Wilson, Marius de Groot, Daniel C. Alexander, Neil P. Oxtoby, Joseph Jacob
2022 J jnl
CoRR
Mou-Cheng Xu, Yukun Zhou, Chen Jin, Stefano B. Blumberg, Frederick J. Wilson, Marius de Groot, Daniel C. Alexander, Neil P. Oxtoby, Joseph Jacob
2022 J jnl
Frontiers Artif. Intell.
Neil P. Oxtoby, Cameron Shand, David M. Cash, Daniel C. Alexander, Frederik Barkhof
2022 J jnl
NeuroImage
Esther E. Bron, Stefan Klein, Annika Reinke, Janne M. Papma, Lena Maier-Hein, Daniel C. Alexander, Neil P. Oxtoby
2021 J jnl
Frontiers Big Data
Damiano Archetti, Alexandra L. Young, Neil P. Oxtoby, Daniel Ferreira, Gustav Mårtensson, Eric Westman, Daniel C. Alexander, Giovanni B. Frisoni, Alberto Redolfi
2021 J jnl
CoRR
Mou-Cheng Xu, Yukun Zhou, Chen Jin, Stefano B. Blumberg, Frederick J. Wilson, Marius de Groot, Neil P. Oxtoby, Daniel C. Alexander, Joseph Jacob
2021 J jnl
ACM Trans. Comput. Heal.
Maura Bellio, Dominic Furniss, Neil P. Oxtoby, Sara Garbarino, Nicholas C. Firth, Annemie Ribbens, Daniel C. Alexander, Ann Blandford
2021 J jnl
Frontiers Artif. Intell.
Alexandra L. Young, Jacob W. Vogel, Leon M. Aksman, Peter A. Wijeratne, Arman Eshaghi, Neil P. Oxtoby, Steven C. R. Williams, Daniel C. Alexander
2021 J jnl
CoRR
Esther E. Bron, Stefan Klein, Annika Reinke, Janne M. Papma, Lena Maier-Hein, Daniel C. Alexander, Neil P. Oxtoby
2021 J jnl
SoftwareX
Leon M. Aksman, Peter A. Wijeratne, Neil P. Oxtoby, Arman Eshaghi, Cameron Shand, André Altmann, Daniel C. Alexander, Alexandra L. Young
2019 conf
ABCD-NP@MICCAI
Ágoston Mihalik, Mikael Brudfors, Maria Robu, Fabio S. Ferreira, Hongxiang Lin, Anita Rau, Tong Wu, Stefano B. Blumberg, Baris Kanber, Maira Tariq, Mar Estarellas Garcia, Cemre Zor, Daniil I. Nikitichev, Janaina Mourão Miranda, Neil P. Oxtoby
2019 conf
ABCD-NP@MICCAI
Neil P. Oxtoby, Fabio S. Ferreira, Ágoston Mihalik, Tong Wu, Mikael Brudfors, Hongxiang Lin, Anita Rau, Stefano B. Blumberg, Maria Robu, Cemre Zor, Maira Tariq, Mar Estarellas Garcia, Baris Kanber, Daniil I. Nikitichev, Janaina Mourão Miranda
2019 J jnl
CoRR
Razvan V. Marinescu, Arman Eshaghi, Marco Lorenzi, Alexandra L. Young, Neil P. Oxtoby, Sara Garbarino, Sebastian J. Crutch, Daniel C. Alexander
2019 J jnl
NeuroImage
Razvan V. Marinescu, Arman Eshaghi, Marco Lorenzi, Alexandra L. Young, Neil P. Oxtoby, Sara Garbarino, Sebastian J. Crutch, Daniel C. Alexander
2019 J jnl
CoRR
Daniele Ravì, Stefano B. Blumberg, Daniel C. Alexander, Neil P. Oxtoby
2019 conf
MICCAI (3)
Daniele Ravì, Daniel C. Alexander, Neil P. Oxtoby
2019 J jnl
CoRR
Daniele Ravì, Daniel C. Alexander, Neil P. Oxtoby
2019 conf
MICCAI (2)
Razvan V. Marinescu, Marco Lorenzi, Stefano B. Blumberg, Alexandra L. Young, Pere Planell-Morell, Neil P. Oxtoby, Arman Eshaghi, Keir X. Yong, Sebastian J. Crutch, Polina Golland, Daniel C. Alexander
2019 J jnl
CoRR
Razvan V. Marinescu, Marco Lorenzi, Stefano B. Blumberg, Alexandra L. Young, Pere P. Morell, Neil P. Oxtoby, Arman Eshaghi, Keir X. Yong, Sebastian J. Crutch, Daniel C. Alexander
2019 conf
PRIME@MICCAI
Razvan V. Marinescu, Neil P. Oxtoby, Alexandra L. Young, Esther E. Bron, Arthur W. Toga, Michael W. Weiner, Frederik Barkhof, Nick C. Fox, Polina Golland, Stefan Klein, Daniel C. Alexander
2017 conf
IPMI
Razvan V. Marinescu, Arman Eshaghi, Marco Lorenzi, Alexandra L. Young, Neil P. Oxtoby, Sara Garbarino, Timothy J. Shakespeare, Sebastian J. Crutch, Daniel C. Alexander
2015 J jnl
Medical Image Anal.
Alexandra L. Young, Neil P. Oxtoby, Sébastien Ourselin, Jonathan M. Schott, Daniel C. Alexander
2015 conf
IPMI
Alexandra L. Young, Neil P. Oxtoby, Jonathan Huang, Razvan V. Marinescu, Pankaj Daga, David M. Cash, Nick C. Fox, Sébastien Ourselin, Jonathan M. Schott, Daniel C. Alexander
2014 conf
BAMBI
Neil P. Oxtoby, Alexandra L. Young, Nick C. Fox, Pankaj Daga, David M. Cash, Sébastien Ourselin, Jonathan M. Schott, Daniel C. Alexander
redb/extractors/js_extractors/js_xray.py
← Index redb/extractors/js_extractors/js_xray.py python
"""Subprocess wrapper for the bundled js-x-ray Node bridge.

Mirrors `js_deobfuscator.py`: shell out to a Node script with a per-sample
timeout, kill the process group on hang, demote `FileNotFoundError` to debug
(missing tool is routine — the host either has Node + the bundled package
installed or it doesn't), and return a structured result on success.

The bridge lives at `redb/extractors/js_extractors/scripts/js-xray-runner.js`.
Operators install the JS dependency once with `npm install` in that directory
(or override the path with `JS_XRAY_RUNNER_PATH`).

Configuration (env vars):
    JS_XRAY_RUNNER_PATH   Path to the Node bridge script (default: bundled).
    JS_XRAY_TIMEOUT       Seconds before the subprocess is killed. Default: 30.

`run(source, log)` returns `XRayResult(obfuscator, warnings)` on a successful
analysis, or `XRayResult(None, [])` for any non-success path (binary missing,
timeout, parse failure, etc.). The two unsuccessful states are
indistinguishable to the caller on purpose — they all collapse to "no
js-x-ray verdict, fall back to heuristic".
"""

from __future__ import annotations

import json
import os
import signal
import subprocess
import tempfile
from dataclasses import dataclass, field
from typing import List, Optional

# Bundled bridge: redb/extractors/js_extractors/scripts/js-xray-runner.js
_DEFAULT_RUNNER = os.path.join(
    os.path.dirname(__file__), "scripts", "js-xray-runner.js"
)
_DEFAULT_NODE = "node"
_DEFAULT_TIMEOUT_SECS = 30


@dataclass
class XRayResult:
    """Parsed js-x-ray output. `obfuscator` is the recognised family name
    (e.g. "jsfuck", "obfuscator.io") or None when js-x-ray did not flag the
    code. `warnings` carries every {kind, value} pair the analyser produced;
    the heuristic uses it as a corroborating signal. `avg_identifier_length`
    is js-x-ray's own AST-derived figure — used as a fallback for the
    heuristic's `avg_identifier_length<2` strong signal when pyjsparser
    can't parse the source (anything ES2015+ trips it)."""

    obfuscator: Optional[str] = None
    warnings: List[dict] = field(default_factory=list)
    avg_identifier_length: Optional[float] = None

    @property
    def flagged(self) -> bool:
        return self.obfuscator is not None


def _empty() -> XRayResult:
    return XRayResult(obfuscator=None, warnings=[])


def run(source: str, log) -> XRayResult:
    if not source:
        return _empty()

    runner = os.getenv("JS_XRAY_RUNNER_PATH", _DEFAULT_RUNNER)
    node_bin = os.getenv("JS_XRAY_NODE_BIN", _DEFAULT_NODE)
    timeout = int(os.getenv("JS_XRAY_TIMEOUT", str(_DEFAULT_TIMEOUT_SECS)))

    if not os.path.exists(runner):
        log.debug(f"js-x-ray runner not found at {runner}")
        return _empty()

    # Skip the subprocess entirely when the JS dependency isn't installed.
    # Without this, every call to a host that has `node` but never ran
    # `npm install` next to the runner would still fork node, get a require
    # error, and exit nonzero — wasted ~50–200ms per JS sample (and per test).
    runner_dir = os.path.dirname(runner)
    if not os.path.isdir(os.path.join(runner_dir, "node_modules", "@nodesecure", "js-x-ray")):
        log.debug(f"@nodesecure/js-x-ray not installed in {runner_dir}")
        return _empty()

    tmp_path = None
    try:
        with tempfile.NamedTemporaryFile(
            suffix=".js", mode="w", delete=False, encoding="utf-8"
        ) as tmp:
            tmp.write(source)
            tmp_path = tmp.name

        try:
            process = subprocess.Popen(
                [node_bin, runner, tmp_path],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                preexec_fn=os.setsid,
            )
            try:
                stdout, stderr = process.communicate(timeout=timeout)
            except subprocess.TimeoutExpired:
                # Kill the whole process group so any node helpers die too.
                try:
                    os.killpg(os.getpgid(process.pid), signal.SIGTERM)
                    process.wait(timeout=5)
                except Exception:
                    try:
                        os.killpg(os.getpgid(process.pid), signal.SIGKILL)
                    except Exception:
                        pass
                log.warning(f"js-x-ray timed out after {timeout}s")
                return _empty()

            if process.returncode != 0:
                err = stderr.decode("utf-8", errors="replace").strip()
                log.debug(f"js-x-ray exited {process.returncode}: {err}")
                return _empty()

            text = stdout.decode("utf-8", errors="replace").strip()
            if not text:
                return _empty()

            try:
                payload = json.loads(text)
            except json.JSONDecodeError as e:
                log.warning(f"js-x-ray emitted non-JSON output: {e}")
                return _empty()

            obfuscator = payload.get("obfuscator")
            warnings = payload.get("warnings") or []
            if not isinstance(warnings, list):
                warnings = []

            ids_avg = payload.get("idsLengthAvg")
            if not isinstance(ids_avg, (int, float)):
                ids_avg = None

            return XRayResult(
                obfuscator=obfuscator,
                warnings=warnings,
                avg_identifier_length=ids_avg,
            )
        finally:
            if tmp_path:
                try:
                    os.unlink(tmp_path)
                except Exception:
                    pass
    except FileNotFoundError:
        log.debug(f"node binary not found at {node_bin}")
        return _empty()
    except Exception as e:
        log.error(f"js-x-ray subprocess error: {e}")
        return _empty()