Back to skill

Security audit

Destiny Fusion Pro

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent offline astrology report skill with local calculation scripts and no evidence of exfiltration, persistence, or hidden system changes.

Reasonable to install if you are comfortable running a local Python astrology-report script. Use a virtual environment, pin and review dependencies before installing iztro-py, cairosvg, pillow, lunar-python, or iztro, and be aware that chart output may write a local SVG/JPG file.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T08 · Insecure Dependencies

Warning
Location
scripts/fortune_fusion.py:285
Finding

Unpinned Third-Party Dependency Installation Guidance

Content
View full analysis
Any: try: from iztro_py import astro except ModuleNotFoundError as exc: raise RuntimeError("未安装 iztro-py,请先安装:pip install iztro-py") from exc return astro ``` ```python def render_jpg_cairosvg(svg: str, quality: int = 92) -> bytes: try: import cairosvg except ModuleNotFoundError as exc: raise RuntimeError("生成 JPG 需要 cairosvg,请先安装:pip install cairosvg") from exc try: from PIL import Image except ModuleNotFoundError as exc: raise RuntimeError("生成 JPG 需要 pillow,请先安装:pip install pillow") from exc ``` ```javascript #!/usr/bin/env node import { astro } from 'iztro'; ``` ### Technical Analysis The runtime error messages instruct users to install `iztro-py`, `cairosvg`, and `pillow` without specifying reviewed versions or integrity hashes. The JavaScript engine also imports `iztro`, while the audited project contains no `package.json`, package-manager lockfile, Python dependency manifest, or hash-locked requirements file. Bare installation commands resolve whatever package version the configured registry currently serves. Consequently, the effective dependency code may differ from the code that was tested or reviewed. This creates a conditional supply-chain risk if a dependency release, package registry, mirror, DNS path, or local package-manager configuration is compromised. The project does not automatically install these packages, and no evidence showed that the named packages are intentionally malicious. Exploitation therefore depends on a user or deployment process following the unpinned installation guidance. ### Attack Path 1. A user invokes functionalit ...[truncated 1278 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/fortune_fusion.py:410
Finding

JavaScript Engine Fails Because the Subprocess Module Is Not Imported

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (15)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill advertises a fully offline workflow and includes a recommended shell command invocation, but it does not declare any explicit tool scope such as allowed tools or permissions. That mismatch means an agent may infer or grant broader shell and file-write capabilities than intended, increasing the chance of unauthorized local command execution or filesystem modification if the skill is invoked in an automation context.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest describes an offline destiny consultation/reporting skill, where local computation and optional chart rendering are expected. However, this code adds a separate capability to spawn a node subprocess to execute another engine, which is not an obvious requirement of the stated purpose and expands execution capability beyond straightforward report generation.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/fortune_fusion.py (reported line 410)May include surrounding context.

python
args.extend(["--year", str(year), "--anchor-date", anchor_date])

    try:
        out = subprocess.check_output(args, text=True)
    except FileNotFoundError as exc:
        raise RuntimeError("当前环境缺少 node,无法启用 JS 备用引擎") from exc
    except subprocess.CalledProcessError as exc:

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The generated report content is entirely hardcoded in Chinese, including titles, explanatory text, and disclaimers, with no option for user language selection. This creates a natural-language locale policy concern because the skill enforces a specific language without opt-in or a clearly documented region-specific constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The call to astro.bySolar hard-codes the locale as zh-CN, which enforces a specific language/locale in the skill's behavior. This is a natural-language policy concern because the file provides no user opt-in, fallback, or documented reason for restricting output to Chinese.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The code executes an external subprocess via subprocess.check_output(args, text=True) to invoke a Node.js-based fallback engine, which is a safety-relevant operation for code files. Although the script's purpose involves astrology calculation, there is no docstring, inline comment, or immediate user-facing disclosure near this operation explaining that an external runtime will be launched.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/fortune_fusion.py (reported line 479)May include surrounding context.

python
def pillar_detail(prefix: str) -> dict[str, Any]:
        return {
            "ganzhi": getattr(ec, f"get{prefix}")(),
            "na_yin": getattr(ec, f"get{prefix}NaYin")(),
            "wu_xing": getattr(ec, f"get{prefix}WuXing")(),
            "shi_shen_gan": getattr(ec, f"get{prefix}ShiShenGan")(),

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/fortune_fusion.py (reported line 480)May include surrounding context.

python
def pillar_detail(prefix: str) -> dict[str, Any]:
        return {
            "ganzhi": getattr(ec, f"get{prefix}")(),
            "na_yin": getattr(ec, f"get{prefix}NaYin")(),
            "wu_xing": getattr(ec, f"get{prefix}WuXing")(),
            "shi_shen_gan": getattr(ec, f"get{prefix}ShiShenGan")(),
            "shi_shen_zhi": list(getattr(ec, f"get{prefix}ShiShenZhi")()),

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/fortune_fusion.py (reported line 481)May include surrounding context.

python
return {
            "ganzhi": getattr(ec, f"get{prefix}")(),
            "na_yin": getattr(ec, f"get{prefix}NaYin")(),
            "wu_xing": getattr(ec, f"get{prefix}WuXing")(),
            "shi_shen_gan": getattr(ec, f"get{prefix}ShiShenGan")(),
            "shi_shen_zhi": list(getattr(ec, f"get{prefix}ShiShenZhi")()),
            "hide_gan": list(getattr(ec, f"get{prefix}HideGan")()),

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/fortune_fusion.py (reported line 482)May include surrounding context.

python
"ganzhi": getattr(ec, f"get{prefix}")(),
            "na_yin": getattr(ec, f"get{prefix}NaYin")(),
            "wu_xing": getattr(ec, f"get{prefix}WuXing")(),
            "shi_shen_gan": getattr(ec, f"get{prefix}ShiShenGan")(),
            "shi_shen_zhi": list(getattr(ec, f"get{prefix}ShiShenZhi")()),
            "hide_gan": list(getattr(ec, f"get{prefix}HideGan")()),
            "xun": getattr(ec, f"get{prefix}Xun")(),

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/fortune_fusion.py (reported line 483)May include surrounding context.

python
"na_yin": getattr(ec, f"get{prefix}NaYin")(),
            "wu_xing": getattr(ec, f"get{prefix}WuXing")(),
            "shi_shen_gan": getattr(ec, f"get{prefix}ShiShenGan")(),
            "shi_shen_zhi": list(getattr(ec, f"get{prefix}ShiShenZhi")()),
            "hide_gan": list(getattr(ec, f"get{prefix}HideGan")()),
            "xun": getattr(ec, f"get{prefix}Xun")(),
            "xun_kong": getattr(ec, f"get{prefix}XunKong")(),

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/fortune_fusion.py (reported line 484)May include surrounding context.

python
"wu_xing": getattr(ec, f"get{prefix}WuXing")(),
            "shi_shen_gan": getattr(ec, f"get{prefix}ShiShenGan")(),
            "shi_shen_zhi": list(getattr(ec, f"get{prefix}ShiShenZhi")()),
            "hide_gan": list(getattr(ec, f"get{prefix}HideGan")()),
            "xun": getattr(ec, f"get{prefix}Xun")(),
            "xun_kong": getattr(ec, f"get{prefix}XunKong")(),
            "di_shi": getattr(ec, f"get{prefix}DiShi")(),

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/fortune_fusion.py (reported line 485)May include surrounding context.

python
"shi_shen_gan": getattr(ec, f"get{prefix}ShiShenGan")(),
            "shi_shen_zhi": list(getattr(ec, f"get{prefix}ShiShenZhi")()),
            "hide_gan": list(getattr(ec, f"get{prefix}HideGan")()),
            "xun": getattr(ec, f"get{prefix}Xun")(),
            "xun_kong": getattr(ec, f"get{prefix}XunKong")(),
            "di_shi": getattr(ec, f"get{prefix}DiShi")(),
        }

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/fortune_fusion.py (reported line 486)May include surrounding context.

python
"shi_shen_zhi": list(getattr(ec, f"get{prefix}ShiShenZhi")()),
            "hide_gan": list(getattr(ec, f"get{prefix}HideGan")()),
            "xun": getattr(ec, f"get{prefix}Xun")(),
            "xun_kong": getattr(ec, f"get{prefix}XunKong")(),
            "di_shi": getattr(ec, f"get{prefix}DiShi")(),
        }

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/fortune_fusion.py (reported line 487)May include surrounding context.

python
"hide_gan": list(getattr(ec, f"get{prefix}HideGan")()),
            "xun": getattr(ec, f"get{prefix}Xun")(),
            "xun_kong": getattr(ec, f"get{prefix}XunKong")(),
            "di_shi": getattr(ec, f"get{prefix}DiShi")(),
        }

    pillars = {

Static analysis

No suspicious patterns detected.