← iran-bourse-mcp@0.5.0

Propose a patch

A fix the maintainer can act on, with the evidence attached. It opens under your GitHub account in your browser; KillerSkills holds no token and never modifies the package. The fix is verified the only way we verify anything: the next crawl re-runs the new version in the honeypot. 78 · Caution

Evidence

The sandbox observed nothing beyond the static findings; the proposal cites those.

Diff · removes 34 caught lines

Download .patch
diff --git a/benchmarks/grade.py b/benchmarks/grade.py
--- a/benchmarks/grade.py
+++ b/benchmarks/grade.py
@@ -32,1 +32,0 @@
-return str(text or "").replace("ي", "ی").replace("ك", "ک").replace(" ", "").replace("‌", "")
diff --git a/benchmarks/tasks.json b/benchmarks/tasks.json
--- a/benchmarks/tasks.json
+++ b/benchmarks/tasks.json
@@ -20,1 +20,0 @@
-"question_fa": "برای نماد «فولاد» در روز دوشنبه ۱۱ آبان ۱۴۰۵ (2026-11-02): میانگین وزنی قیمت (VWAP) از روی تک‌تک معاملات، تعداد معاملات، حجم بزرگ‌ترین معامله و ساعت آن (HH:MM:SS).",
@@ -42,1 +41,0 @@
-…market-wide", "question_fa": "در آخرین جلسه بازار، بین نمادهایی که بورس آن‌ها را «سهام عادی» طبقه‌بندی کرده (بورس و فرابورس)، ۵ نماد با بیشترین ارزش صف خری…
diff --git a/scripts/gen_assets.py b/scripts/gen_assets.py
--- a/scripts/gen_assets.py
+++ b/scripts/gen_assets.py
@@ -138,1 +138,0 @@
-<text x="64" y="238" font-family="{SANS}" font-size="22" fill="{MUTED}" unicode-bidi="plaintext">بورس تهران، برای ایجنت‌های هوش مصنوعی</text>
@@ -276,1 +275,0 @@
-<text x="80" y="396" font-family="{SANS}" font-size="32" fill="{MUTED}" unicode-bidi="plaintext">بورس تهران، برای ایجنت‌های هوش مصنوعی</text>
diff --git a/scripts/tool_groups.py b/scripts/tool_groups.py
--- a/scripts/tool_groups.py
+++ b/scripts/tool_groups.py
@@ -20,1 +20,0 @@
-"market_status": "وضعیت بازار", "market_overview": "نمای کلی بازار", "indices": "شاخص‌ها و شاخص صنایع",
@@ -21,1 +20,0 @@
-"market_watch": "دیده‌بان کل بازار (سهام، صندوق، اوراق، اختیار، آتی)", "top_movers": "بیشترین رشد/ریزش، صف خرید و فروش، ورود پول حقیقی",
@@ -22,1 +20,0 @@
-"industry_summary": "خلاصه گروه‌های صنعتی و ورود پول حقیقی هر صنعت", "index_contributors": "بیشترین تأثیر بر شاخص", "market_snapshot": "جدول پایان روز کل بازار",
@@ -23,1 +20,0 @@
-"market_holder_moves": "جابه‌جایی سهامداران عمده", "supervisor_messages": "پیام ناظر", "search_symbol": "جستجوی نماد",
@@ -25,1 +21,0 @@
-"index_history": "تاریخچه و روند لحظه‌ای هر شاخص", "index_constituents": "اعضای شاخص و تأثیر هر نماد", "fund_ranking": "رتبه‌بندی و مقایسهٔ صندوق‌های سرمایه‌گذاری",
diff --git a/src/iran_bourse_mcp/server.py b/src/iran_bourse_mcp/server.py
--- a/src/iran_bourse_mcp/server.py
+++ b/src/iran_bourse_mcp/server.py
@@ -40,1 +40,0 @@
-- For the exchange's own rankings (برترین‌ها: block trades, rights, ETFs, options, queues, industries) use top_lists; for who is
@@ -125,1 +124,0 @@
-"""All indices: total, equal-weight, free-float and every industry index with change % (شاخص‌ها و شاخص صنایع)."""
@@ -142,1 +140,0 @@
-…PS, base volume, NAV)")] = "compact", ) -> dict: """Whole-market table (دیده‌بان بازار) of the exchange's own feed: about 3,700 instruments (shares, base mar…
@@ -173,1 +170,0 @@
-"""Per-industry breakdown: traded value, average and cap-weighted change, index effect, queue counts (گروه‌های صنعتی)."""
@@ -263,1 +259,0 @@
-"""Live/last quote with correct change %, volume, value, VWAP, price limits, ranges, P/E and market cap (قیمت لحظه‌ای)."""
diff --git a/src/iran_bourse_mcp/screener.py b/src/iran_bourse_mcp/screener.py
--- a/src/iran_bourse_mcp/screener.py
+++ b/src/iran_bourse_mcp/screener.py
@@ -110,1 +110,0 @@
-_f("open_interest", "num", "contracts", "موقعیت‌های باز", "Open interest of options and futures.", aliases=("buyop",)),
@@ -824,1 +823,0 @@
-Preset("strong_close", "Up more than 3% and closing at the day's high", "بسته‌شدن در سقف روز",
diff --git a/src/iran_bourse_mcp/funds.py b/src/iran_bourse_mcp/funds.py
--- a/src/iran_bourse_mcp/funds.py
+++ b/src/iran_bourse_mcp/funds.py
@@ -1,1 +1,0 @@
-"""Investment-fund universe and ranking (صندوق‌های سرمایه‌گذاری) from the exchange's own fund registry.
@@ -12,1 +11,0 @@
-always 0), and ``name`` is null: the display name is ``mfName`` without the words 'صندوق سرمایه‌گذاری'.
@@ -42,1 +40,0 @@
-13: {"key": "project", "fa": "پروژه‌ای", "official": "پروژه‌ای", "en": ("project",)},
diff --git a/src/iran_bourse_mcp/text.py b/src/iran_bourse_mcp/text.py
--- a/src/iran_bourse_mcp/text.py
+++ b/src/iran_bourse_mcp/text.py
@@ -43,1 +43,0 @@
-text = ascii_digits(text).replace("‌", "").replace(" ", "")
diff --git a/tests/test_derivatives.py b/tests/test_derivatives.py
--- a/tests/test_derivatives.py
+++ b/tests/test_derivatives.py
@@ -329,1 +329,0 @@
-# «کاورد کال‌های برج ۱۰»: every expiry in that Jalali month, not the nearest one
diff --git a/src/iran_bourse_mcp/toplists.py b/src/iran_bourse_mcp/toplists.py
--- a/src/iran_bourse_mcp/toplists.py
+++ b/src/iran_bourse_mcp/toplists.py
@@ -1,1 +1,0 @@
-"""The exchange's own «برترین‌ها» (best-of) lists, shaped for agents.
@@ -40,1 +39,0 @@
-60: "بازار برق آزاد", 64: "بازار مصرف‌کنندگان بزرگ برق", 67: "آتی انرژی", 68: "گواهی سپرده حامل‌های انرژی", 69: "بازار برق سبز",
@@ -129,1 +127,0 @@
-_d("professional_investors", "stocks", T, "ProInvest:1", "بازار سرمایه‌گذاری حرفه‌ای", "Professional investors' market", COLS_MOVERS, aliases=("pro_invest",)),
diff --git a/src/iran_bourse_mcp/codal_reports.py b/src/iran_bourse_mcp/codal_reports.py
--- a/src/iran_bourse_mcp/codal_reports.py
+++ b/src/iran_bourse_mcp/codal_reports.py
@@ -22,1 +22,0 @@
-_ZW = dict.fromkeys(map(ord, "‌‍‎‏­ـًٌٍَُِّْٰٔ"), None)
@@ -31,1 +30,0 @@
-s = unescape(str(s)).translate(_LETTERS).translate(_DIGITS).replace("­", "")
diff --git a/src/iran_bourse_mcp/glossary.py b/src/iran_bourse_mcp/glossary.py
--- a/src/iran_bourse_mcp/glossary.py
+++ b/src/iran_bourse_mcp/glossary.py
@@ -52,1 +52,0 @@
-"شاخص هم‌وزن": {"en": "equal-weight index", "meaning": "Index where every stock has the same weight; reflects the typical stock better than the total index."},
diff --git a/tests/test_funds.py b/tests/test_funds.py
--- a/tests/test_funds.py
+++ b/tests/test_funds.py
@@ -121,1 +121,0 @@
-row = by_reg(fd.shape_fund_ranking({25: sample[25]}))[12352]  # published as '>صندوق سرمایه‌گذاری بازنشستگی تکمیلی ...'
diff --git a/src/iran_bourse_mcp/dates.py b/src/iran_bourse_mcp/dates.py
--- a/src/iran_bourse_mcp/dates.py
+++ b/src/iran_bourse_mcp/dates.py
@@ -187,1 +187,0 @@
-(1, 13): "روز طبیعت (سیزده‌به‌در)",
@@ -201,1 +200,0 @@
-dt.date(2026, 4, 2): "روز طبیعت (سیزده‌به‌در)",
diff --git a/tests/test_indices.py b/tests/test_indices.py
--- a/tests/test_indices.py
+++ b/tests/test_indices.py
@@ -402,1 +402,0 @@
-assert melli["name"].replace("‌", "") == "ملی صنایع مس ایران" and melli["ins_code"] == "35425587644337450"  # letters normalised
diff --git a/tests/test_text.py b/tests/test_text.py
--- a/tests/test_text.py
+++ b/tests/test_text.py
@@ -16,1 +16,0 @@
-assert match_key("می‌نا") == match_key("مینا")
diff --git a/tests/test_status.py b/tests/test_status.py
--- a/tests/test_status.py
+++ b/tests/test_status.py
@@ -148,1 +148,0 @@
-assert (first["symbol"], first["name"], first["date"], first["jdate"], first["time"]) == ("ثنوسا", "نوسازی‌وساختمان‌تهران‌", "2026-11-04", "1405/08/13", "18:45:44")

Zero-context hunks: apply with git apply --unidiff-zero fix.patch on the tagged source of 0.5.0. If the behavior is intended, declare it (host under permissions.network, a line in the README) instead of removing it; the next crawl scores declarations.

Issue / PR body

Title: iran-bourse-mcp: Hidden zero-width characters detected (KillerSkills verdict caution 78)

## What the honeypot observed
KillerSkills ran **[email protected]** in an isolated sandbox (decoy credentials, recording proxy, syscall trace; engine 1.8.1) and scored it **CAUTION 78/100**. Summary: no network, touches nothing outside the project, writes no memory.

- See the findings below.

Full trace and findings: https://killerskills.ai/skills/pypi/iran-bourse-mcp/0.5.0

## Findings with a location
- `benchmarks/grade.py:32` · Hidden zero-width characters detected — benchmarks/grade.py:32 · Hidden zero-width characters detected — may conceal content
- `benchmarks/tasks.json:42` · Hidden zero-width characters detected — benchmarks/tasks.json:42 · Hidden zero-width characters detected — may conceal content
- `scripts/gen_assets.py:138` · Hidden zero-width characters detected — scripts/gen_assets.py:138 · Hidden zero-width characters detected — may conceal content
- `scripts/tool_groups.py:20` · Hidden zero-width characters detected — scripts/tool_groups.py:20 · Hidden zero-width characters detected — may conceal content
- `scripts/gen_assets.py:276` · Hidden zero-width characters detected — scripts/gen_assets.py:276 · Hidden zero-width characters detected — may conceal content
- `benchmarks/tasks.json:20` · Hidden zero-width characters detected — benchmarks/tasks.json:20 · Hidden zero-width characters detected — may conceal content
- `src/iran_bourse_mcp/server.py:125` · Hidden zero-width characters detected — src/iran_bourse_mcp/server.py:125 · Hidden zero-width characters detected — may conceal content
- `src/iran_bourse_mcp/screener.py:824` · Hidden zero-width characters detected — src/iran_bourse_mcp/screener.py:824 · Hidden zero-width characters detected — may conceal content
- `src/iran_bourse_mcp/funds.py:1` · Hidden zero-width characters detected — src/iran_bourse_mcp/funds.py:1 · Hidden zero-width characters detected — may conceal content
- `src/iran_bourse_mcp/text.py:43` · Hidden zero-width characters detected — src/iran_bourse_mcp/text.py:43 · Hidden zero-width characters detected — may conceal content
- `src/iran_bourse_mcp/funds.py:42` · Hidden zero-width characters detected — src/iran_bourse_mcp/funds.py:42 · Hidden zero-width characters detected — may conceal content
- `tests/test_derivatives.py:329` · Hidden zero-width characters detected — tests/test_derivatives.py:329 · Hidden zero-width characters detected — may conceal content

## Proposed change
The attached patch removes the 34 lines above. If the behavior is intended, the fix is to declare it instead: list the host under `permissions.network` (or the MCP manifest) and say in the README why the package needs it; the next crawl will re-score it with the declaration taken into account.

## How this will be verified
Nothing is "verified safe" by assertion. When a new version is published, KillerSkills re-runs it in the honeypot and the verdict page updates; you can trigger it early from the verdict page ("Re-scan after I publish a fix"). Reply here or at [email protected] if you believe the verdict is wrong; disputes are reviewed by a person and the outcome is published on the verdict page.

_Proposed through killerskills.ai/threats by a user of the package, under their own GitHub account. The evidence is public; the package was never modified by KillerSkills._
# or from a terminal, under your own account:
gh repo fork msmahdinejad/iran-bourse-mcp --clone && cd iran-bourse-mcp
curl -s https://killerskills.ai/skills/pypi/iran-bourse-mcp/0.5.0/patch.diff | git apply --unidiff-zero
git checkout -b killerskills/0.5.0 && git commit -am "iran-bourse-mcp: Hidden zero-width characters detected"
gh pr create --fill --body-file <(curl -s https://killerskills.ai/skills/pypi/iran-bourse-mcp/0.5.0/patch.md)

We count proposals opened, not merged: a merge shows up as a new version that the crawl re-runs. Disputes: the maintainer can contest the verdict from its page; a person reviews it and the outcome is published.