Back to skill

Security audit

个人日程管理

Security checks for vulnerabilities and agentic risk

Overview

This personal scheduler is not clearly malicious, but it exposes private calendar data and event creation through an unauthenticated network-accessible debug web server.

Install only if you are prepared to treat it as local experimental software: bind the Web server to 127.0.0.1, disable Flask debug mode, add authentication before storing real calendar details, remove the hard-coded Feishu ID, and add confirmation for deletes or updates.

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 (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/web_server.py:22
Finding
Unauthenticated Network Exposure of Calendar Data and Event Creation API<![CDATA[ ## Vulnerability Details **File Location**: `scripts/web_server.py:22-48` **Vulnerability Type**: Missing authentication and unrestricted network binding **Risk Level**: High ### Vulnerable Code ```python @app.route('/api/events') def get_events(): """获取日程列表""" date = request.args.get('date') events = scheduler.list_events(date) return jsonify(events) @app.route('/api/events', methods=['POST']) def create_event(): """创建日程""" data = request.json event_id = scheduler.add_event( title=data.get('title'), start_time=data.get('start_time'), end_time=data.get('end_time'), location=data.get('location'), description=data.get('description') ) return jsonify({'success': True, 'id': event_id}) if __name__ == '__main__': print("="*50) print("日程管理 Web 服务") print("="*50) print("访问地址: http://localhost:8080") print("="*50) app.run(host='0.0.0.0', port=8080, debug=True) ``` ### Technical Analysis The calendar API does not enforce authentication or authorization. The `GET /api/events` endpoint returns stored calendar information, including titles, start and end times, locations, descriptions, and reminder settings. The `POST /api/events` endpoint permits callers to create new events and associated reminder-job records. Although the application prints a localhost URL, it binds to `0.0.0.0`, exposing the service on every available network interface. Any client that can reach TCP port 8080 can therefore invoke these endpoints without presenting credentials. The application also performs no server-side ownership or access-control checks. Consequently, network reachability is treated as sufficient permission to access private calendar information and modify application state. ### Attack Path 1. An attacker identifies a host running the Skill with TCP port 8080 reachable from the local network, container network, or externally exposed interface. 2. The attacker sends ` ...[truncated 1100 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Bind the development server to the loopback interface by default: ```python app.run(host="127.0.0.1", port=8080, debug=False) ``` 2. Add authentication to every calendar endpoint. Use securely generated session identifiers or a suitable established authentication framework. 3. Enforce authorization for every read and mutation operation rather than relying only on authentication. 4. Add CSRF protection to all state-changing browser endpoints. 5. Require an explicit configuration option before permitting LAN or public-interface exposure. 6. Place any intentionally network-accessible deployment behind a reverse proxy that provides TLS, authentication, request limits, and access logging. 7. Validate all JSON fields, including required values, types, maximum lengths, and valid date ranges. 8. Apply rate limits and request-size limits to event-creation endpoints. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/web_server.py:48
Finding
Flask Debugger Exposed on All Network Interfaces<![CDATA[ ## Vulnerability Details **File Location**: `scripts/web_server.py:48` **Vulnerability Type**: Exposed development debugger **Risk Level**: High ### Vulnerable Code ```python app.run(host='0.0.0.0', port=8080, debug=True) ``` ### Technical Analysis The Flask development server is launched with debug mode enabled while listening on every network interface. When an unhandled exception occurs, Flask's debug facilities can expose stack traces, local filesystem paths, source context, configuration details, and runtime state. The interactive Werkzeug debugger is protected by a PIN in common configurations, but it must not be treated as a security boundary. If the PIN is disclosed, derived, disabled, or otherwise bypassed, debugger access can permit arbitrary Python execution with the privileges of the application process. Malformed API input can reach code paths that raise exceptions. For example, `request.json` may not be a dictionary, required event values may be absent, or date strings may fail parsing. Debug mode can then expose detailed exception responses to a remote caller. ### Attack Path 1. An attacker reaches TCP port 8080 because the server listens on `0.0.0.0`. 2. The attacker submits malformed request data to an API endpoint to trigger an unhandled exception. 3. The application returns a debug response containing stack traces and internal implementation details. 4. The attacker uses the disclosed information to map local paths, source files, framework versions, and application behavior. 5. If interactive debugger protection is defeated or its PIN becomes available, the attacker accesses the debugger console. 6. The attacker executes Python code with the operating-system privileges of the Flask process. ### Impact Assessment At minimum, this issue can disclose: - Application source context and stack traces. - Local filesystem paths. - Framework and runtime details. - Configuration and in-process values included in exception contexts. ...[truncated 297 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable debug mode in normal operation: ```python app.run(host="127.0.0.1", port=8080, debug=False) ``` 2. Do not use Flask's development server for a deployed service. Run the application through a maintained production WSGI server. 3. Bind to `127.0.0.1` unless remote access is explicitly required. 4. Add centralized exception handling that returns generic client errors while recording detailed diagnostics only in protected local logs. 5. Validate request content before accessing fields or passing values to the scheduler. 6. Place remotely accessible deployments behind an authenticated TLS reverse proxy and restrict inbound network access with firewall rules. 7. Ensure production settings cannot be overridden into debug mode by untrusted environment variables or request input. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
web/index.html:663
Finding
Stored Cross-Site Scripting Through Event Titles and Locations<![CDATA[ ## Vulnerability Details **File Location**: `web/index.html:663-685`; source endpoint at `scripts/web_server.py:29-38` **Vulnerability Type**: Stored cross-site scripting **Risk Level**: High ### Vulnerable Code The server stores untrusted event fields without validation or output encoding: ```python @app.route('/api/events', methods=['POST']) def create_event(): """创建日程""" data = request.json event_id = scheduler.add_event( title=data.get('title'), start_time=data.get('start_time'), end_time=data.get('end_time'), location=data.get('location'), description=data.get('description') ) return jsonify({'success': True, 'id': event_id}) ``` The client later inserts those stored values directly into `innerHTML`: ```javascript function loadEvents() { fetch('/api/events') .then(r => r.json()) .then(events => { const list = document.getElementById('eventsList'); if (events.length === 0) { list.innerHTML = ` <div class="empty-state"> <div class="empty-icon">📅</div> <div class="empty-text" data-i18n="noEvents">${i18n[currentLang].noEvents}</div> </div> `; } else { list.innerHTML = events.map(e => ` <div class="event-item"> <div class="event-color-bar" style="background: #007AFF"></div> <div class="event-time">${new Date(e[2]).toLocaleTimeString('zh', {hour: '2-digit', minute: '2-digit'})}</div> <div class="event-content"> <div class="event-title">${e[1]}</div> ${e[4] ? `<div class="event-location">📍 ${e[4]}</div>` : ''} </div> </div> `).join(''); } }) .catch(err => console.error ...[truncated 2193 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not insert database-controlled fields through `innerHTML`. 2. Create DOM elements explicitly and assign untrusted values through `textContent`: ```javascript const title = document.createElement('div'); title.className = 'event-title'; title.textContent = e[1]; const location = document.createElement('div'); location.className = 'event-location'; location.textContent = `📍 ${e[4]}`; ``` 3. If rich HTML is an actual requirement, sanitize it using a maintained allowlist-based HTML sanitizer before insertion. 4. Validate event fields on the server, enforcing string types and reasonable maximum lengths. Validation should supplement, not replace, contextual output encoding. 5. Add a restrictive Content Security Policy that disallows inline scripts and inline event handlers. 6. Authenticate the event-creation API so arbitrary network clients cannot persist content. 7. Review every other use of `innerHTML` and ensure that only trusted static markup reaches it. 8. Add automated tests using representative HTML and event-handler payloads to verify that event data is rendered only as text. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:83
Finding
Unpinned Flask Dependency Produces a Non-Reproducible Installation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:83-87` **Vulnerability Type**: Unpinned third-party dependency **Risk Level**: Medium ### Vulnerable Code ```bash pip install flask ``` ### Technical Analysis The installation instructions request Flask without specifying a reviewed version, a constraints file, hashes, or a locked transitive dependency graph. The package installer therefore resolves whichever compatible Flask release and transitive dependencies are available from the configured package index at installation time. This makes installations non-reproducible and allows the code executed by the Skill to change without a corresponding change to the audited project. A newly introduced vulnerable release, compromised dependency release, or unexpected compatibility change could be installed automatically. The reviewed project does not contain evidence of typosquatting or a deliberately malicious dependency. The risk arises from unconstrained dependency resolution and the absence of integrity verification. ### Attack Path 1. A user follows the documented installation command. 2. `pip` contacts the configured package index and resolves the current Flask package and its transitive dependencies. 3. The resolved versions may differ from those used during development or security review. 4. If a resolved release is compromised or contains an exploitable vulnerability, its code is installed into the environment. 5. The application imports Flask when `scripts/web_server.py` runs, executing the installed package with the privileges of the application process. ### Impact Assessment The precise impact depends on the package version resolved at installation time. A compromised or vulnerable dependency could potentially execute code with the user's privileges, access application files, or expose additional network vulnerabilities. Even without package compromise, version drift can cause security fixes, defaults, or application behavior to diffe ...[truncated 42 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Define reviewed direct and transitive dependency versions in a lock file. 2. Use hash verification for downloaded distributions, for example through a generated requirements file containing `--hash` entries. 3. Install dependencies in an isolated virtual environment. 4. Configure a trusted package index explicitly where appropriate. 5. Add automated dependency vulnerability scanning and update dependencies through reviewed pull requests. 6. Document the supported Python version and regenerate the lock file for each supported environment. 7. Avoid broad unbounded version specifications in production installation instructions. ]]>
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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (30)

Tp4

High
Category
MCP Tool Poisoning
Confidence
79% confidence
Finding
该代码与“个人日程管理”中的一部分能力相符,尤其是“自动提醒”。它负责把日程提醒转换为定时任务并保存到本地配置,属于提醒调度的支撑实现。但声明中列出的多项核心能力——自然语言设置、重复日程、Web界面、导入导出——在此代码片段中均未体现。代码的实际行为更窄,主要是本地 cron/提醒任务管理,而不是完整的个人日程管理功能。因此描述对该代码能力有明显过度表述,构成描述与行为不一致。

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
该代码的核心目的仍属于个人日程管理并带有自动提醒,这与描述的主体方向基本一致;但声明中的多项关键功能并未在提供代码中体现,尤其是自然语言设置、重复日程、Web界面、导入导出。repeat_rule 虽出现在方法签名中,但没有被持久化、解析或用于生成重复事件,因此不能算已实现。另一方面,代码实际保存 feishu_user_id,并在提醒任务中携带该字段,表明存在面向飞书用户的提醒集成倾向,这属于描述中未提及的外部服务相关能力。综合看,描述与代码存在明显不一致,应判定为 mismatch。

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill declares executable capabilities such as Python, local file storage, backup creation, and shell-invoked scripts, but does not declare any tool scope or allowed permissions. This weakens review boundaries and can let a seemingly simple scheduling skill access files or execute commands beyond what a user would reasonably expect.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The skill advertises natural-language deletion of calendar entries without any mention of confirmation, preview, or disambiguation safeguards. In a scheduler context, ambiguous language or accidental invocation can cause unintended loss of appointments, reminders, or recurring events, which may materially disrupt a user's obligations.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The config sets the timezone to "Asia/Shanghai", which imposes a specific locale setting in a natural-language relevant way. Under the policy, locale constraints should either be user-selectable or clearly documented as justified for a region-specific skill.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
This code performs a file export of potentially sensitive calendar content, including titles, locations, and descriptions, but the function docstring only describes the output path and does not warn that personal schedule data will be persisted in plain .ics form. There is a success print in the CLI, but no prior disclosure in the function comments/docstring for callers using the class directly.

Intent-Code Divergence

Medium
Confidence
94% confidence
Finding
The docstring at L085-L091 says the method imports schedules from .ics files, and the module docstring at L003-L005 states support for .ics format. However, the parser normalizes keys by stripping parameters at L117-L119, so values like DTSTART;VALUE=DATE are stored as DTSTART, while later logic checks for DTSTART;VALUE=DATE at L131-L138. This means documented all-day .ics support is contradicted by the actual implementation.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The import operation writes parsed events into the scheduler database, which changes user data, but the docstring only states that it imports events and returns a count. Although the CLI prints the number imported afterward, there is no up-front disclosure or confirmation that the database will be modified.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Content
if len(end_str) == 15:
                        end_time = datetime.strptime(end_str, '%Y%m%dT%H%M%S')
                    else:
                        end_time = start_time + __import__('datetime').timedelta(hours=1)
                    
                    is_all_day = False
Confidence
75% confidence
Finding
Dynamic __import__() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The natural-language strings in the module docstrings and all user-facing output are exclusively in Chinese, including operational status messages and reminder content. This appears to impose a specific language/locale on users without any visible opt-in or documented locale constraint, which matches the policy-violation criterion for language or locale restrictions.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
When provided, the Feishu user ID is appended to the command string and then persisted into the cron_jobs.json file as part of the saved job definition. This is handling user-related data, but the file contains no user-facing notice that such identifiers will be stored locally for later task execution.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This code creates and updates a local cron configuration file that persists reminder jobs, and the paired deletion flow later removes entries from that file. Although there are internal comments and docstrings for developers, there is no explicit user-facing warning, confirmation, or disclosure near these data-modifying operations to inform the user that reminder tasks are being stored and changed locally.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The module description, command help, and examples are entirely in Chinese, and the skill presents itself as a natural-language interface without indicating language options or user opt-in. This can violate language/locale policy requirements because the skill implicitly constrains interaction to a specific language.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The manifest describes a personal scheduling skill with natural-language scheduling, reminders, recurring events, web UI, and import/export. Spawning a subprocess to run another script is not an obvious or necessary capability for that purpose from the stated intent, and expands execution capability beyond ordinary schedule management logic.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
print(f"  - {job['event_title']}: {job['reminder_time']}")
                # 执行发送
                import subprocess
                subprocess.run(['python', 'send_reminder.py', job['event_id']])
        else:
            print("没有待发送的提醒")
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill deletes a matched schedule entry immediately once a single match is found, without confirmation or undo capability. In a natural-language scheduler, ambiguous parsing or unintended invocations can cause irreversible data loss, making this a real integrity issue even if not a classic exploit primitive.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
This code file contains natural-language documentation saying the skill converts Chinese natural language to schedule data, which implies a fixed language constraint. Under the policy, forcing a specific language without user opt-in or documented justification is a violation.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The module description and user-facing strings present the skill as a Chinese-language personal scheduler, and the configuration also fixes the timezone to Asia/Shanghai by default. Under the policy, forcing a specific language or locale without user choice can be a natural-language policy violation unless clearly justified or offered as an option.

Description-Behavior Mismatch

Medium
Confidence
90% confidence
Finding
The code embeds and persists a specific Feishu user identifier as a default configuration value, creating an undeclared external messaging integration and exposing a real platform identifier in source. This can lead to privacy issues, misdirected reminders, and unauthorized linkage of user scheduling data to a third-party messaging account if deployed as-is.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
This code saves scheduler configuration to config.json, including a Feishu user identifier, but provides no confirmation prompt, print/log message, or warning comment beyond an internal docstring. For a code file, persistent file writes involving user-related data should have some visible disclosure unless already clearly communicated elsewhere in markdown, which is not available in this file.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The code writes event details to a SQLite database and later writes reminder job metadata to reminder_jobs.json, but there is no visible disclosure to the user that calendar content and reminder metadata will be persisted locally. This is safety-relevant because it affects user data storage and later deletion behavior, yet the file contains no prompt, logging, or warning text for these operations.

Context-Inappropriate Capability

Medium
Confidence
77% confidence
Finding
The stated purpose supports storing events and reminders, but this code additionally prepares OS-level command execution metadata (`python .../send_reminder.py`) for later use. Building executable commands is a broader orchestration capability than simple schedule management and is not declared in the manifest.

Natural-Language Policy Violations

Medium
Confidence
98% confidence
Finding
This code file contains natural-language strings such as the module description, error messages, and CLI usage entirely in Chinese. Under the policy rule, forcing a specific language without offering the user a language or locale choice is a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The module docstring and startup messages are written only in Chinese, which imposes a specific language on users without offering a locale choice. Under the policy, language constraints should be opt-in or clearly justified as region-specific.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This code file exposes a POST endpoint that creates calendar events, which is a user-data write operation. While the function has an internal docstring, there is no confirmation, user-facing notice, or broader warning in this file that the request will persist changes to the user's schedule.

Static analysis

No suspicious patterns detected.