T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/crs_generator.py:64
- Finding
- Unnecessary Extraction and Unredacted Output of Personal Financial Data<![CDATA[ ## Vulnerability Details **File Location**: `scripts/crs_generator.py:64-66`, `scripts/crs_generator.py:78-104`, and `scripts/crs_generator.py:386-391` **Vulnerability Type**: Excessive sensitive-data processing and plaintext disclosure **Risk Level**: Medium ### Vulnerable Code ```python data = { "client_name": None, "account_number": None, "account_type": None, "address": None, "statement_date": None, "currencies": {}, "holdings": [], "total_value_hkd": None, "transactions": [], "fees": {}, } ``` ```python for line in lines: # Pattern: "张三 (0123456789) 客户户口 : 0123456789" m = re.search(r"(\S+)\s*\((\d+)\).*客户户口\s*:\s*(\d+)", line) if m: data["client_name"] = m.group(1) data["account_number"] = m.group(3) # Account type if "户口类别" in line: m = re.search(r"户口类别\s*:\s*(.+?)\s", line) if m: data["account_type"] = m.group(1) # Address if "區" in line or "市" in line or "省" in line: if not data["address"] and "省" not in line: continue if re.search(r"[\u4e00-\u9fff]{2,}(?:省|市|區|镇|路|號|号|座)", line): if not re.search(r"(?:皇后|中心|大道|Tel|电话|傳真)", line): data["address"] = line.strip() # --- Address: collect multi-line --- addr_lines = [] capture = False for line in lines: if re.search(r"[\u4e00-\u9fff]{2,}省[\u4e00-\u9fff]{2,}市", line): capture = True if capture: if re.search(r"(?:客户主任|列印|户口类别)", line): break clean = line.strip() if clean and not re.search(r"(?:皇后|中心|大道|Tel|电话|傳真|^$)", clean): addr_lines.append(clean) if addr_lines: data["address"] = "".join(addr_lines) ``` ```python def main(): import argparse parser = argparse.ArgumentParser(description="Parse a local broker PDF into JSON.") parser.add_argument("pdf") args = parser.parse_args() print(json.dumps(parse_statement(args.pdf), ensure_ascii=False, ind ...[truncated 1534 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Remove `client_name` and `address` extraction because these values are not needed for the declared calculation. - Replace full account numbers with a stable masked identifier, such as the final four digits, before storing or returning parser output. - Return a deliberately allowlisted data structure containing only required transaction, currency, date, and balance fields. - Add an explicit `--include-sensitive-metadata` diagnostic option if identity extraction is operationally unavoidable, and keep it disabled by default. - Send diagnostic information to a controlled logger with redaction rather than printing the full parsed object. - Add tests confirming that names, addresses, and complete account numbers cannot appear in default output. - Document local retention and deletion expectations for generated output. ]]>
