T09 · Insecure Skill Coding Practices
- Location
scripts/migrate_stock_to_pg.py:13- Finding
PostgreSQL Credentials Exposed Through Unredacted Logging
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly matches its A-share market-report purpose, but it needs review because it can mutate local/PostgreSQL market-data stores and a migration script can print database credentials.
Review before installing if you will run it against a real PostgreSQL database or in a workspace containing secrets. Use a dedicated low-privilege database, rotate any password that may have appeared in migration logs, avoid running from directories with unrelated .env files, and treat generated HTML as untrusted if report text can include external or user-supplied links.
scripts/migrate_stock_to_pg.py:13PostgreSQL Credentials Exposed Through Unredacted Logging
scripts/_shared/html_report/markdown_engine.py:21Unsafe Markdown Link Schemes Permit Script Execution in Generated Reports
{match.group(1)}")
return f"@@CODE{len(code_values) - 1}@@"
escaped = re.sub(r"`([^`]+)`", keep_code, escaped)
escaped = re.sub(r"\*\*([^*]+)\*\*", r"\1", escaped)
escaped = re.sub(r"(?\1", escaped)
escaped = re.sub(r"\[([^\]]+)\]\(([^)]+)\)", r'\1', escaped)
for idx, value in enumerate(code_values):
escaped = escaped.replace(f"@@CODE{idx}@@", value)
return escaped
```
### Technical Analysis
The renderer HTML-escapes Markdown text but inserts link destinations directly into an `href` attribute without validating the URL scheme. HTML escaping protects the surrounding markup but does not make dangerous schemes safe.
For example:
```markdown
[Open report details](javascript:alert(document.domain))
```
is rendered as:
```html
Open report details
```
If a reader clicks the link, the browser can execute JavaScript in the generated report's document context. Other risky schemes, including certain `data:` URLs, are also not rejected.
The report Markdown is produced by an Agent and can potentially include user-supplied or externally derived text. Consequently, an attacker who can influence generated Markdown may be able to place a malicious link into the final HTML report.
### Attack Path
1. An attacker supplies content that is incorporated into the generated report, such as a crafted Markdown link.
2. The Agent preserves or reproduces that link in `report_YYYYMMDD.md`.
3. `rend
...[truncated 922 chars]scripts/_shared/html_report/builder.py:33Generated HTML Reports Initiate Undeclared Requests to Google Fonts
The declared description presents a domain-specific market analysis/research skill focused on Tushare Pro A-share daily-data evidence generation. The supplied code does not implement any market-analysis logic, Tushare data handling, feature grouping, report generation, or stock-review methodology. Instead, it is a generic shared database access layer used to connect to PostgreSQL or SQLite, manage pools, mask DSNs, translate SQL placeholders, and ping tables. While such infrastructure could support the broader skill, this code chunk’s actual purpose is materially different from the declared end-user skill behavior and exposes undeclared capabilities around database connectivity and diagnostics. Therefore this chunk does not accurately represent the declared skill purpose.
The declared description says this skill should generate deterministic evidence packages for post-market A-share analysis using Tushare daily-related datasets. However, the actual code does not perform any market-data analysis, report generation, feature grouping, historical review, or stock observation logic. Its sole purpose is operational: checking DB connectivity and required tables. That is a materially different primary purpose and capability set. While the mentioned tables include stock-related data, the script only verifies their existence and connection status, which is infrastructure support rather than the described analytical methodology. Therefore this is a clear description-behavior mismatch.
声明描述的是一个面向 A 股盘后研究的领域分析 skill,核心应是读取/加工市场数据并生成确定性证据包与分析结论。而实际代码片段只是共享的 HTML report 包初始化文件,负责导出渲染相关组件,属于通用展示层基础设施。它与声明中的金融数据分析主目的明显不一致,也没有体现任何相关数据访问、计算或业务分析流程。尽管报告渲染可作为研报输出的支持实现细节,但该代码片段本身的实际作用与声明的核心能力存在明显偏离,因此应判定为描述与行为不匹配。
The declared description is about a domain-specific financial analysis skill centered on Tushare Pro A-share daily data and market research methodology. The supplied code does not perform any market-data retrieval, financial analysis, evidence-pack construction, feature grouping, or stock observation logic. Instead, it is generic presentation infrastructure for building HTML reports from markdown with themes, chart hooks, and UI scripts. While such a component could support the broader skill as an implementation detail, this code chunk by itself has a materially different primary purpose and exposes undeclared capabilities related to HTML rendering and client-side report composition.
The declared description says this skill is for A-share market post-close analysis based on Tushare Pro data, including trend analysis, sentiment, feature grouping, historical review, and quantitative observation workflows. The supplied code does none of that. It contains a generic markdown rendering utility for converting markdown text into HTML, with support for tables, lists, code blocks, headings, and inline styles. It does not access Tushare data, perform any stock or index analysis, generate evidence packages, or implement the described market-research methodology. This is not merely a supporting implementation detail tied closely to the declared purpose; it is a generic presentation-layer component with a materially different primary purpose.
声明描述的是一个面向 A 股盘后复盘与量化观察的金融分析 skill,核心能力应围绕行情数据获取、指标计算、特征分组和研报证据包生成。而提供的代码仅处理 Markdown 到 HTML 的文本保真验证:解析 HTML、忽略 script/style、标准化文本、抽取 Markdown 片段并检查是否在 HTML 可见文本中出现。其主要用途属于报告渲染/质量保障工具链,而非证券数据分析或研报生成。两者主用途明显不一致,因此应判定为描述与行为不匹配。
The declared description is for an analytical research-generation skill focused on producing post-market evidence and structured market analysis from Tushare Pro daily data. The supplied code does not implement analysis, report generation, feature grouping, historical review logic, or quant observation outputs. Instead, it is an ETL utility whose primary purpose is migrating cached market data files into PostgreSQL. While the migrated data may support the declared analytical workflow, this code chunk itself is infrastructure for storage/import, not the described market-research methodology skill. Therefore the description does not accurately represent the actual behavior.
Referenced artifact was not completely inspected
按需生成 HTML:当用户要求 HTML、网页、可视化报告或截图风格输出时,先完成并核对 `reports/report_YYYYMMDD.md`,再运行 `scripts/render_report_html.py` 生成同日期 HTML。HTML 是展示层产物,不新增研报判断、不删减 Markdown 正文;若同
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.
日期,上涨,涨停,下跌,跌停,平盘,活跃度,成交额,融资净买入,全市场换手率
2026/05/15,1486,71.0,3932,46.0,99.0,,3134384000.0,7995515163.0,3.1584
2026/5/14,1047,82.0,4387,48.0,81.0,19.41%,3388086341.0,,3.1434
2026/5/13,3215,147.0,2134,17.0,167.0,,3264212322.0,21939951590.0,2.9745
Reading credentials from a .env file constitutes credential access, and here it is broader than necessary because it targets the current working directory rather than a narrowly scoped skill-owned location. In shared agent workspaces this can expose unrelated secrets if the process is launched from another repository or directory containing credentials.
if token:
return token
env_path = os.path.join(os.getcwd(), ".env")
if not os.path.exists(env_path):
return ""
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).
parser.add_argument("--evidence", default=None, help="Evidence JSON path. Defaults to sibling evidence_YYYYMMDD_utf8.json when input is report_YYYYMMDD.md.")
parser.add_argument("--title", default=None, help="HTML document title.")
parser.add_argument("--theme", default="default", choices=list_themes(), help="HTML style theme. default = Claude-UI; print = monochrome serif, A4-friendly.")
parser.add_argument("--no-validate", action="store_true", help="Skip Markdown text preservation validation.")
return parser
Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.
@contextlib.contextmanager
def patched_environment(env: Dict[str, str]):
original = os.environ.copy()
try:
os.environ.clear()
os.environ.update(env)
The skill advertises and instructs use of environment variables, local file reads/writes, database access, and network-backed data retrieval, but it does not declare any explicit tool/permission scope. In an agent setting, this weakens least-privilege controls and can cause the skill to be run with broader capabilities than necessary, increasing the blast radius if the skill is misused or later modified.
The file presents all operational instructions exclusively in Chinese and does not indicate that users may choose another language or locale. Under the stated policy, forcing a specific language without opt-in is a natural-language policy violation.
This markdown template begins with and consistently instructs output in Chinese, including explicit Chinese phrasing requirements such as “用一句人话定性今天的盘面.” Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is clearly documented and justified.
The entire template is written as prescriptive Chinese-language output format and wording, with no indication that users may choose another language. This creates a natural-language locale policy issue because it implicitly requires a specific language without opt-in or stated regional justification.
This markdown template presents all instructions and labels exclusively in Chinese, which can constitute a language/locale policy violation when no user choice or opt-in is offered. The file does not document that the skill is region-specific or otherwise justify the language restriction.
The file’s headings and authoring instructions are entirely in Chinese, including prescriptive output text such as '无候选时写:暂无命中。' and the required one-sentence judgment format. This creates a natural-language locale constraint with no indication that the user can opt into another language or that the skill is intentionally limited to a Chinese-language/regional use case.
标题与整份文档内容均以中文撰写,且未说明这是区域性/合规性要求,也没有提供其他语言选项。根据规则,若技能文档强制特定语言而无用户选择或明确正当理由,属于语言/locale 策略违规。
The README’s instructional content is entirely in Chinese, including usage guidance and behavior descriptions, with no indication that language selection is optional or that the skill is intentionally restricted to a Chinese-speaking context. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation.
The builder hard-codes lang: str = "zh-CN" as the default document language, which imposes a specific locale on all generated reports unless callers explicitly override it. This is a natural-language locale policy concern because the file does not indicate user choice or a documented region-specific justification for forcing Chinese locale by default.
The manifest frames this skill as a methodology for generating post-market analysis evidence from Tushare-derived daily data, with emphasis on producing deterministic evidence packages. This file goes beyond read-only analysis by implementing multiple mutating operations against backend storage, including DELETE, TRUNCATE, and bulk INSERTs for daily frames, datasets, and market history.
The code performs a full-table destructive operation with TRUNCATE TABLE when writing unkeyed datasets, which can irreversibly remove existing data before reinserting replacement rows. Although the docstring mentions 'full replacement', there is no user-facing disclosure, confirmation prompt, or explicit warning near the destructive action itself.
This statement irreversibly clears the entire market_history table before re-inserting data. The function docstring says 'Replace market_history table contents', but there is no explicit user-facing warning, confirmation, or disclosure that all existing records will be deleted as part of the operation.
Normal execution updates persistent reference CSV/JSON files or database state rather than acting as a read-only evidence generator. This side effect can poison future analyses, create nondeterministic outputs across runs, and let bad upstream data become long-lived local state.
No suspicious patterns detected.