T01 · Skill Instruction Hijacking
- Location
scripts/draw_wheel.py:37- Finding
Default Promotional URL and QR Code Injection into Generated Charts
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This astrology chart skill mostly matches its stated purpose, but it auto-installs software at runtime and adds a default QR/donation frame to generated charts.
Review before installing. This skill performs the advertised astrology calculation and rendering, but run it only in an environment where you are comfortable with a bundled native Windows extension and avoid relying on its runtime auto-install behavior. Install Pillow yourself in an isolated environment, inspect or disable the default QR/frame before sharing generated charts, and avoid processing third-party birth data or AI conclusion files without consent.
scripts/draw_wheel.py:37Default Promotional URL and QR Code Injection into Generated Charts
scripts/draw_wheel.py:10Automatic Installation of an Unpinned Dependency at Runtime
scripts/draw_wheel.py:767Path Traversal Through Unsanitized Output Name
Referenced artifact was not completely inspected
| `scripts/swisseph.cp314-win_amd64.pyd.dat` | Bundled Swiss Ephemeris binary (2 MB) | MSVC++ Redist |
The README explicitly describes a workflow where birth date, birth time, birth location, and derived chart data are sent to an AI for analysis, but it does not warn users that this is sensitive personal data or advise on safe handling, retention, or third-party disclosure. Because birth data is personally identifying and potentially sensitive, users may unknowingly transmit it to external models, logs, or shared files without informed consent or privacy safeguards.
Suspicious Unicode normalization or mixed-script content
The text explicitly states that draw_wheel.py only calls natal_chart_swe.py and renders returned data, implying a narrowly scoped renderer. Elsewhere in the same file, the documented CLI for draw_wheel.py includes --conclusion FILE and --frame FILE, and the changelog says a QR code/frame now renders by default, which means the renderer also ingests arbitrary local files beyond natal_chart_swe.py JSON output.
Calling the tool 'Renderer only' suggests it merely transforms natal chart data into an image. However, the quick reference immediately below documents --conclusion FILE and --frame FILE inputs, and the changelog notes default QR/frame rendering, showing the script also consumes unrelated local content and incorporates it into the output.
Output size or generation rate is not bounded. Unbounded output enables denial-of-service through resource exhaustion, log flooding, or context-window stuffing.
- **Zodiac symbols instead of text abbreviations**: wheel now shows ♈♉♊♋♌♍♎♏♐♑♒♓ instead of AR/TA/GE/etc.
- **2x resolution**: canvas is now 2840×1800 (was 1420×900), all fonts and elements scaled proportionally
- **Planet legend moved to bottom-left**: no longer overlaps the chart wheel; placed below info box
- **Full interpretation fits**: larger text panel (1040px) with bigger fonts ensures all 12 houses + aspects render without truncation
- Added get_symbol_font() helper: uses Segoe UI Symbol for reliable zodiac glyph rendering
- Version bumped: 3.1.0 → 3.2.0
A chart-rendering script should not silently acquire new code from the internet at runtime, because that introduces a broader capability than its stated purpose and changes the host environment. Even if intended for convenience, it permits external dependency execution and undermines reproducibility and reviewability.
The script automatically runs pip install at runtime without user consent, causing network access and code retrieval from a package index during normal execution. This expands the trust boundary from the local skill to external package infrastructure and can result in unreviewed code execution or environment modification.
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
_ttf_dir = os.path.dirname(os.path.abspath(__file__))
Silent package installation is risky because users are not informed that execution may download and install software, modify the Python environment, and run third-party package code. In an agent skill context, undisclosed environment-changing behavior is especially concerning because it exceeds user expectations for a rendering utility.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
else:
print(f"Warning: frame not found at {frame_path}")
res = subprocess.run([sys.executable, os.path.join(_SCRIPTDIR,"natal_chart_swe.py"),
args.date, args.time, args.city, "--json"],
capture_output=True, text=True, timeout=30, cwd=_SCRIPTDIR, encoding="utf-8")
if res.returncode != 0: print("Error:", res.stderr or res.stdout); sys.exit(1)
The docstring frames this file as producing a natal chart wheel and panels, but the code launches a separate Python script rather than only rendering provided data. Spawning external processes is a significant capability that is not signaled by the file's stated role as a drawing script.
This code file contains user-facing strings, labels, and examples entirely in Russian, and the CLI usage/help also assumes Russian-language interaction. Under the policy rule for natural-language violations, forcing a specific language without user opt-in is a reportable locale policy issue.
For markdown files, SQP-2 applies when the documentation omits warnings about behaviors that could affect user data or system integrity. These lines state that the skill auto-restores .ttf files on first run via shutil.copy2, which implies writing files to disk, but the changelog provides no caution or disclosure about that side effect.
The default city is set to a Russian locale value while the script otherwise supports both English and Russian, which embeds a locale assumption into the user experience. This can conflict with language/locale policy expectations because the user is not explicitly opting into a region-specific default or being told why that locale is chosen.
The script saves a generated image file to a hard-coded location on disk, which is a file write affecting user data/workspace state. While it prints the path after saving, there is no earlier warning, prompt, or descriptive comment near the save behavior informing the user where output will be written.
This code embeds only two fixed locale datasets, Russian and English, and does not contain any natural-language indication that the user can choose or opt into a language. Under the policy, locale constraints can be a concern when a skill effectively enforces specific languages without explicit user choice or justification.
Detected: suspicious.dynamic_code_execution