T09 · Insecure Skill Coding Practices
- Location
scripts/generate_pipeline.py:276- Finding
Untrusted Experiment Plan Values Are Embedded into Executable Python Code
- Content
View full analysis
Vulnerability Details
File Location:
scripts/generate_pipeline.py, source extraction at lines 62–67, 75–79, and 89–96; vulnerable code-generation sink at lines 276–288
Vulnerability Type: Python code injection through unsafe string interpolation
Risk Level: HighVulnerable Code
The generator extracts attacker-controlled strings directly from the experiment plan:
python config['dataset'] = { 'name': name_match.group(1).strip() if name_match else 'unknown', 'type': type_match.group(1).strip() if type_match else 'unknown', 'scale': scale_match.group(1).strip() if scale_match else 'unknown', 'input_shape': input_match.group(1).strip() if input_match else None, 'output_shape': output_match.group(1).strip() if output_match else None, }python config['model'] = { 'backbone': backbone_match.group(1).strip() if backbone_match else 'resnet18', 'num_layers': int(layers_match.group(1)) if layers_match else None, 'hidden_size': int(hidden_match.group(1)) if hidden_match else 128, }python config['training'] = { 'optimizer': optimizer_match.group(1).strip().lower() if optimizer_match else 'adamw', 'learning_rate': float(lr_match.group(1)) if lr_match else 0.001, 'batch_size': int(batch_match.group(1)) if batch_match else 32, 'epochs': int(epochs_match.group(1)) if epochs_match else 100, 'loss': loss_match.group(1).strip().lower() if loss_match else 'cross_entropy', }These strings are then embedded verbatim inside quoted Python literals:
python class Config: # 任务类型 task_type = "{config.get('task_type', 'classification')}" # 数据集配置 dataset_name = "{dataset_info.get('name', 'unknown')}" dataset_type = "{dataset_info.get('type', 'image')}" num_classes = {num_classes} # 模型配置 model_name = "{model_info.get('backbone', 'resnet18')}" pre ...[truncated 2593 chars]- Remediation
View remediation
Remediation Suggestions
-
Do not construct Python string literals by directly interpolating untrusted text.
-
Serialize every generated Python string with a safe representation:
python dataset_name = repr(dataset_info.get('name', 'unknown')) dataset_type = repr(dataset_info.get('type', 'image')) model_name = repr(model_info.get('backbone', 'resnet18')) optimizer = repr(training_info.get('optimizer', 'adamw'))The template should then insert those already escaped literals without adding another pair of quotation marks.
-
Prefer generating a non-executable configuration file such as YAML or JSON using
yaml.safe_dump()orjson.dump(), and load it as data rather than Python source. -
Apply strict allowlists to fields with a finite set of supported values:
- Dataset type: supported dataset categories only.
- Optimizer:
adamw,adam, orsgd. - Model name: explicitly supported model identifiers.
- Task type: explicitly supported task identifiers.
-
Reject line breaks, control characters, and invalid syntax in fields intended to be simple identifiers.
-
Add regression tests using quotation marks, backslashes, multiline values, comments, and Python expressions in every interpolated plan field.
-
Treat generated code as untrusted until it has passed syntax validation and security review.
-
