T09 · Insecure Skill Coding Practices
- Location
scripts/reconcile.py:287- Finding
Raw Financial and Personal Data Is Exposed by the Preview Command
- Content
View full analysis
Vulnerability Details
File Location:
scripts/reconcile.py, lines 287-292; related disconnected sanitization implementation at lines 58-74
Vulnerability Type: Sensitive-data exposure through application output
Risk Level: MediumVulnerable Code
python def desensitize_dataframe(df: pd.DataFrame) -> pd.DataFrame: """对敏感字段脱敏(仅用于展示,不影响匹配计算)""" df = df.copy() for col in df.columns: col_lower = col.lower() if any(k in col_lower for k in ["账号", "account"]): df[col] = df[col].astype(str).apply( lambda x: x[:4] + "****" + x[-4:] if len(x) >= 8 else "****") elif any(k in col_lower for k in ["姓名", "name", "户名"]): df[col] = df[col].astype(str).apply( lambda x: x[0] + "**" if len(x) >= 2 else "**") elif any(k in col_lower for k in ["手机", "phone", "mobile"]): df[col] = df[col].astype(str).apply( lambda x: re.sub(r"(\d{3})\d{4}(\d{4})", r"\1****\2", x)) return dfpython def cmd_preview(args): print(f"📂 预览文件: {args.file}") df = load_file(args.file) print(f"\n列名: {list(df.columns)}") print(f"行数: {len(df)}") print(f"\n前 5 行:") print(df.head().to_string())Technical Analysis
The project implements
desensitize_dataframe(), but no audited execution path invokes it. In particular,cmd_preview()loads the input intodfand immediately prints the first five rows in their original form.Bank and reconciliation files can contain account numbers, customer names, phone numbers, transaction identifiers, balances, and other financial information. Consequently, the preview output can disclose raw sensitive values to terminal history, redirected output files, centralized process logs, CI/CD logs, agent transcripts, or any user able to observe the invoking process.
This behavior also contradicts `references/desensitization- ...[truncated 1417 chars]
- Remediation
View remediation
Remediation Suggestions
- Apply sanitization before every display path:
python safe_df = desensitize_dataframe(df) print(safe_df.head().to_string()) - Keep raw data only for reconciliation calculations and use a separate sanitized copy for previews, reports, exports, diagnostics, and error messages.
- Extend sanitization to the documented identity-card and email fields and use normalized column-name matching.
- Default to a minimal preview containing only recognized date, amount, and sanitized identifier fields. Require explicit informed consent to display raw rows.
- Add automated tests proving that account numbers, names, phone numbers, identity-card numbers, and email addresses never appear in preview output.
- Review all logging and exception paths to ensure that raw data frames and sensitive cell values are not emitted.
- Update the documentation so it accurately describes when sanitization occurs and which fields it covers.
- Apply sanitization before every display path:
