Back to skill

Security audit

DLT大乐透预测 v4.0

Security checks for vulnerabilities and agentic risk

Overview

This lottery prediction skill is coherent, but it needs Review because it can influence gambling spend and uses unsafe local Python/model loading patterns.

Install only if you are comfortable with a Chinese-language lottery tool that reads a local DLT Excel file, writes/loads local model artifacts, and may show betting recommendations. Treat all predictions as entertainment, not financial guidance, and avoid using it in a shared or untrusted workspace unless the import paths and joblib model loading are fixed.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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)

T09 · Insecure Skill Coding Practices

Error
Location
dlt_predictor_upgraded.py:1030
Finding

Automatic Unsafe Deserialization of a Joblib Model During Predictor Initialization

Content
View full analysis

Vulnerability Details

File Location: dlt_predictor_upgraded.py:980-983 and dlt_predictor_upgraded.py:1030-1038
Vulnerability Type: Unsafe deserialization of a local Joblib/Pickle artifact
Risk Level: High

Vulnerable Code

python
        # 数据文件路径(倒序文件,自动修正)
        self.data_path = '/mnt/d/cp/DLT历史数据_适配模型版.xlsx'
        
        # 尝试从磁盘加载已保存的模型
        self._load_models()
python
    def _load_models(self):
        """从磁盘加载模型(若存在)"""
        import joblib
        model_dir = self._get_model_dir()
        stacker_path = model_dir / 'stacker_.pkl'

        # 若stacker未训练过,尝试加载
        if hasattr(self, 'stacker_') and hasattr(self.stacker_, 'fitted_') and not self.stacker_.fitted_:
            if stacker_path.exists():
                try:
                    self.stacker_ = joblib.load(str(stacker_path))

Technical Analysis

DLTPredictorUpgraded automatically calls _load_models() during object initialization. If models/stacker_.pkl exists, the file is passed directly to joblib.load() without validating its provenance, integrity, ownership, permissions, or expected object structure.

Joblib model files use Python pickle-compatible deserialization. Pickle is an executable serialization format: crafted objects can invoke attacker-selected callables through methods such as __reduce__ while the file is being loaded. Consequently, checking that the file exists does not make it safe.

The vulnerable path is also reachable through the documented DLTFusionComplete entry point. Its constructor creates a DLTPredictorUpgraded instance, which triggers model loading without a separate user confirmation or trust decision.

Attack Path

  1. An attacker obtains the ability to place or replace files under the Skill installation directory. This could occur through a compromised Skill archive, an untrusted shared workspace, an insecure update process, or overly permissiv ...[truncated 1058 chars]
Remediation
View remediation

Remediation Suggestions

  1. Do not deserialize untrusted Joblib or Pickle files. Prefer non-executable model formats supported by the relevant framework.
  2. Make model loading explicit rather than invoking it automatically from the constructor.
  3. If Joblib must be retained, distribute a trusted manifest containing cryptographic hashes or signatures and verify the model before loading it.
  4. Reject symbolic links and ensure the resolved model path remains inside the expected model directory.
  5. Require the model and its parent directory to have trusted ownership and restrictive permissions.
  6. Run model loading in a sandboxed, low-privilege worker without access to credentials, sensitive files, or unrestricted networking.
  7. Validate the loaded object's expected type and metadata after integrity verification. Type validation alone is not sufficient because malicious code executes during deserialization.
  8. Fail closed when integrity verification is unavailable or unsuccessful.

T07 · Tool Hijacking and Spoofing

Warning
Location
dlt_fusion_complete.py:12
Finding

Hard-Coded Search-Path Precedence Permits Python Module Substitution

Content
View full analysis

Vulnerability Details

File Location: dlt_fusion_complete.py:12-21
Vulnerability Type: Python import-path hijacking
Risk Level: Medium

Vulnerable Code

python
import random
import warnings
warnings.filterwarnings('ignore')

sys.path.insert(0, '/home/claw/.openclaw/workspace/skills/dlt_lottery_prediction')

import numpy as np
import pandas as pd
from typing import List, Dict, Tuple, Optional, Any
from collections import Counter, defaultdict

# 导入所有子模块
from dlt_predictor_upgraded import DLTPredictorUpgraded, load_dlt_data

The documentation also instructs users to give the same directory import precedence:

python
import sys
sys.path.insert(0, '/home/claw/.openclaw/workspace/skills/dlt_lottery_prediction')

from dlt_fusion_complete import DLTFusionComplete

Technical Analysis

The module places an absolute, hard-coded directory at the beginning of sys.path. Subsequent imports use top-level module names instead of package-relative imports. Python therefore searches the external hard-coded directory before normal package locations.

If the audited artifact is executed from a different installation directory while the hard-coded directory exists, a same-named module in that directory can replace the intended implementation. Python executes top-level module code immediately during import, so a substituted dlt_predictor_upgraded.py can run arbitrary code before any prediction operation begins.

This behavior also creates ambiguity about which code is actually running: review of one artifact does not guarantee that imported modules originate from that artifact.

Attack Path

  1. An attacker gains write access to /home/claw/.openclaw/workspace/skills/dlt_lottery_prediction, such as through shared-workspace permissions, another vulnerable component, or a compromised Skill installation.
  2. The attacker creates or replaces dlt_predictor_upgraded.py in that directory w ...[truncated 1122 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the hard-coded sys.path.insert() operation.

  2. Package and install the project using standard Python packaging.

  3. Use explicit package-relative imports, for example:

    python
    from .dlt_predictor_upgraded import DLTPredictorUpgraded, load_dlt_data
    from .strategy_fusion_engine import StrategyFusionEngine
    
  4. Update the documentation so users import the installed package without manually modifying sys.path.

  5. Verify that the package installation directory and its parent directories are not writable by untrusted users.

  6. If dynamic path configuration is unavoidable, resolve and validate the directory, require trusted ownership and permissions, and append it only after trusted package locations rather than assigning it highest precedence.

  7. Add startup diagnostics or tests that verify imported modules' resolved __file__ paths remain under the expected package root.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (54)

exec() call detected

High
Category
Dangerous Code Execution
Confidence
98% confidence
Finding

The skill uses exec() to perform wildcard imports from module names at runtime after modifying sys.path to include a local modules directory. Although the module names are hardcoded, exec-based importing expands the attack surface by executing arbitrary top-level code from whichever module file is resolved first, and the prior sys.path manipulation makes module hijacking or malicious replacement in that directory more dangerous.

Content

Scanner excerpt · dlt_lottery_skill.py (reported line 51)May include surrounding context.

python
'dlt_compound_betting'
]:
    try:
        exec(f'from {module_name} import *', globals())
        print(f"  ✅ {module_name} 导入成功")
    except ImportError:
        print(f"  ⚠️  {module_name} 导入失败(使用None替代)")

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The document designs a lottery recommendation engine that can influence financial decisions, yet it provides no risk warning, no statement that outcomes are random, and no responsible-use guidance. In a gambling-adjacent context, presenting predictive scoring, ranking, and 'final recommendations' without safeguards can mislead users into overtrusting the system and suffering financial harm.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The file’s natural-language documentation and user-facing strings are entirely in Chinese, including the module description and runtime messages, with no indication that language is configurable or optional. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The docstring at L303-L311 states this method applies a size-ratio constraint centered on 1 large + 1 small, allowing 2:0 or 0:2 only as float. In practice, the condition at L327-L329 merely checks that both numbers fall within the overall 1-12 range partitions, which all normal pairs do, so no actual constraint is enforced.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation at L462-L469 describes selection according to fused scores and optional custom strategy weights. However, the method generates candidates using internal defaults, scores them via score_back_combo, and returns the top result without reading fused_scores at all and without using sw after assignment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring, examples, and metadata are entirely in Chinese, and the file does not indicate that the skill is region-specific or that users may opt into another language. Under the language/locale policy, forcing a specific language without user choice or clear justification is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Validation error strings and test output visible to users are hardcoded in Chinese throughout the code. Because the file provides no locale selection mechanism or documented regional limitation, these user-facing strings impose a language choice by default.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Natural-language strings throughout the file, including class docstrings and report output, are written in Chinese and the generated report text is fixed to that locale. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is explicitly justified.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The class docstring states '每个池生成6+4复式(6个前区+4个后区)', implying every pool method produces 6 front and 4 back numbers. However, the pool methods pool_hot, pool_cold, pool_balanced, pool_game_theory, and pool_genetic all default to front_k=5 and back_k=2, so the documented behavior contradicts the actual default implementation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill generates concrete lottery betting recommendations and frames them as optimized strategies without providing a clear warning that the output is not predictive and may cause financial loss. In this skill context, that is more dangerous because the surrounding language ('期望回报', '推荐投注', '稳定中奖') can increase user trust and encourage risky gambling behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module title, docstrings, and user-facing console messages are written entirely in Chinese, indicating a fixed language experience. There is no natural-language indication that users can choose another language or that the skill is intentionally limited to a Chinese-only regional context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file’s natural-language description presents the skill entirely in Chinese and does not indicate that users may interact in other languages or opt into this locale. Under the policy for natural-language violations, forcing a specific language without user opt-in is a reportable issue unless clearly justified as region-specific.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The argument parser documents --top-k as the predict command's quantity parameter, but DLTLotterySkill.predict is defined to accept n_per_group and strategy, not top_k. The CLI then calls skill.predict(top_k=args.top_k), which contradicts the advertised command behavior and will fail at runtime instead of producing predictions.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The CLI treats skill.predict(...) as if it returns an iterable of prediction items with keys like 方案编号, 前区号码, 后区号码, and 置信度. However, the implemented predict() returns a dictionary containing fields such as total_draws, strategy, and recommendations, so the command's documented behavior and code expectations actively conflict.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The _save_models method creates a models directory and writes multiple pickle files to disk using joblib.dump. Although there is a success print after saving, there is no advance disclosure or confirmation that running the skill will persist model artifacts locally, which is a user-impacting file write operation.

Content

No source excerpt is available for this finding.

Insecure deserialization: joblib.load()

Medium
Category
Dangerous Code Execution
Confidence
95% confidence
Finding

The code uses joblib.load() to deserialize a model object from disk without any integrity verification, type restriction, or trust boundary enforcement. joblib relies on pickle-compatible deserialization, so a tampered stacker_.pkl file can execute arbitrary Python code at load time, making this a real code execution risk rather than a mere reliability issue.

Content

Scanner excerpt · dlt_predictor_upgraded.py (reported line 1038)May include surrounding context.

python
if hasattr(self, 'stacker_') and hasattr(self.stacker_, 'fitted_') and not self.stacker_.fitted_:
            if stacker_path.exists():
                try:
                    self.stacker_ = joblib.load(str(stacker_path))
                    if hasattr(self.stacker_, 'fitted_') and self.stacker_.fitted_:
                        print(f"  [模型加载] StackingMetaLearner 已加载 (fitted={self.stacker_.fitted_})")
                except Exception as e:

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Comments in predict at L1339-L1341 and L1357 describe auto-loading with reverse-order correction. But predict delegates to load_dlt_data(), whose current implementation no longer reverses data and instead assumes the file is already in forward order, creating an intent/documentation contradiction within the module.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The docstring at L1741-L1745 states that the Excel data is in reverse order and that the function will detect and convert it to forward chronological order. However, the implementation comment at L1803-L1804 says the file is already forward-ordered and that all reversal logic was removed, so the documentation actively contradicts the actual behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This Python file contains its primary module docstring entirely in Chinese, establishing the skill's interface/documentation in a single language with no indication that users can choose another locale. The policy explicitly flags language or locale constraints when a skill forces a specific language without user opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The initialization print statements are user-visible runtime messages and are hardcoded in Chinese, with no mechanism for locale selection or fallback. This creates a natural-language policy issue because the skill effectively forces one language on all users.

Content

No source excerpt is available for this finding.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The prize mapping is internally inconsistent for the (3,0) case: the PRIZE_RULES table defines (3,0) twice, and in Python the later entry overwrites the earlier one. That means users may be told the wrong prize name or amount for a valid outcome, which can corrupt financial or evaluation results even though this is not a code-execution issue.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module docstring and all user-facing descriptive text are written only in Chinese, presenting the skill as Chinese-language only. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale limitation is explicitly justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The report strings returned to users are all fixed in Chinese, such as the title, labels, and warning text. This enforces a single language in user-visible output without any choice mechanism or documented justification.

Content

No source excerpt is available for this finding.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.