Grades are a hygiene check, not a security guarantee.

MCP, MCP server

Artha Council

Artha Council, an MCP server listed in the PlugVet directory.

Compatibility: Not stated.

Grade C

One Medium finding. Read the findings before installing.

Graded by PlugVetRubric v2

Not a guarantee. A hygiene check of the source at the commit shown, not a security audit.

NETWORK_HOST_FROM_INPUT

Why this grade

  • NETWORK_HOST_FROM_INPUT Medium

    A file takes a URL or endpoint as input and has no fixed host list.

    run.py, line 235 resp = requests.get(

Any High, or two or more Medium findings, give D. One Medium gives C. Low findings or a security Note give B. Each code names a finding behind the letter.

Grades are a hygiene check of the source at the commit shown, on the date checked, not a security audit or a guarantee. The free directory grades are automated. Before release, a PlugVet engineer reviews every paid report and any grade we hold back, including all F grades, against the source code and the evidence we quote.

What was checked

Plain notes from the hygiene checks.

  • Permissions

    Concern

    can delete files.

    PERMISSION_DELETE_FILES

    run.py, line 1230

    proc = subprocess.run(

    artha/test_enhancements.py, line 24

    shutil.rmtree(self.tmp_dir, ignore_errors=True)

    artha/test_enhancements.py, line 122

    shutil.rmtree(self.tmp_dir, ignore_errors=True)

    Show more

    artha_mcp/jobs.py, line 46

    self._processes: dict[str, subprocess.Popen[str]] = {}

    artha_mcp/jobs.py, line 169

    process = subprocess.Popen(

    artha_mcp/jobs.py, line 254

    def _terminate_process_tree(process: subprocess.Popen[str]) -> None:

    artha_mcp/provenance.py, line 96

    completed = subprocess.run(

    dashboard/server.py, line 193

    completed = subprocess.run(

    scripts/artha_source_sync.py, line 69

    return subprocess.run(

    scripts/artha_source_sync.py, line 255

    completed = subprocess.run(

    scripts/robinhood_auto_trade_runner.mjs, line 380

    try { fs.unlinkSync(lockFile); } catch {}

    scripts/robinhood_auto_trade_runner.mjs, line 397

    fs.unlinkSync(lockFile);

    scripts/robinhood_manual_review_runner.mjs, line 245

    try { fs.unlinkSync(lockFile); } catch {}

    scripts/robinhood_manual_review_runner.mjs, line 260

    fs.unlinkSync(lockFile);

    scripts/robinhood_snapshot_sync.mjs, line 467

    fs.unlinkSync(lockFile);

    scripts/robinhood_snapshot_sync.mjs, line 482

    fs.unlinkSync(lockFile);

  • Install and update

    Concern

    dependencies are not pinned.

    INSTALL_UNPINNED

    requirements.txt, line 1

    python-dotenv>=1.2.2

  • Network

    Serious

    accepts a host from input, with no fixed list in this file.

    NETWORK_HOST_FROM_INPUT

    run.py, line 235

    resp = requests.get(

    artha/chatgpt_backend.py, line 146

    return requests.post(

    artha/chatgpt_backend.py, line 191

    response = requests.post(

    Show more

    artha/collector.py, line 1255

    resp = requests.get("https://api.alternative.me/fng/?limit=1&format=json", timeout=10)

    artha/economic_calendar.py, line 96

    def fetch(self, days_ahead: int = 7, days_back: int = 1) -> list[CalendarEvent]:

    artha/economic_calendar.py, line 100

    days_ahead: How many days forward to fetch (default 7)

    artha/economic_calendar.py, line 101

    days_back: How many days back to fetch (for "post" state detection)

    artha/regime_indicators.py, line 327

    resp = requests.get(url, params=params, timeout=10)

    artha/researcher.py, line 300

    response = requests.get(url, headers=headers, timeout=(connect_timeout, read_timeout), stream=True)

  • Secrets

    Concern

    reads a credential or environment file.

    SECRETS_ENV_READ SECRETS_PATH_DOTENV

    artha/claude_sdk.py, line 21

    2. Personal workspace .env (~/.openclaw/workspace-personal/.env)

    artha/claude_sdk.py, line 40

    # Personal workspace .env path for OAuth token fallback

    artha/claude_sdk.py, line 41

    _WORKSPACE_ENV = Path.home() / ".openclaw" / "workspace-personal" / ".env"

    Show more

    artha/claude_sdk.py, line 54

    if os.environ.get("CLAUDE_CODE_OAUTH_TOKEN"):

    artha/claude_sdk.py, line 57

    # Fallback: read from personal workspace .env

    artha/claude_sdk.py, line 66

    logger.info("Loaded OAuth token from personal workspace .env")

    artha/claude_sdk.py, line 71

    "or add it to ~/.openclaw/workspace-personal/.env"

    artha/config.py, line 42

    FMP_API_KEY: str = os.getenv("FMP_API_KEY", "")

    artha/config.py, line 43

    MASSIVE_API_KEY: str = os.getenv("MASSIVE_API_KEY", "") or os.getenv("POLYGON_API_KEY", "")

    artha/config.py, line 44

    FINNHUB_API_KEY: str = os.getenv("FINNHUB_API_KEY", "")

    artha/config.py, line 45

    BENZINGA_API_KEY: str = os.getenv("BENZINGA_API_KEY", "") or os.getenv("ARTHA_BENZINGA_API_KEY", "")

    artha/config.py, line 46

    COINGECKO_API_KEY: str = os.getenv("COINGECKO_API_KEY", "")

    artha/config.py, line 47

    ALPHA_VANTAGE_API_KEY: str = os.getenv("ALPHA_VANTAGE_API_KEY", "")

    artha/config.py, line 48

    FRED_API_KEY: str = os.getenv("FRED_API_KEY", "")

    artha/config.py, line 198

    # Portfolio settings. Deployments should override these examples in .env.

    artha/config.py, line 611

    # ~/.openclaw/workspace-personal/.env (see artha/claude_sdk.py).

  • Agent instructions

    Pass

    No instruction to ignore earlier instructions or to hide a step.

  • Obfuscation

    Note

    a file was over the read cap and was not fully read.

    OBFUSCATION_FILE_OVER_READ_CAP

    artha/scheduler.py, line 1

    """Async scheduler for Artha monitoring and analysis tasks."""

    artha/test_production_hardening.py, line 1

    """Production-hardening tests for calibration, risk, and deterministic engines.

  • Licence

    Pass

    A licence file is present (LICENSE).

  • Maintainer activity

    Pass

    The latest commit is within the last 365 days.

Note

Hygiene check of commit bc3ef17b4ebc. can delete files. dependencies are not pinned. accepts a host from input, with no fixed list in this file. reads a credential or environment file. a file was over the read cap and was not fully read.

Date and source

Date checked:

View source

github.com

Commit graded: bc3ef17b4ebc4a56004fc098209caa39919500f5

This link goes to the original host. PlugVet does not host or check what you download from there, and installing it is your own decision and risk.

Read how this letter is chosen