Suspicious — Risk Score 45/100
Last scan:1 day ago Rescan
45 /100
rewrite_question
补全上下文并重写用户提问
Skill claims to only rewrite queries but secretly connects to an external IP (47.77.199.56), embeds a default admin JWT credential, queries a Milvus database, and executes Python subprocesses — all undeclared.
Skill Namerewrite_question
Duration65.5s
Enginepi
Use with caution
Block deployment. The hardcoded external IP, embedded JWT token, undeclared Milvus access, and subprocess spawning represent significant hidden functionality that directly contradicts the SKILL.md declaration of network:NONE and no database access.

Findings 7 items

Severity Finding Location
High
Network capability declared as NONE but actual traffic exists Doc Mismatch
SKILL.md declares 'network: NONE' yet rewrite_question.py:472 makes HTTP POST requests to an externally hosted Gemini API at the hardcoded IP 47.77.199.56. The skill description says it only 'rephrases questions' with no mention of LLM API calls or external network communication.
resp = client.post(self.api_url, json=payload, headers=headers)
→ Update SKILL.md to declare network:READ for LLM API calls. Consider documenting the external service endpoint.
rewrite_question.py:472
High
Default JWT token embedded in source code Credential Theft
A default JWT token (BI-eyJ...Ij8pY) is hardcoded in _get_gemini_config() containing userId:'admin' and an expiration of March 2027. While this may be an internal service token, embedding credentials in source code is a security risk and could leak in logs or version control.
os.getenv('GEMINI_TOKEN', _default_token)  # _default_token is the embedded JWT
→ Remove the embedded JWT from source code. Require GEMINI_TOKEN to be set via environment or .env file only.
rewrite_question.py:562
High
Hardcoded external IP address for all LLM communication Data Exfil
The Gemini API endpoint defaults to a raw IP address (47.77.199.56) rather than a DNS hostname. This IP is in Chinese address space (47.77.x.x). The base URL is not configurable via SKILL.md or documented, and all queries — potentially including user data and conversation context — are sent to this address.
base_url = os.getenv('GEMINI_API_URL', 'http://47.77.199.56/api/v1beta')
→ Use a DNS-resolvable hostname instead of a raw IP. Declare the network endpoint in SKILL.md. Consider whether data sent to this external service is within compliance.
rewrite_question.py:559
Medium
Undeclared Milvus database access Priv Escalation
The skill connects to a Milvus vector database (rewrite_question.py:584-596) to fetch QA pairs. The connection supports user/password authentication. SKILL.md declares database:NONE and no mention of database access anywhere in the documentation.
from pymilvus import MilvusClient; client.query(collection_name=collection, ...)
→ Declare database:READ access in SKILL.md if Milvus access is intentional. Document which Milvus collection is queried and what data is retrieved.
rewrite_question.py:584
Medium
Undeclared Python subprocess execution via Node.js wrapper RCE
index.js uses child_process.spawn to execute Python code inline, passing the skill directory and JSON payload as arguments. This is shell/code execution that is not declared in SKILL.md (shell:NONE).
spawn(PYTHON_BIN, ['-c', script, skillDir])
→ Document the shell:WRITE capability if subprocess execution is intentional, or refactor to use a different IPC mechanism.
index.js:62
Medium
Hidden SQL bypass via QA pair matching not documented Doc Mismatch
Path A (rewrite_question.py:227-237) silently outputs SQL when a user query matches a QA pair in Milvus — bypassing the normal rewriting flow entirely. The rewritten query is unchanged, but matched_sql contains a full SQL statement. This 'shortcut' behavior is not described in SKILL.md.
if matched_qa: ... return RewriteOutput(..., is_qa_matched=True, matched_sql=updated_sql)
→ Document the QA pair matching behavior in SKILL.md, including that SQL can be directly output.
rewrite_question.py:227
Low
No dependency pinning — uses httpx, pymilvus, python-dotenv without versions Supply Chain
No requirements.txt, pyproject.toml, or package.json exists. The code imports httpx, pymilvus, python-dotenv with no version constraints, making it vulnerable to dependency confusion or supply chain attacks.
import httpx
→ Create a requirements.txt or pyproject.toml with pinned versions for all dependencies.
rewrite_question.py:1
ResourceDeclaredInferredStatusEvidence
Filesystem NONE WRITE ✓ Aligned index.js:61 — writes JSON output to file via Python subprocess
Network NONE WRITE ✗ Violation rewrite_question.py:472 — httpx.Client POST to http://47.77.199.56; SKILL.md:net…
Shell NONE WRITE ✗ Violation index.js:62 — spawn(PYTHON_BIN, ['-c', script, skillDir])
Environment NONE READ ✓ Aligned rewrite_question.py:556 — os.getenv for GEMINI_API_KEY, MILVUS_HOST, MILVUS_PASS…
Skill Invoke NONE NONE No cross-skill invocation found
Clipboard NONE NONE No clipboard access
Browser NONE NONE No browser access
Database NONE WRITE ✗ Violation rewrite_question.py:584-596 — PyMilvusClient query() reads from Milvus; supports…
1 High 2 findings
📡
High IP Address 硬编码 IP 地址
47.77.199.56
rewrite_question.py:559
🔗
Medium External URL 外部 URL
http://47.77.199.56/api/v1beta
rewrite_question.py:559

File Tree

3 files · 41.2 KB · 943 lines
Python 1f · 769L JavaScript 1f · 128L Markdown 1f · 46L
├─ 📜 index.js JavaScript 128L · 4.5 KB
├─ 🐍 rewrite_question.py Python 769L · 35.3 KB
└─ 📝 SKILL.md Markdown 46L · 1.4 KB

Dependencies 4 items

PackageVersionSourceKnown VulnsNotes
httpx unpinned import No No requirements.txt or pyproject.toml; httpx version uncontrolled
pymilvus unpinned import No Used for Milvus DB access; optional import with try/except
python-dotenv unpinned import No Used for .env loading; optional import with try/except
asyncio built-in stdlib No Standard library, no risk

Security Positives

✓ No base64-encoded payloads piped to shell
✓ No direct credential exfiltration code (credentials sent to intended Gemini API endpoint, not third-party)
✓ No reverse shell, C2, or ransomware patterns found
✓ No cron/scheduled task or persistence mechanisms
✓ No prompt injection instructions in comments
✓ No ~/.ssh, ~/.aws, or .env file reading beyond standard dotenv loading