Back to skill

Security audit

Stocks Quant Assistant

Security checks for vulnerabilities and agentic risk

Overview

This stock-monitoring skill is mostly purpose-aligned, but it includes risky setup and health-check behavior that can expose messaging credentials or create persistent scheduled execution without enough guardrails.

Review carefully before installing. Do not run scripts/health-check.sh with real Feishu credentials unless it is fixed to redact app_secret, avoid the sudo launchctl and setup-sleep.sh power-setting guidance, and prefer a pinned dependency install in an isolated environment. Expect the skill to create scheduled jobs and send market reports to configured Feishu or Telegram recipients.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (6)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/health-check.sh:77
Finding

Health-check output exposes Feishu application credentials

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
setup.py:18
Finding

Shell-command injection through unquoted installation paths

Content
View full analysis
> " + SKILL_DIR + "/logs/cron.log 2>&1\n" "30 10 * * * " + cron_cmd + " >> " + SKILL_DIR + "/logs/cron.log 2>&1\n" "0 13 * * * " + cron_cmd + " >> " + SKILL_DIR + "/logs/cron.log 2>&1\n" "50 14 * * * " + cron_cmd + " >> " + SKILL_DIR + "/logs/cron.log 2>&1\n" ) try: result = run(f'(crontab -l 2>/dev/null | grep -v stock_monitor.py; echo "{cron_line}") | crontab -', timeout=5) ``` ### Technical Analysis The common `run` helper always invokes commands through `subprocess.run(..., shell=True)`. Values derived from `SKILL_DIR`, `PLIST_PATH`, and `sys.executable` are inserted directly into shell command strings without robust shell quoting. If the project is installed under a path containing shell metacharacters, command substitutions, quotes, or separators, the generated setup command can be interpreted as additional shell syntax. The cron registration path is especially exposed because it embeds the values into both a shell pipeline and a double-quoted `echo` command. The cron registration also creates persistent execution entries, so successful injection could be made recurring if malicious content is inserted into the generated crontab. ### Attack Path 1. An attacker supplies or relocates the project into a directory whose name contains shell syntax ...[truncated 937 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
setup.py:30
Finding

Automatic installation of unpinned Python dependencies

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
stock_monitor.py:273
Finding

Fund identifiers and valuation data are transported over plaintext HTTP

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/setup-sleep.sh:7
Finding

Optional setup script performs unnecessary administrator-level power-policy changes

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
SKILL.md:90
Finding

Documentation recommends unnecessary root-level LaunchAgent loading

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (86)

YARA rule 'agent_skill_credential_exfiltration_webhook': AI agent skill credential harvesting followed by webhook or external exfiltration [agent_skills]

Critical
Category
YARA Match
Confidence
85% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · stock_monitor.py (reported line 994)May include surrounding context.

python
join(missing)}", file=sys.stderr)
            print("[ERROR] 请在 config.yaml 或 config.local.yaml 中填写飞书凭证", file=sys.stderr)
            print("[ERROR] 参见 SKILL.md 的「飞书推送配置」章节", file=sys.stderr)
            print(report_text)  # 降级到控制台输出
            return

        try:
            # 1. 获取 tenant_access_token
            token_resp = requests.post(
                'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal',
                json={'app_id': app_id, 'app_secret': app_secret},
                timeout=10
            )
            token_resp.raise_for_status()
            access_token = token_resp.json().get('tenant_access_token', '')
            if not access_token:
                raise ValueError("No access_token returned")

            # 2. 发送消息到 chat_id
            msg_resp = requests.post(
                'https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id',

Tainted flow: 'chat_id' from os.environ.get (line 1025, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · stock_monitor.py (reported line 1005)May include surrounding context.

python
raise ValueError("No access_token returned")

            # 2. 发送消息到 chat_id
            msg_resp = requests.post(
                'https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id',
                headers={'Authorization': f'Bearer {access_token}'},
                json={

Tainted flow: 'bot_token' from os.environ.get (line 1024, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · stock_monitor.py (reported line 1028)May include surrounding context.

python
chat_id = tg_cfg.get('chat_id', os.environ.get('TG_CHAT_ID', ''))
        if bot_token and chat_id:
            try:
                requests.post(
                    f'https://api.telegram.org/bot{bot_token}/sendMessage',
                    json={'chat_id': chat_id, 'text': report_text},
                    timeout=10

Ssd 3

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The script explicitly echoes Feishu credential-related configuration values in plain text during a routine health check. Because health-check commands are commonly run interactively or captured in logs, this creates a practical secret disclosure path that could enable unauthorized use of the Feishu integration or lateral access depending on how the credentials are scoped.

Content

No source excerpt is available for this finding.

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · scripts/setup-sleep.sh (reported line 27)May include surrounding context.

sh
echo "✅ 配置完成!"
echo ""
echo "💡 提示:"
echo "- 如果需要恢复默认设置,运行: sudo pmset -a womp 1 && sudo pmset -a powersave 1"
echo "- 查看详细设置: pmset -g assertions"

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
91% confidence
Finding

Using shell=True in a generic command runner amplifies tool-parameter abuse risk because every caller passes a fully composed shell command string. In this installer, commands include filesystem paths and shell metacharacters for pipelines/redirection, so attacker-controlled installation locations or environment manipulation could turn benign maintenance operations into arbitrary command execution.

Content

Scanner excerpt · setup.py (reported line 22)May include surrounding context.

python
def run(cmd, check=True, timeout=30):
    """执行 shell 命令"""
    result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=timeout)
    if check and result.returncode != 0:
        print(f"[ERROR] Command failed: {cmd}")
        print(f"STDERR: {result.stderr}")

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill self-installs dependencies and proceeds to set up OS-level scheduled execution despite its primary stated purpose being stock monitoring. In agent ecosystems, self-install plus persistence is materially more dangerous because skills are expected to be task-focused and minimally invasive.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The natural-language instructions, warnings, setup steps, and usage guidance are presented exclusively in Chinese throughout the file. This can violate a language/locale policy when a skill forces a specific language without giving users an explicit choice or documenting a justified locale restriction.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

Lines L005-L006 assert that private credential-containing configuration is kept out of published skill contents and that regenerated configs avoid secret material. However, the published SKILL.md then instructs users to place Feishu credentials directly into config.yaml and shows the secret-bearing fields in the example at L057-L063, undermining the stated safety guarantee.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

Reference to the plist file is part of the same persistence mechanism: a LaunchAgent configuration file is a standard macOS autorun artifact. Because the skill claims first-run registration of scheduled tasks and handles private config/credentials, persistence expands the blast radius of any future compromise or misconfiguration.

Content

Scanner excerpt · SKILL.md (reported line 94)May include surrounding context.

解决:

bash
launchctl load ~/Library/LaunchAgents/com.openclaw.stock-monitor.plist
# 如需管理员权限,加上 sudo
sudo launchctl load ~/Library/LaunchAgents/com.openclaw.stock-monitor.plist

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

Reference to the plist file is part of the same persistence mechanism: a LaunchAgent configuration file is a standard macOS autorun artifact. Because the skill claims first-run registration of scheduled tasks and handles private config/credentials, persistence expands the blast radius of any future compromise or misconfiguration.

Content

Scanner excerpt · SKILL.md (reported line 94)May include surrounding context.

解决:

bash
launchctl load ~/Library/LaunchAgents/com.openclaw.stock-monitor.plist
# 如需管理员权限,加上 sudo
sudo launchctl load ~/Library/LaunchAgents/com.openclaw.stock-monitor.plist

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILL.md (reported line 95)May include surrounding context.

解决:

bash
launchctl load ~/Library/LaunchAgents/com.openclaw.stock-monitor.plist
# 如需管理员权限,加上 sudo
sudo launchctl load ~/Library/LaunchAgents/com.openclaw.stock-monitor.plist

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILL.md (reported line 96)May include surrounding context.

解决:

bash
launchctl load ~/Library/LaunchAgents/com.openclaw.stock-monitor.plist
# 如需管理员权限,加上 sudo
sudo launchctl load ~/Library/LaunchAgents/com.openclaw.stock-monitor.plist

Session Persistence

Medium
Category
Rogue Agent
Confidence
89% confidence
Finding

The plist reference at this line is again part of a persistence path, but in the higher-risk context of a sudo-assisted load command. Persistence combined with elevated execution can allow recurring access to files, network destinations, and secrets without further user interaction.

Content

Scanner excerpt · SKILL.md (reported line 96)May include surrounding context.

bash
launchctl load ~/Library/LaunchAgents/com.openclaw.stock-monitor.plist
# 如需管理员权限,加上 sudo
sudo launchctl load ~/Library/LaunchAgents/com.openclaw.stock-monitor.plist

❌ 提示「实时数据获取失败」

Session Persistence

Medium
Category
Rogue Agent
Confidence
89% confidence
Finding

The plist reference at this line is again part of a persistence path, but in the higher-risk context of a sudo-assisted load command. Persistence combined with elevated execution can allow recurring access to files, network destinations, and secrets without further user interaction.

Content

Scanner excerpt · SKILL.md (reported line 96)May include surrounding context.

bash
launchctl load ~/Library/LaunchAgents/com.openclaw.stock-monitor.plist
# 如需管理员权限,加上 sudo
sudo launchctl load ~/Library/LaunchAgents/com.openclaw.stock-monitor.plist

❌ 提示「实时数据获取失败」

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

User-facing strings, comments, logs, and the module description are written entirely in Chinese, which effectively forces a specific language for operators and users. The file does not provide an alternative language option, opt-in mechanism, or justification that this skill is intended only for a Chinese-language environment.

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

python
def check_launchd():
    """检查 LaunchAgent 运行状态"""
    try:
        result = subprocess.run(
            ['launchctl', 'list', LAUNCHD_LABEL],
            capture_output=True, text=True, timeout=10
        )

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

python
try:
        # 加载服务
        result = subprocess.run(
            ['launchctl', 'bootstrap', 'gui/$UID', plist],
            capture_output=True, text=True, timeout=15
        )

Session Persistence

Medium
Category
Rogue Agent
Confidence
76% confidence
Finding

Unlike the other RA2 hits, this line actively bootstraps a user LaunchAgent, which modifies session persistence. In the context of a health-check script, automatically restoring persistence without explicit user confirmation can be dangerous because it changes system state and can keep the monitored skill running indefinitely after a simple check operation.

Content

Scanner excerpt · health_check.py (reported line 50)May include surrounding context.

python
try:
        # 加载服务
        result = subprocess.run(
            ['launchctl', 'bootstrap', 'gui/$UID', plist],
            capture_output=True, text=True, timeout=15
        )
        if result.returncode == 0:

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The docstring states the generated minimal config template contains no private data or credentials, but the template written by the function includes Feishu credential fields such as app_id, app_secret, and chat_id. Even though these are placeholder values rather than real secrets, the documentation actively contradicts the code's behavior about whether credential material is present in the generated file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The health check performs a real outbound Feishu authentication and sends a real message using configured credentials as part of a routine check, without an explicit confirmation at the point of action. In a skill context, that means merely running a 'health check' can trigger external side effects and transmit secrets to a third-party API, which is risky if the user did not expect networked actions.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

This duplicate finding points to the same credential-bearing Feishu token request. The security issue is not the HTTPS call itself, but that a background health check automatically uses and transmits secrets externally without a strong consent boundary.

Content

Scanner excerpt · health_check.py (reported line 173)May include surrounding context.

python
chat_id = feishu.get('chat_id')
        
        # 获取 token
        resp = requests.post(
            'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal',
            json={'app_id': app_id, 'app_secret': app_secret},
            timeout=10

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

This duplicate finding points to the same credential-bearing Feishu token request. The security issue is not the HTTPS call itself, but that a background health check automatically uses and transmits secrets externally without a strong consent boundary.

Content

Scanner excerpt · health_check.py (reported line 173)May include surrounding context.

python
chat_id = feishu.get('chat_id')
        
        # 获取 token
        resp = requests.post(
            'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal',
            json={'app_id': app_id, 'app_secret': app_secret},
            timeout=10

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

This duplicate finding refers to the same live message send operation. The dangerous aspect in context is the unprompted external side effect and disclosure of activity timing/state to a third-party messaging platform during a nominal health check.

Content

Scanner excerpt · health_check.py (reported line 185)May include surrounding context.

python
# 发送测试
        msg = f"✅ 股票监控定时任务健康检查\n时间: {datetime.now().strftime('%H:%M:%S')}\n状态: 一切正常"
        resp = requests.post(
            'https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id',
            headers={'Authorization': f'Bearer {token}'},
            json={

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

This duplicate finding refers to the same live message send operation. The dangerous aspect in context is the unprompted external side effect and disclosure of activity timing/state to a third-party messaging platform during a nominal health check.

Content

Scanner excerpt · health_check.py (reported line 185)May include surrounding context.

python
# 发送测试
        msg = f"✅ 股票监控定时任务健康检查\n时间: {datetime.now().strftime('%H:%M:%S')}\n状态: 一切正常"
        resp = requests.post(
            'https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id',
            headers={'Authorization': f'Bearer {token}'},
            json={