Back to skill

Security audit

运势计算 (Fortune Luck)

Security checks for vulnerabilities and agentic risk

Overview

This fortune-telling skill is purpose-aligned and disclosed, with modest privacy and dependency hygiene issues users should understand before installing.

Install only if you are comfortable giving the skill your birth date and having it saved locally at ~/.openclaw/fortune_birthday.json. Consider deleting that file when no longer needed, using a restricted local account, and pinning lunar-python to a reviewed version if you install manually.

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
README.md:13
Finding

Unpinned Third-Party Dependency Installation

Content
View full analysis

Vulnerability Details

File Location: README.md:13-17; dependency imported at fortune_luck.py:14-18
Vulnerability Type: Unpinned third-party dependency
Risk Level: Medium

Vulnerable Code Snippet:

bash
pip install lunar-python

Technical Analysis

The installation instructions retrieve the latest available lunar-python release without specifying a reviewed version, lockfile, or cryptographic hash. Consequently, separate installations can resolve to different package versions, and the effective dependency code may change without a corresponding change to this project.

The dependency name is consistent with the lunar_python import, and the audit found no evidence of typosquatting or an intentionally malicious package. The risk instead arises from unconstrained dependency resolution and the absence of integrity verification.

Attack Path

  1. An attacker compromises the package publishing account, upstream distribution infrastructure, or a future dependency release.
  2. The attacker publishes a modified version under the expected package name.
  3. A user follows the documented unpinned installation command.
  4. Package management resolves and installs the attacker-controlled release.
  5. Malicious package code can execute during installation or when fortune_luck.py imports the package.

Impact Assessment

Exploitation would execute code with the privileges of the user or service installing or running the skill. Depending on those privileges, impact could include access to user files, environment variables, application data, and network resources, as well as modification of files writable by that account. The project itself does not request elevated privileges, so this issue does not independently provide administrative or root access.

Remediation
View remediation

Remediation Suggestions

  • Pin lunar-python to a reviewed, exact version in a dependency manifest.
  • Generate and commit a lockfile so installations resolve to reproducible dependency versions.
  • Require package hashes where supported, such as with pip install --require-hashes.
  • Review dependency updates before changing the pinned version.
  • Use automated vulnerability and dependency-integrity scanning in CI.
  • Install dependencies in an isolated virtual environment under a non-privileged account.

T09 · Insecure Skill Coding Practices

Note
Location
fortune_luck.py:25
Finding

Birth Date Stored in Plaintext Without Explicit Restrictive Permissions

Content
View full analysis

Vulnerability Details

File Location: fortune_luck.py:25-26, 45-56
Vulnerability Type: Insecure storage of personal data
Risk Level: Low

Vulnerable Code Snippet:

python
USER_DATA_DIR = os.path.join(os.path.expanduser("~"), ".openclaw")
BIRTHDAY_FILE = os.path.join(USER_DATA_DIR, "fortune_birthday.json")
python
data = {
    "birth_date": birth_date,
    "calendar_type": calendar_type,
}
with open(BIRTHDAY_FILE, "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

Technical Analysis

The skill persists a user's birth date and calendar type as an unencrypted JSON file. The file is created with Python's default open() behavior, so its permissions depend on the process umask and surrounding directory permissions. The implementation does not explicitly enforce owner-only access.

A birth date is personal information and may be useful for identity profiling or account-recovery attacks when combined with other exposed data. Encryption is not always necessary for a local preference file, but explicit access controls are appropriate for personal data.

Exploitation requires another local account or process that can access the user's home directory and the resulting file. On systems with a restrictive umask and properly protected home directory, practical exposure may already be limited.

Attack Path

  1. A user invokes functionality that stores a birth date through save_birthday().
  2. The process creates fortune_birthday.json using permissions inherited from the current umask.
  3. The system has permissive directory permissions or a permissive umask.
  4. Another local user or compromised process reads ~/.openclaw/fortune_birthday.json.
  5. The attacker obtains the stored birth date and calendar type.

Impact Assessment

The direct impact is unauthorized disclosure of personal information belonging to the current user. This does not gra ...[truncated 330 chars]

Remediation
View remediation

Remediation Suggestions

  • Create ~/.openclaw with owner-only permissions, such as mode 0700 on POSIX systems.
  • Create the birthday file atomically with mode 0600 rather than relying solely on the process umask.
  • If an existing file is reused, verify and correct its permissions before writing.
  • Use a temporary file in the same protected directory, flush it, and atomically replace the destination to avoid partial writes.
  • On Windows, apply an access control list restricted to the current user.
  • Document what information is stored, its location, retention behavior, and how users can delete it.
  • Consider making persistence opt-in and avoid storing the birth date when it is only needed for a single calculation.
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (8)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The listed trigger phrases are broad, natural-language requests such as '帮我算运势' and '今天运势怎么样', which can overlap with ordinary conversation and cause the skill to activate unintentionally. In an agent environment, unintended invocation can lead to wrong routing, privacy-relevant context being consumed by the skill, or disruption of expected assistant behavior, even though the skill itself appears non-privileged and low risk.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger phrases are broad, generic requests about luck or daily fortune, which can overlap with normal conversation and cause the skill to activate unintentionally. That increases the chance of unsolicited collection or use of personal data, especially because the skill may then prompt for and persist the user's birthday.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill persistently stores a full birth date in a user directory without clearly disclosing retention, purpose, deletion options, or privacy implications before saving. A birth date is personal data, and undisclosed local persistence can expose users to privacy harm, especially on shared systems or when users do not expect long-term storage.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The module description, installation error, prompts, and CLI messages are all written in Chinese, and the interactive flow assumes Chinese-language use without any opt-in or alternative locale. Under the language/locale policy, forcing a specific language without user choice is a natural-language policy violation unless the locale restriction is clearly justified.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill stores the user's birthday persistently in ~/.openclaw/fortune_birthday.json, which is personal data and remains on disk beyond the current session. This creates an unnecessary privacy risk if the host is shared, backed up, or inspected later, especially since the module's visible purpose is just daily fortune calculation and the storage behavior is not clearly surfaced here.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Birthday data is written to a local file without any visible consent flow, warning, or notice that the information will be stored on disk. Because date of birth is personal information, silent persistence can violate user expectations and increase privacy exposure if another local user or process can access the file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The module docstring is written only in Chinese ("运势查询wrapper"), indicating a language-specific skill presentation without any visible user choice or opt-in. Under the policy, forcing a specific language or locale without offering a choice is a natural-language policy concern.

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 · fortune_luck.py (reported line 319)May include surrounding context.

python
for n in names:
        if hasattr(obj, n):
            try:
                v = getattr(obj, n)()
                if v is not None:
                    return v
            except Exception:

Static analysis

No suspicious patterns detected.