Back to skill

Security audit

bill claw

Security checks for vulnerabilities and agentic risk

Overview

BillClaw is a coherent local bookkeeping skill, but it exposes private financial data through review-worthy dashboard and export risks.

Install only if you are comfortable with a local skill managing a SQLite ledger of financial records. Keep the dashboard bound to 127.0.0.1, avoid using it with untrusted transaction data, review records before delete or merge confirmations, and be cautious when exporting CSV files or choosing output paths.

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)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/dashboard.html:520
Finding
Stored Cross-Site Scripting in Transaction Dashboard<![CDATA[ ## Vulnerability Details **File Location**: `scripts/dashboard.html:520-539`, with unsafe input accepted at `scripts/main.py:65-68` and `scripts/parser.py:258-266` **Vulnerability Type**: Stored Cross-Site Scripting **Risk Level**: High ### Vulnerable Code ```javascript function renderTable() { const tb = qs('tbody'); tb.innerHTML = ''; const rows = [...state.tableRows]; const mult = state.sortDir === 'asc' ? 1 : -1; rows.sort((a, b) => { const ka = state.sortKey; let va = a[ka], vb = b[ka]; if (ka === 'amount') { va = Number(va); vb = Number(vb); return mult * (va - vb); } return mult * String(va || '').localeCompare(String(vb || ''), 'zh-CN'); }); rows.forEach((r) => { const tr = document.createElement('tr'); const tag = r.type === '收入' ? 'tag-in' : 'tag-out'; tr.innerHTML = `<td>${r.date}</td><td><span class="tag ${tag}">${r.type}</span></td><td>${r.category}</td>` + `<td class="num">${fmtMoney(r.amount)}</td><td>${(r.note || '').replace(/</g, '&lt;')}</td>`; tb.appendChild(tr); }); } ``` The corresponding CLI accepts database-controlled values without validating the date format or constraining the category: ```python date_str = str(payload["date"]) type_ = str(payload["type"]) category = str(payload["category"]) amount = float(payload["amount"]) ``` ```python if type_ not in ("收入", "支出"): issues.append("type must be income or expense") if type_ == "支出" and category not in expense_defaults: pass # custom categories allowed if type_ == "收入" and category not in income_defaults: pass ``` ### Technical Analysis The dashboard constructs table rows through `innerHTML` and directly interpolates the transaction's `date` and `category` fields. Both fields originate from SQLite records and can contain arbitrary HTML because the record-validation function does not validate dates or restrict custom-category content. A payload such as the following can therefore be s ...[truncated 1943 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Stop constructing transaction rows through `innerHTML`. 2. Create each table cell with `document.createElement()` and assign all database values through `textContent`. 3. Validate `date` with a strict ISO `YYYY-MM-DD` parser before insertion and reject invalid or trailing content. 4. Apply reasonable length limits to category, note, source, and date fields. 5. If HTML rendering is ever necessary, use a maintained allowlist-based sanitizer rather than manual character replacement. 6. Add regression tests that store HTML and event-handler payloads in every transaction field and verify that the dashboard displays them as plain text. 7. Deploy a restrictive Content Security Policy, such as one that disallows inline scripts, as defense in depth. CSP must supplement rather than replace safe DOM construction. A safe rendering pattern is: ```javascript function appendTextCell(row, value, className = '') { const cell = document.createElement('td'); if (className) cell.className = className; cell.textContent = value == null ? '' : String(value); row.appendChild(cell); } ``` ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/web.py:40
Finding
Unauthenticated Financial Data Exposure When Bound to a Non-Loopback Interface<![CDATA[ ## Vulnerability Details **File Location**: `scripts/web.py:40-110`, with caller-controlled binding at `scripts/main.py:270-273` **Vulnerability Type**: Missing Authentication and Unsafe Network Exposure **Risk Level**: High ### Vulnerable Code The server host is supplied by the caller without restricting it to a loopback address: ```python def cmd_serve(payload: dict[str, Any], db_path: Path | None) -> None: from web import run_server host = str(payload.get("host") or "127.0.0.1") port = int(payload.get("port") or 8000) run_server(host=host, port=port, db_path=db_path) ``` Sensitive APIs have no authentication or authorization checks: ```python @app.route("/api/summary") def api_summary(): date_from, date_to = _date_args() with conn_ctx() as conn: t = totals(conn, date_from=date_from, date_to=date_to) rows = aggregate_by_category( conn, date_from=date_from, date_to=date_to, type_="支出" ) exp_only = [{"category": r["category"], "total": float(r["total"])} for r in rows] inc_rows = aggregate_by_category( conn, date_from=date_from, date_to=date_to, type_="收入" ) inc_only = [{"category": r["category"], "total": float(r["total"])} for r in inc_rows] return jsonify( { "totals": t, "expense_by_category": exp_only, "income_by_category": inc_only, } ) ``` ```python @app.route("/api/transactions") def api_transactions(): date_from, date_to = _date_args() type_ = request.args.get("type") or None if type_ == "": type_ = None page = max(1, int(request.args.get("page", 1))) per_page = min(500, max(10, int(request.args.get("per_page", 100)))) offset = (page - 1) * per_page with conn_ctx() as conn: total = count_transactions( conn, date_from=date_from, date_to=date_to, type_=type_ ) rows = query_transactions( conn, ...[truncated 2133 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Reject non-loopback bind addresses unless an explicit secure-remote mode is enabled. 2. Resolve and validate host values against loopback addresses such as `127.0.0.1` and `::1`. 3. Display a prominent warning and require explicit confirmation before exposing the service to a network. 4. If remote access is required, add strong authentication and authorization to every API route. 5. Place the application behind a hardened reverse proxy that provides TLS, request-size limits, access logging, and rate limiting. 6. Do not rely on obscurity of the port or firewall configuration as the sole access control. 7. Add response headers such as a restrictive Content Security Policy, `X-Content-Type-Options: nosniff`, and an appropriate `Referrer-Policy`. 8. Document that the Flask development server is unsuitable for direct public exposure. 9. Add tests proving that an unauthenticated remote-mode request is rejected and that default operation binds only to loopback. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/main.py:230
Finding
Spreadsheet Formula Injection in CSV Exports<![CDATA[ ## Vulnerability Details **File Location**: `scripts/main.py:230-244` **Vulnerability Type**: CSV/Spreadsheet Formula Injection **Risk Level**: Medium ### Vulnerable Code ```python def cmd_export_csv(payload: dict[str, Any], db_path: Path | None) -> dict[str, Any]: path = Path(payload.get("path") or "billclaw_export.csv") with get_connection(db_path) as conn: rows = query_transactions( conn, date_from=payload.get("date_from"), date_to=payload.get("date_to"), type_=payload.get("type"), category=payload.get("category"), limit=payload.get("limit", 10000), ) if not rows: path.write_text("", encoding="utf-8") return {"ok": True, "error": None, "data": {"path": str(path.resolve()), "rows": 0}} keys = list(rows[0].keys()) with path.open("w", newline="", encoding="utf-8-sig") as f: w = csv.DictWriter(f, fieldnames=keys) w.writeheader() w.writerows(rows) return {"ok": True, "error": None, "data": {"path": str(path.resolve()), "rows": len(rows)}} ``` ### Technical Analysis `csv.DictWriter` correctly escapes CSV delimiters and quotes, but it does not neutralize spreadsheet formulas. Text fields including `category`, `note`, and `source` can begin with spreadsheet formula markers such as: ```text = + - @ ``` When the resulting CSV file is opened in spreadsheet software, such cells may be interpreted as formulas rather than plain text. Quoting the cell according to CSV syntax does not necessarily prevent formula evaluation. The exact consequences depend on the spreadsheet product and its security configuration. Potential formula behavior includes external references, network requests, misleading displayed values, or dangerous legacy formula features. ### Attack Path 1. An attacker or untrusted data source causes a transaction field to contain a formula-like value, for example: ```text =HYPERLINK("ht ...[truncated 1087 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat all exported text fields as untrusted spreadsheet input. 2. Before writing a text cell, detect optional leading whitespace followed by `=`, `+`, `-`, or `@`. 3. Prefix dangerous cells with a single quote or another spreadsheet-compatible neutralization character. 4. Preserve numeric fields as numbers only after strict numeric validation. 5. Document whether the export is intended as a raw machine-readable CSV or a spreadsheet-safe CSV. 6. Add tests for formula prefixes, leading tabs, carriage returns, Unicode whitespace, and quoted values. 7. Consider offering two clearly named export modes: raw CSV for trusted programmatic consumption and spreadsheet-safe CSV for users. Example hardening logic: ```python def spreadsheet_safe(value: Any) -> Any: if not isinstance(value, str): return value stripped = value.lstrip() if stripped.startswith(("=", "+", "-", "@")): return "'" + value return value safe_rows = [ {key: spreadsheet_safe(value) for key, value in row.items()} for row in rows ] w.writerows(safe_rows) ``` ]]>

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding
Unpinned Python Dependencies Permit Unreviewed Future Versions<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:1-4` **Vulnerability Type**: Non-Reproducible and Unbounded Dependency Resolution **Risk Level**: Medium ### Vulnerable Code ```text dateparser>=1.2.0 pydantic>=2.0.0 matplotlib>=3.8.0 flask>=3.0.0 ``` The documented installation command resolves these unrestricted versions from the configured package index: ```bash pip install -r requirements.txt ``` ### Technical Analysis Every dependency uses only a lower version bound. An installation performed after the audit may therefore select a substantially newer package than the version originally reviewed or tested. The dependency file also contains no package hashes or lock data. This does not prove that any currently listed package is malicious. The weakness is that the installed dependency set is neither reproducible nor cryptographically constrained. A future compromised release, unexpected major behavior change, or compromise of the configured package source could introduce unreviewed installation or runtime behavior. The declared package names appear consistent with the imported libraries; no typosquatting or dependency-confusion package name was identified in the reviewed file. ### Attack Path 1. A new dependency version is published after this project was audited. 2. The version satisfies the open-ended `>=` constraint. 3. A user runs the documented `pip install -r requirements.txt` command. 4. The package resolver selects the newer, unreviewed release. 5. Package installation hooks or imported runtime code execute in the user's virtual environment. 6. If that release or package source is compromised, the dependency gains the privileges of the installing or running user. ### Impact Assessment A compromised dependency executes with the privileges of the user running installation or BillClaw. Within those privileges, dependency code could access: - The SQLite ledger and report output. - Files available to the Python process. - ...[truncated 274 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin each direct and transitive dependency to an exact reviewed version. 2. Generate a lock file with a tool such as `pip-tools`, Poetry, or uv. 3. Require cryptographic hashes during installation, for example through a hash-locked requirements file and `pip --require-hashes`. 4. Use a trusted package index and explicitly configure approved sources. 5. Run automated dependency vulnerability and provenance checks in continuous integration. 6. Upgrade dependencies through a controlled process that includes changelog review, tests, and security review. 7. Rebuild lock files periodically so security updates are adopted deliberately rather than implicitly. 8. Record and verify the versions of bundled browser libraries through an inventory or software bill of materials. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (32)

Tool Parameter Abuse

High
Category
Tool Misuse
Content
## 报表图表中的中文

`scripts/report.py` 会自动选用系统里常见的中文字体(如 macOS 的 PingFang SC、Windows 的微软雅黑、Linux 的 Noto CJK 等)。若饼图/标题仍显示为方框,请在系统安装一款 CJK 字体,例如 Debian/Ubuntu:`sudo apt install fonts-noto-cjk`,安装后删除 matplotlib 字体缓存再试:`rm -rf ~/.cache/matplotlib`。

## Web 看板静态资源
Confidence
90% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
## 报表图表中的中文

`scripts/report.py` 会自动选用系统里常见的中文字体(如 macOS 的 PingFang SC、Windows 的微软雅黑、Linux 的 Noto CJK 等)。若饼图/标题仍显示为方框,请在系统安装一款 CJK 字体,例如 Debian/Ubuntu:`sudo apt install fonts-noto-cjk`,安装后删除 matplotlib 字体缓存再试:`rm -rf ~/.cache/matplotlib`。

## Web 看板静态资源
Confidence
85% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description covers a full-featured BillClaw bookkeeping application with CLI commands, database interactions, and dashboard/reporting features. The supplied code chunk, however, is merely a static vendor JavaScript asset placeholder/comment for Chart.js. On its own, it does not exhibit the declared primary purpose or capabilities. While Chart.js could support chart rendering in a dashboard, this chunk is only a supporting front-end dependency and not representative of the described skill behavior. Therefore, the description does not accurately represent what this specific supplied code chunk actually does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This code chunk does not match the described BillClaw bookkeeping skill behavior. The declaration centers on a Python/SQLite bookkeeping CLI and related local dashboard/report features. The actual code is a static vendor asset for chart zooming and panning in the browser. While interactive chart support could be a supporting detail of a dashboard, this chunk by itself does not perform any of the declared core functions and instead serves a different, narrower purpose as a front-end dependency. Therefore the supplied chunk is materially inconsistent with the declared purpose.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This code does not implement or expose the declared bookkeeping functionality. Instead, it is a generic vendor-side JavaScript dependency for handling touch gestures in a web interface. While such a library could be a supporting asset of a dashboard, the chunk itself has a materially different purpose and none of the declared BillClaw CLI/SQLite/accounting behaviors are present here. Therefore, the description does not accurately represent what this supplied code chunk actually does.

Ae1

High
Category
analysis-evasion
Content
- Web 看板:本地 Flask + `scripts/dashboard.html` + `scripts/static/vendor` 内 Chart.js,支持时间筛选、按月柱状图、分页明细与图表交互(缩放/平移等),离线可开页
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- Web 看板:本地 Flask + `scripts/dashboard.html` + `scripts/static/vendor` 内 Chart.js,支持时间筛选、按月柱状图、分页明细与图表交互(缩放/平移等),离线可开页
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- Web 看板:本地 Flask + `scripts/dashboard.html` + `scripts/static/vendor` 内 Chart.js,支持时间筛选、按月柱状图、分页明细与图表交互(缩放/平移等),离线可开页
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
This markdown file is natural-language documentation, and its headings, descriptions, and command annotations are all presented in Chinese. Under the policy, forcing a specific language without user opt-in can be a natural-language policy violation when no alternative language option or justification is provided.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
## 报表图表中的中文

`scripts/report.py` 会自动选用系统里常见的中文字体(如 macOS 的 PingFang SC、Windows 的微软雅黑、Linux 的 Noto CJK 等)。若饼图/标题仍显示为方框,请在系统安装一款 CJK 字体,例如 Debian/Ubuntu:`sudo apt install fonts-noto-cjk`,安装后删除 matplotlib 字体缓存再试:`rm -rf ~/.cache/matplotlib`。

## Web 看板静态资源
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill clearly instructs the agent to read environment variables, read/write local files, operate on a SQLite database, generate PNG/CSV output, and potentially delete files, yet it declares no explicit tool scope or permission boundaries. This increases the chance of over-broad tool access and accidental misuse because the runtime cannot enforce least-privilege constraints from the skill manifest itself.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The skill advertises activation on broad, everyday phrases about money tracking, categories, charts, exports, and running local scripts, without clear exclusions or tighter triggering conditions. Over-broad routing can cause the agent to invoke a capability-rich local skill in contexts the user did not intend, increasing the risk of unintended database modification, file creation, or local service startup.

Session Persistence

Medium
Category
Rogue Agent
Content
- **目录含义**:`report` 将合图与单图 PNG 写入 `output_dir`。未传时默认为**当前工作目录**下的 `billclaw_output/`(与显式传 `./billclaw_output` 等价,取决于执行 `main.py` 时的 cwd)。这些文件仅为报表缓存/附件,**不替代** SQLite 账本(`db/expenses.db`)。
- **为何要清理**:同一目录下反复生成会堆积同名或带时间戳的文件,长期占用磁盘;对话中若用户关心空间、目录杂乱、或希望「整理报表文件」,应说明该目录用途与可清理性。
- **Agent 行为**:**删除磁盘文件前须征得用户明确同意**;同意后可删除该 `output_dir` 下过期的 PNG(或按用户指定的保留策略,例如只保留最近 N 天/最近一次生成)。删除前用一两句话说明将删的是报表图片、不涉及账本数据。
- **系统级定时清理(可选)**:若用户希望在无人值守时自动清理,可建议用本机 **cron**(Linux/macOS)或 **launchd**(macOS)定期删除指定 `output_dir` 下的 `*.png`(或整目录内旧文件),具体路径与保留天数由用户自行配置;Agent 不擅自替用户配置系统定时任务,除非用户明确要求协助编写命令或 plist 片段。
Confidence
75% confidence
Finding
The skill explicitly discusses assisting with cron/launchd-based periodic cleanup, which can introduce persistent scheduled behavior on the host. Although it says not to configure such tasks unless explicitly requested, persistence mechanisms are sensitive because they can be abused to maintain ongoing execution or cause recurring file deletion if the agent misinterprets a request.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The default category labels are hard-coded in Chinese, and later logic also depends on fixed Chinese values for transaction kinds. This imposes a specific language/locale in the skill behavior without any visible opt-in, language selection, or justification in the file.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The function deletes transaction records from the database, which is a destructive operation affecting user data. In this file, there is no confirmation prompt, logging, print statement, or explanatory comment/docstring warning that records will be permanently removed.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
Multiple user-facing strings in this file are hardcoded in Chinese, including errors, hints, and the CLI description, which effectively forces a specific language for all users. The file does not offer language selection or explain that the skill is intentionally limited to a Chinese-language context.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The export command accepts a user-controlled path and writes transaction data directly to that location with no path restriction, overwrite protection, or confirmation step in this file. In an agent-integrated context, this can be abused to overwrite arbitrary files writable by the process or exfiltrate sensitive bookkeeping data to unexpected locations, especially if another component passes untrusted payloads through to the CLI.

Missing User Warnings

Medium
Confidence
83% confidence
Finding
The serve command starts a Flask-backed server based on user-supplied host and port, which is a network-listening action with no safety gating in this file. While it defaults to localhost, allowing arbitrary host values means a caller can expose the bookkeeping dashboard on external interfaces, increasing the attack surface and potentially disclosing sensitive financial data if the web layer lacks authentication or is misconfigured.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The time parser is explicitly restricted to `languages=["zh", "en"]`, which imposes a language/locale constraint in natural-language handling. There is no surrounding user choice, opt-in, or documented justification that this skill is intentionally limited to Chinese and English inputs.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This file hardcodes user-visible chart labels, titles, and messages in Chinese, such as chart titles and empty-state text, without offering a locale choice. That can violate language/locale policy when the skill is expected to adapt to user preference rather than enforce a single language.

Unbounded Output

Medium
Category
Output Handling
Content
* https://github.com/kurkle/color#readme
 * (c) 2023 Jukka Kurkela
 * Released under the MIT License
 */function _t(t){return t+.5|0}const yt=(t,e,i)=>Math.max(Math.min(t,i),e);function vt(t){return yt(_t(2.55*t),0,255)}function Mt(t){return yt(_t(255*t),0,255)}function wt(t){return yt(_t(t/2.55)/100,0,1)}function kt(t){return yt(_t(100*t),0,100)}const St={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,A:10,B:11,C:12,D:13,E:14,F:15,a:10,b:11,c:12,d:13,e:14,f:15},Pt=[..."0123456789ABCDEF"],Dt=t=>Pt[15&t],Ct=t=>Pt[(240&t)>>4]+Pt[15&t],Ot=t=>(240&t)>>4==(15&t);function At(t){var e=(t=>Ot(t.r)&&Ot(t.g)&&Ot(t.b)&&Ot(t.a))(t)?Dt:Ct;return t?"#"+e(t.r)+e(t.g)+e(t.b)+((t,e)=>t<255?e(t):"")(t.a,e):void 0}const Tt=/^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/;function Lt(t,e,i){const s=e*Math.min(i,1-i),n=(e,n=(e+t/30)%12)=>i-s*Math.max(Math.min(n-3,9-n,1),-1);return[n(0),n(8),n(4)]}function Et(t,e,i){const s=(s,n=(s+t/60)%6)=>i-i*e*Math.max(Math.min(n,4-n,1),0);return[s(5),s(3),s(1)]}function Rt(t,e,i){const s=Lt(t,1,.5);let n;for(e+i>1&&(n=1/(e+i),e*=n,i*=n),n=0;n<3;n++)s[n]*=1-e-i,s[n]+=e;return s}function It(t){const e=t.r/255,i=t.g/255,s=t.b/255,n=Math.max(e,i,s),o=Math.min(e,i,s),a=(n+o)/2;let r,l,h;return n!==o&&(h=n-o,l=a>.5?h/(2-n-o):h/(n+o),r=function(t,e,i,s,n){return t===n?(e-i)/s+(e<i?6:0):e===n?(i-t)/s+2:(t-e)/s+4}(e,i,s,h,n),r=60*r+.5),[0|r,l||0,a]}function zt(t,e,i,s){return(Array.isArray(e)?t(e[0],e[1],e[2]):t(e,i,s)).map(Mt)}function Ft(t,e,i){return zt(Lt,t,e,i)}function Vt(t){return(t%360+360)%360}function Bt(t){const e=Tt.exec(t);let i,s=255;if(!e)return;e[5]!==i&&(s=e[6]?vt(+e[5]):Mt(+e[5]));const n=Vt(+e[2]),o=+e[3]/100,a=+e[4]/100;return i="hwb"===e[1]?function(t,e,i){return zt(Rt,t,e,i)}(n,o,a):"hsv"===e[1]?function(t,e,i){return zt(Et,t,e,i)}(n,o,a):Ft(n,o,a),{r:i[0],g:i[1],b:i[2],a:s}}const Wt={x:"dark",Z:"light",Y:"re",X:"blu",W:"gr",V:"medium",U:"slate",A:"ee",T:"ol",S:"or",B:"ra",C:"lateg"
...[truncated 28 chars]
Confidence
75% confidence
Finding
Output size or generation rate is not bounded. Unbounded output enables denial-of-service through resource exhaustion, log flooding, or context-window stuffing.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
This code contains natural-language text exclusively in Chinese, including the module description and the user-facing confirmation message, which indicates the skill is oriented to a specific language/locale without any visible opt-in or alternative. Under the stated policy, forcing a specific language without user choice or documented regional justification is a natural-language policy concern.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The file contains a hard-coded Chinese error message, and nearby API logic also uses Chinese category values such as "支出" and "收入". Because this code does not offer a language choice or document that the skill is intentionally region-specific, it appears to impose a specific locale contrary to the language/locale policy.

Unpinned Dependencies

Low
Category
Supply Chain
Content
dateparser>=1.2.0
pydantic>=2.0.0
matplotlib>=3.8.0
flask>=3.0.0
Confidence
95% confidence
Finding
The dependency is specified with only a minimum version, which allows future installs to resolve to different releases over time. This weakens reproducibility and can unintentionally introduce vulnerable or incompatible versions through the software supply chain.

Unpinned Dependencies

Low
Category
Supply Chain
Content
dateparser>=1.2.0
pydantic>=2.0.0
matplotlib>=3.8.0
flask>=3.0.0
Confidence
98% confidence
Finding
Using an unpinned pydantic version means deployments may receive different package versions, including ones with known security advisories. In a skill that parses user-driven bookkeeping data, that uncertainty increases supply-chain and availability risk.

Static analysis

No suspicious patterns detected.