T09 · Insecure Skill Coding Practices
- Location
platforms/dingtalk/scripts/somark_dingtalk/sheet_route.py:44- Finding
DingTalk Spreadsheet Image Processing Allows SSRF and Internal Data Upload
- Content
View full analysis
bool: parsed = urlparse(value.strip()) return parsed.scheme.casefold() in {"http", "https"} and bool(parsed.netloc) ``` Image references are derived from table content in the supplied SoMark JSON: ```python references = list(source.image_references) references.extend( (match.group(1), None, None) for match in _MARKDOWN_IMAGE_RE.finditer(source.text) ) seen_refs: set[str] = set() for reference, width_px, height_px in references: if reference in seen_refs: continue seen_refs.add(reference) images.append( ImagePlan( cell=cell, source_reference=reference, local_path=_local_asset(reference, assets), width=width_px, height=height_px, ) ) ``` The downloader follows the supplied URL without private-network or redirect-destination validation: ```python def download_remote_image( reference: str, destination_dir: Path, *, timeout: float = 30.0, max_bytes: int = _MAX_IMAGE_BYTES, ) -> Path: """Materialize one SoMark table-image URL after the preview is ready.""" if not is_remote_image_reference(reference): raise ValueError("image reference is not an HTTP(S) URL") parsed = urlparse(reference.strip()) if parsed.username or parsed.password: raise ValueError("image URL must not contain credentials") request = Request(reference, headers={"User-Agent": "SoMark-DingTalk-Adapter/1"}) destin ...[truncated 4842 chars]- Remediation
View remediation
