T09 · Insecure Skill Coding Practices
- Location
scripts/source_connector.py:146- Finding
Trello API credentials exposed through URL query strings
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill has a coherent project-management purpose, but it should be reviewed because it can modify connected services and has under-scoped local vault scanning and credential-handling risks.
Install only if you are comfortable giving it project-management tokens that may create, update, and comment on tasks. Use least-privilege tokens, point Obsidian only at a task-specific vault or folder, avoid mixed personal notes, and treat the local project-nerve data directory as sensitive because it can contain cached task details.
scripts/source_connector.py:146Trello API credentials exposed through URL query strings
scripts/task_aggregator.py:521Obsidian integration scans unrelated Markdown files and ignores the configured task tag
scripts/utils.py:154Aggregated project and Obsidian task data is stored in plaintext without explicit restrictive permissions
声明描述的是一个完整的跨平台项目管理聚合器,其中“自学习引擎”只是其一部分;但提供的代码块实际只覆盖学习引擎子模块。该模块通过 JSON 文件持久化错误、成功和纠正模式,生成建议与统计,并不执行任何项目管理聚合器应有的核心行为,如连接外部平台、读取/写入任务、统一管理工作项、建立任务关系图谱等。因此,代码行为与整体声明的主要目的存在实质性不符。虽然描述中提到支持自学习引擎,这部分与代码一致,但不足以覆盖其被宣称的核心产品能力。
声明描述的是一个更高层的项目管理聚合器,重点在跨平台任务统一管理,以及自学习和关系图谱等高级能力。但该代码块实际仅是“数据源连接器”,负责保存连接配置、检测凭据有效性、列出和删除连接。它没有执行任务同步、聚合、编辑、分析或图谱构建等核心产品行为。对于 GitHub 也只是请求 /user 验证 token,而不是处理 Issues。另一个未在描述中体现的实际能力是访问本地 Obsidian Vault 目录、扫描 Markdown 文件,并将连接信息持久化到本地 JSON 文件。虽然这些可视为聚合器的支撑模块,但如果用该描述来代表这段代码本身,存在明显的描述与行为不匹配。
该代码块的核心用途与描述明显不一致。声明强调的是一个跨平台项目管理聚合器,重点在统一接入和管理多个任务平台,以及更高级的自学习和关系图谱能力;而代码仅对本地 tasks_cache.json 缓存数据做统计分析,输出冲刺相关指标和图表。它没有展示任何外部平台 API 集成、任务同步、管理中枢、自学习模型或关系图谱构建逻辑。相反,代码的主要功能是付费版冲刺分析报表生成,因此属于主要用途不符且存在未声明能力/产品形态差异。
声明描述的是一个广义的跨平台项目管理聚合核心,强调统一管理多个外部任务平台,以及高级能力如自学习和关系图谱。但该代码块只负责基于已有缓存任务数据生成站会日报和周报,属于报告/汇总输出功能,而不是聚合管理本身。代码没有展示任何对 Trello、GitHub Issues、Linear、Notion、Obsidian 的连接、拉取、写回、统一管理操作,也没有自学习或图谱分析能力。虽然注释提到‘支持跨平台汇总’,但具体实现仅消费 tasks_cache.json 中的数据并格式化成 Markdown,因此与声明的主要用途存在明显偏差。
主体功能上,描述中的“跨平台项目管理聚合器,统一管理 Trello、GitHub Issues、Linear、Notion、Obsidian 任务”与代码基本一致,因为代码确实从这五个平台/来源汇总任务,并提供搜索、阻碍分析和优先级排序。然而描述中的两项重要扩展能力与代码不符:其一,“任务关系图谱”完全未实现;其二,“自学习引擎”最多只是可选地向 learning_engine 记录成功/失败日志,不足以支持“自学习”这一表述。此外,声明权限为空,但代码实际具有明显的数据访问能力:访问多个第三方服务 API,并递归读取本地 Obsidian Vault 中的 Markdown 文件。基于这些未声明或夸大的能力,整体应判定为描述与实际行为存在不匹配。
声明描述的是一个完整的跨平台项目管理聚合器,核心能力应包括多平台任务接入、统一管理与可能的数据同步/聚合;同时还宣称具备自学习引擎和任务关系图谱。实际提供的代码块仅是一个“任务关系图谱”脚本,围绕本地 JSON 图数据进行关系建模和分析。它确实支持任务关系图谱相关功能,但没有任何网络/API 调用、平台适配、外部服务访问或任务聚合逻辑,也没有任何自学习、模型训练、推荐或智能推断实现。因此,代码行为只匹配声明中的一小部分,而与整体宣称的主要用途存在实质性不一致。
代码的核心作用是“任务写入器”,重点在向多个平台写入和修改任务数据,而不是实现一个完整的‘项目中枢’或‘聚合器’。它确实涉及多个声明中的平台,也有简单的平台自动检测逻辑,因此与声明存在部分重合。但描述中最关键的高层能力——统一聚合管理、任务关系图谱、自学习引擎——在该代码块中并未得到实质实现;其中自学习仅表现为可选的成功/错误记录,远弱于通常理解的‘引擎’。此外,Obsidian 只支持创建,不支持更新/评论,和“统一管理”表述也有差距。因此该描述对这段代码的能力有明显夸大,构成不匹配。
代码整体仍与“项目管理聚合器”的基础支撑能力相关,例如统一状态/优先级、支持的平台列表、任务格式化和图表输出,因此并非完全偏离声明目的。但声明强调的关键能力——跨平台统一管理之外的“自学习引擎”和“任务关系图谱”在此代码块中没有对应实现;相反,代码实际实现了一个未声明的重要能力:订阅分级与付费功能门控。此外,该模块还显式进行本地数据目录管理和 JSON 文件读写,属于实际资源使用行为,声明中未提及。基于“描述与实际行为”对照,这构成部分但实质性的能力不一致。
The skill is explicitly designed to consume multiple high-value credentials, including GitHub, Trello, Linear, and Notion tokens, and then perform network and write operations on the user's behalf. Even though the document says not to ask for tokens in chat, the combination of broad credential access, multi-platform action support, and missing explicit tool scoping means a compromise, prompt-injection, or unsafe downstream script could abuse these secrets to read or modify external systems.
|------|------|------|
| `PNC_TRELLO_API_KEY` | 否 | Trello API Key(连接 Trello 时需要) |
| `PNC_TRELLO_TOKEN` | 否 | Trello 用户 Token |
| `PNC_GITHUB_TOKEN` | 否 | GitHub Personal Access Token |
| `PNC_LINEAR_API_KEY` | 否 | Linear API Key |
| `PNC_NOTION_TOKEN` | 否 | Notion Integration Token |
| `PNC_NOTION_DATABASE_ID` | 否 | Notion 目标数据库 ID |
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def _test_github(config: Dict[str, Any]) -> Dict[str, Any]:
"""测试 GitHub API 连接。
需要 personal access token。
通过访问 /user 端点验证凭据。
Args:
The skill declares broad capabilities involving environment variables, local file access, file writes, and network access, but does not explicitly constrain tool scope with a permissions or allowed-tools declaration. This increases the blast radius of any prompt-injection, logic flaw, or unsafe implementation in the referenced scripts because the agent may be able to access credentials, local vault contents, and external APIs without clear least-privilege boundaries.
The description states the agent 'always uses Chinese to communicate with the user,' which imposes a language choice unconditionally. This is a natural-language policy issue because it does not offer the user any language or locale choice or indicate that the skill is limited to a justified Chinese-only context.
The usage examples instruct users to invoke the skill with Chinese command phrases such as '连接', '同步任务', '搜索', and '创建任务'. Because the document presents these as the canonical commands and does not state that English equivalents are supported, it imposes a locale-specific interaction pattern without explicit user opt-in.
The guide shows Trello authentication via query parameters containing key and token. Putting credentials in URLs is dangerous because URLs are commonly logged by clients, proxies, observability systems, browser history, and error traces, causing credential leakage beyond the intended recipient.
| 获取看板列表 | GET | `https://api.trello.com/1/boards/{boardId}/lists?key={key}&token={token}` |
| 获取看板卡片 | GET | `https://api.trello.com/1/boards/{boardId}/cards?key={key}&token={token}` |
| 创建卡片 | POST | `https://api.trello.com/1/cards?key={key}&token={token}` |
| 更新卡片 | PUT | `https://api.trello.com/1/cards/{cardId}?key={key}&token={token}` |
| 添加评论 | POST | `https://api.trello.com/1/cards/{cardId}/actions/comments?key={key}&token={token}&text={text}` |
**认证方式**: Query 参数传递 `key` 和 `token`。
This line documents a comment endpoint with both credentials and user-supplied text in the URL query string. That increases exposure of both secrets and potentially sensitive comment content through logs and intermediaries, creating a dual confidentiality risk.
| 获取看板卡片 | GET | `https://api.trello.com/1/boards/{boardId}/cards?key={key}&token={token}` |
| 创建卡片 | POST | `https://api.trello.com/1/cards?key={key}&token={token}` |
| 更新卡片 | PUT | `https://api.trello.com/1/cards/{cardId}?key={key}&token={token}` |
| 添加评论 | POST | `https://api.trello.com/1/cards/{cardId}/actions/comments?key={key}&token={token}&text={text}` |
**认证方式**: Query 参数传递 `key` 和 `token`。
The guide explicitly documents sending project/task data and authentication credentials to multiple third-party SaaS platforms, but it does not warn about privacy, consent, data minimization, or tenant-boundary risks. In a project-management aggregator, this omission can lead operators to sync sensitive internal content, comments, and metadata externally without appropriate disclosure or controls.
This code file contains user-facing natural-language descriptions and messages exclusively in Chinese, including the module description and operational guidance. Per the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is clearly justified, which is not present here.
The module-level natural-language description is entirely in Chinese and presents the skill as operating in that locale, with no indication that users may choose another language. Under the stated policy, forcing a specific language without opt-in is a natural-language policy violation unless the locale restriction is explicitly documented and justified.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
if not token:
return {"success": False, "message": "缺少 GitHub Token,请设置 PNC_GITHUB_TOKEN 环境变量"}
url = "https://api.github.com/user"
headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/vnd.github.v3+json",
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
if not token:
return {"success": False, "message": "缺少 GitHub Token,请设置 PNC_GITHUB_TOKEN 环境变量"}
url = "https://api.github.com/user"
headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/vnd.github.v3+json",
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
if not token:
return {"success": False, "message": "缺少 GitHub Token,请设置 PNC_GITHUB_TOKEN 环境变量"}
url = "https://api.github.com/user"
headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/vnd.github.v3+json",
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
if not token:
return {"success": False, "message": "缺少 GitHub Token,请设置 PNC_GITHUB_TOKEN 环境变量"}
url = "https://api.github.com/user"
headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/vnd.github.v3+json",
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
if not token:
return {"success": False, "message": "缺少 GitHub Token,请设置 PNC_GITHUB_TOKEN 环境变量"}
url = "https://api.github.com/user"
headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/vnd.github.v3+json",
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
if not token:
return {"success": False, "message": "缺少 GitHub Token,请设置 PNC_GITHUB_TOKEN 环境变量"}
url = "https://api.github.com/user"
headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/vnd.github.v3+json",
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
if not token:
return {"success": False, "message": "缺少 GitHub Token,请设置 PNC_GITHUB_TOKEN 环境变量"}
url = "https://api.github.com/user"
headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/vnd.github.v3+json",
No suspicious patterns detected.