T09 · Insecure Skill Coding Practices
- Location
scripts/data_transformer.py:327- Finding
Transform Sandbox Escape Through Exposed NumPy Native-Library Interfaces
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This data-reporting skill is coherent, but it can run generated Python and evaluate chart JavaScript in ways that may execute unsafe code if inputs are hostile.
Review before installing. Use this skill only with trusted datasets, chart specs, and generated chart HTML; avoid letting untrusted prompts or files supply transform_code or report_spec chart paths. Prefer running it in a constrained environment with limited filesystem and network access, and consider lockfile/hash controls for dependencies.
scripts/data_transformer.py:327Transform Sandbox Escape Through Exposed NumPy Native-Library Interfaces
scripts/report_assembler.py:118Untrusted Chart JavaScript Is Evaluated by Node.js and Embedded into Generated Reports
requirements.txt:15Mutable Dependency Ranges Permit Unreviewed Supply-Chain Changes
Skill instructs the agent to omit warnings, disclaimers, or ethical commentary. Stripping safety caveats hides risk from the user and is a common jailbreak preamble.
**Numeric coercion is observable:** string columns are cleaned (currency symbols → thousands separators → `%` → Chinese magnitude suffixes `亿`/`万`/`千`, so `8.5万` → `85000`) and then coerced. If only *some* cells fail to parse but ≥50% succeed, the column still becomes numeric with the failures set to missing, and an advisory is emitted naming the column and the number of discarded cells. Below 50% the column is left as text. Previously a single stray `-` silently degraded a whole column to string with no warning.
This code executes LLM-generated Python via exec(), which is inherently dangerous because the surrounding blacklist/AST checks are incomplete as a sandbox boundary. The execution context exposes powerful live objects such as pandas, numpy, and a builtins mapping; attackers can often reach dangerous functionality through object graph traversal, denial-of-service primitives, or overlooked library methods despite superficial filtering.
# P2-print 修复:把 transform 代码里的 print 重定向到 stderr,
# 避免污染 cli.py 末尾输出到 stdout 的 JSON 契约。
with contextlib.redirect_stdout(sys.stderr):
exec(code, ns)
except TimeoutError:
raise TransformError(
f"转换代码执行超时(超过 {self.timeout} 秒),可能存在无限循环",
Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.
manifest_path = out_dir / '_manifest.json'
manifest_path.parent.mkdir(parents=True, exist_ok=True)
manifest_path.write_text(json.dumps(manifest, ensure_ascii=False), encoding='utf-8')
env = os.environ.copy()
env['NODE_PATH'] = str(skill_root / 'scripts')
try:
proc = subprocess.run(
The skill clearly instructs the agent to read local files, write outputs, inspect environment/runtime paths, invoke shell commands, and potentially use optional export dependencies, yet it declares no explicit tool scope or permission boundaries. That creates a real least-privilege gap: an agent may execute broad file and shell operations under this skill without user-visible guardrails, increasing the blast radius if the skill is misused or if downstream prompts become adversarial.
The activation triggers include broad phrases like '写报告', '分析报告', '汇报材料', and 'report', which are common in normal conversation and not tightly bounded to the specific data-to-report workflow. Over-broad activation can cause the skill to engage in unintended contexts, leading the agent to read files, generate artifacts, or run shell-based pipelines when the user did not clearly request this high-capability behavior.
The docstring states that lang is forced to 'zh' or 'en', and the validation later rejects any other locale. This is a language/locale policy constraint that does not offer broader user choice or document a justified region-specific limitation.
The validation explicitly rejects any lang value except 'zh' and 'en'. That hard-coded restriction forces a limited language policy without offering user opt-in to other locales or documenting a justified compliance reason.
The module docstring and many user-facing strings in this CLI are written only in Chinese, which imposes a specific language on users. Under the stated policy, forcing a language without offering a user choice or documenting a justified locale restriction is a natural-language policy violation.
Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.
ok_all = True
for name, min_ver in REQUIREMENTS:
try:
mod = __import__(name)
ver = getattr(mod, '__version__', 'unknown')
ok = _version_ok(ver, min_ver)
except ImportError as e:
The parser help text, option descriptions, and validation errors are consistently Chinese-only, so users are required to interact in that locale. Although a --lang flag exists, it controls chart text rather than CLI interface language, so it does not mitigate the policy issue for command help and errors.
This code file contains natural-language strings entirely in Chinese, including the top-level docstring and later CLI/help text, with no indication that users may choose another language. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless clearly justified as region-specific, which is not documented here.
The file raises exceptions, prints summaries, and emits advisories/warnings using Chinese-language strings throughout the implementation. Because these are direct user-visible outputs and no locale negotiation or configuration exists, the skill effectively mandates one language for all users.
The top-level docstring states that the sandboxed builtins prohibit access to open/exec/eval/import and presents this as a safety property. However, the executor later assigns ns['builtins'] = safe_builtins, meaning builtins is in fact exposed to executed code, albeit in a restricted form. This is an active contradiction between the stated sandbox model and the implemented behavior.
This code file performs a safety-critical operation by executing user/LLM-supplied code via a sandbox, and the surrounding documentation explicitly says execution proceeds without user confirmation. While the file documents the sandboxing, it lacks a user-facing confirmation or disclosure at the execution point for this risky operation.
The script executes manifest-provided JavaScript via vm.runInContext, while the comment explicitly downplays the risk. Even in a VM context, untrusted JavaScript can still trigger denial of service, unsafe code paths in loaded libraries, and in some Node.js configurations may enable sandbox escape or access to powerful globals; treating a locally generated manifest as inherently trusted is a fragile trust assumption. In this skill context, the danger is increased because the file is an automation/export utility likely to process generated data without human review, making supply-chain or upstream data tampering more plausible.
The module docstring and all user/developer-facing explanatory text in this file are written exclusively in Chinese, with no indication that another language is supported or that the user can choose a locale. Under the stated policy, forcing a specific language without opt-in is a natural-language policy violation.
This Python file contains natural-language instructions and slide text entirely in Chinese, including the module description and generated presentation labels. Under the policy rule, forcing a specific language without user opt-in is a locale/language policy violation, and there is no indication in this file that users can choose another language or that the constraint is justified as region-specific.
This Python script's user-facing natural language is entirely in Chinese, including the module docstring, usage text, test names, and printed status messages, and there is no indication that the user can select another language for the script's own interface. Under the policy rule for language/locale constraints, forcing a specific language without opt-in is a natural-language policy violation.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def run_cli(args, timeout=90):
t0 = time.time()
proc = subprocess.run([sys.executable, str(CLI)] + [str(a) for a in args],
capture_output=True, text=True, timeout=timeout)
dt = time.time() - t0
out = None
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
return proc.returncode, out, proc.stderr, dt
def run_dp(args, timeout=60):
proc = subprocess.run([sys.executable, str(DP)] + [str(a) for a in args],
capture_output=True, text=True, timeout=timeout)
return proc.returncode, proc.stdout, proc.stderr
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
rec("P1-8-requirements改用兼容区间",
'pandas>=' in _req and 'pandas==' not in _req and 'numpy>=' in _req,
f"{_req[:80]}")
_proc = subprocess.run([sys.executable, str(CLI), '--doctor'], capture_output=True, text=True, timeout=60)
try:
_doc = json.loads(_proc.stdout)
rec("P1-8---doctor输出版本矩阵",
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
(ROOT / 'report_spec.json').write_text(json.dumps(_spec, ensure_ascii=False), encoding='utf-8')
# 组装(scan 模式 + 仅 html)
_out_html = ROOT / 'report.html'
_proc = subprocess.run([sys.executable, str(_RA), '--spec', str(ROOT / 'report_spec.json'),
'--charts-dir', str(_rchart_dir), '--output', str(_out_html),
'--ledger', str(ROOT / 'ledger.json')],
capture_output=True, text=True, timeout=120)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
# ── R4~R10:论点台账(claims.json)形式校验 ──
def run_ra(extra_args, out_name='report_claims.html', timeout=120):
_proc = subprocess.run([sys.executable, str(_RA),
'--spec', str(ROOT / 'report_spec.json'),
'--charts-dir', str(_rchart_dir),
'--output', str(ROOT / out_name)] + [str(a) for a in extra_args],
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
"annotation": "本图并列展示两条系列。"},
]
(ROOT / 'report_spec_ph.json').write_text(json.dumps(_spec_ph, ensure_ascii=False), encoding='utf-8')
_proc10 = subprocess.run([sys.executable, str(_RA),
'--spec', str(ROOT / 'report_spec_ph.json'),
'--charts-dir', str(_rchart_dir),
'--output', str(ROOT / 'report_ph.html'),
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
(ROOT / 'report_spec_narr.json').write_text(json.dumps(_spec_narr, ensure_ascii=False), encoding='utf-8')
_claims_narr = [{"id": "c1", "claim": "有图章节的主张", "evidence": ["s1"], "section": "s1"}]
(ROOT / 'claims_narr.json').write_text(json.dumps(_claims_narr, ensure_ascii=False), encoding='utf-8')
_proc11 = subprocess.run([sys.executable, str(_RA),
'--spec', str(ROOT / 'report_spec_narr.json'),
'--charts-dir', str(_rchart_dir),
'--output', str(ROOT / 'report_narr.html'),
Detected: suspicious.dynamic_code_execution