T01 · Skill Instruction Hijacking
- Location
scripts/draw_lunar.py:711- Finding
Forced Promotional URL and Donation QR Code in Generated Output
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill largely matches its astrology-chart purpose, but it automatically installs/copies executable dependencies and uses weak temporary-file handling for personal birth data.
Review before installing. Use an isolated Python environment, preinstall a pinned Pillow version yourself, and only run the bundled Windows native Swiss Ephemeris binary if you trust the publisher and package source. Be aware that generated charts include donation/promotional content by default and that birth details may be written to temporary JSON and output image files.
scripts/draw_lunar.py:711Forced Promotional URL and Donation QR Code in Generated Output
scripts/draw_lunar.py:11Automatic Installation of an Unpinned Package at Runtime
scripts/draw_lunar.py:926Predictable Shared Temporary File Allows Race Conditions and File Clobbering
scripts/draw_lunar.py:18Bundled Native Extension Is Activated Without Integrity Verification
Referenced artifact was not completely inspected
| **Swiss Ephemeris** | Bundled as `swisseph.cp314-win_amd64.pyd.dat` |
Referenced artifact was not completely inspected
| **Swiss Ephemeris** | Bundled as `swisseph.cp314-win_amd64.pyd.dat` |
Referenced artifact was not completely inspected
| `seguisym.ttf.dat` | Zodiac symbols ♈♉♊... + planet symbols ☉☽☿... | `.dat` (ClawHub-compatible) |
Referenced artifact was not completely inspected
| `seguisym.ttf.dat` | Zodiac symbols ♈♉♊... + planet symbols ☉☽☿... | `.dat` (ClawHub-compatible) |
Referenced artifact was not completely inspected
| `segoeuisl.ttf.dat` | Cyrillic, latin, digits | `.dat` (ClawHub-compatible) |
Referenced artifact was not completely inspected
| `segoeuisl.ttf.dat` | Cyrillic, latin, digits | `.dat` (ClawHub-compatible) |
Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.
# Get JSON data — write to temp file to avoid console encoding issues
import tempfile
tmp_json = os.path.join(tempfile.gettempdir(), "lunar_analysis_tmp.json")
env = os.environ.copy()
env['PYTHONIOENCODING'] = 'utf-8'
res = subprocess.run(
[sys.executable, os.path.join(script_dir, "lunar_analysis.py")] + analysis_args + ["--output", tmp_json],
Suspicious Unicode normalization or mixed-script content
The documentation states that AI mode renders supplied interpretation text 'without truncation', which can permit oversized untrusted content to flow into rendering. If an upstream agent or input file provides extremely large text, this can cause excessive memory use, rendering failures, denial of service, or unusable output artifacts.
- `string` — plain text interpretation (AI mode)
The renderer (`draw_text_panel`) automatically detects the format and extracts
the text accordingly. AI mode shows full text without truncation; autonomous mode
limits text to keep the chart compact.
## AI Workflow (for OpenClaw agents)
The SKILL.md includes a hard requirement in Russian that agents must always provide extended AI interpretation when possible, and the documented workflow renders the conclusion with --lang ru. This natural-language instruction forces a specific language/locale behavior for agent use without presenting it as a user-selected option, which violates the language/locale policy criteria.
The changelog confirms the same behavior: AI text is displayed in sections 1–8 without truncation. Reiterating this design indicates the renderer intentionally accepts unbounded text from external AI-generated JSON, increasing the risk of denial of service and layout/resource exhaustion when handling adversarial or malformed input.
each with `interpretation` field; `overall` field for section 9 summary only
- **Helper functions `interp_text()` and `show_interp()`** in `draw_text_panel`:
unified extraction of interpretation text from dict, tuple, or string formats
- **AI mode:** full text displayed without truncation in sections 1–8; section 9 shows only `overall`
- **Autonomous mode:** preserved with text limits for compact layout
- **Section 8 (Aspects):** added AI interpretation of transit Moon aspects after the aspect list
- **Conclusion JSON format documented** in SKILL.md with examples for all supported formats
The script installs pillow at runtime via pip if the import fails, which adds package-management and likely network capability during normal execution without user consent. This expands the trust boundary to package indexes and the local Python environment, creating supply-chain and integrity risks if package sources or the environment are compromised.
try:
from PIL import Image, ImageDraw, ImageFont
except ImportError:
subprocess.check_call([sys.executable, "-m", "pip", "install", "pillow", "-q"])
from PIL import Image, ImageDraw, ImageFont
# в”Ђв”Ђ Font + binary setup в”Ђв”Ђ
A renderer should not silently gain package-install and potential network behavior at runtime; doing so materially increases attack surface beyond its chart-rendering purpose. If an attacker can influence package resolution, indexes, or the local Python environment, this behavior could lead to untrusted code execution or environment tampering.
Silently installing a Python package at runtime without warning or confirmation is risky because it changes the host environment and may fetch executable code from external repositories. In restricted or sensitive environments, this can violate least privilege and create an unexpected remote code supply-chain path.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
tmp_json = os.path.join(tempfile.gettempdir(), "lunar_analysis_tmp.json")
env = os.environ.copy()
env['PYTHONIOENCODING'] = 'utf-8'
res = subprocess.run(
[sys.executable, os.path.join(script_dir, "lunar_analysis.py")] + analysis_args + ["--output", tmp_json],
capture_output=True, text=True, timeout=30, cwd=script_dir, encoding="utf-8", env=env
)
The file advertises bilingual support, which is acceptable, but it does not clearly state whether the tool defaults to one language or how locale is selected when --lang is omitted. Because language/locale policy issues apply to natural-language instructions, this is a mild documentation concern if the implementation forces a language without explicit user choice.
Beyond rendering lunar analysis content, the code adds a ClawHub URL and optionally pastes a QR-code-style frame image into the final chart. For an unknown-purpose but apparently analytical renderer, this is an extra capability not inherent to chart generation or interpretation.
The CLI restricts --lang to only "en" and "ru", which is a natural-language locale constraint. The file does not document a policy justification for limiting output to these languages beyond implementation choice, so this may conflict with language-choice expectations.
This code performs a file write when --output is provided, but there is no confirmation prompt or explicit warning near the write operation that user data will be saved to disk. For a code file, file writes are in scope when they lack visible disclosure, and the surrounding docstring only generally mentions outputs without warning that personal birth data and conclusions may be written to a user-specified file.
The script's natural-language interface and reports are effectively limited to English by default, with Russian as the only alternate locale. This can be a language/locale policy concern because the skill imposes a specific output language unless the user knows to opt into the limited alternative.
No suspicious patterns detected.