T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/mdnew_to_mdx.sh:18
- Finding
- Untrusted Remote Content Is Written Directly to an Executable MDX File<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mdnew_to_mdx.sh`, lines 18-70 **Vulnerability Type**: Untrusted MDX generation and insufficient input validation **Risk Level**: Medium ### Vulnerable Code ```bash curl -sS -D - "https://markdown.new/${source_url}" > "$raw_file" awk 'BEGIN{p=0} /^Markdown Content:/{p=1; next} p{print}' "$raw_file" > "$body_file" src_title="" src_description="" if awk 'NR==1{exit ($0=="---" ? 0 : 1)}' "$body_file"; then src_title="$(awk 'BEGIN{inside=0} /^---$/{if(inside==0){inside=1; next}else{exit}} inside && /^title:[[:space:]]/{sub(/^title:[[:space:]]*/, ""); print; exit}' "$body_file")" src_description="$(awk 'BEGIN{inside=0} /^---$/{if(inside==0){inside=1; next}else{exit}} inside && /^description:[[:space:]]/{sub(/^description:[[:space:]]*/, ""); print; exit}' "$body_file")" fi if [ -z "$src_title" ]; then src_title="Official Doc" fi if [ -z "$src_description" ]; then src_description="Converted from docs via markdown.new" fi awk ' BEGIN { in_fm=0 } NR==1 && $0=="---" { in_fm=1; next } in_fm && $0=="---" { in_fm=0; next } in_fm { next } { if ($0 ~ /^\[Skip to main content\]/) next if ($0 ~ /^\[\]\(https:\/\/[^)]*\)\[Docs\]\(\/home\)$/) next if ($0 ~ /^Copy as Markdown$/) next if ($0 ~ /^Copied!$/) next if ($0 ~ /^On this page$/) next if ($0 ~ /^[[:space:]]*\* \[[^]]+\]\(#[^)]+\)[[:space:]]*$/) next line=$0 gsub(/\[\]\(#[^)]+ "Direct link to [^"]+"\)/, "", line) print line } ' "$body_file" > "$content_file" awk ' { if ($0 ~ /^[[:space:]]*$/) { blank++; if (blank <= 1) print ""; next } blank=0; print } ' "$content_file" > "$clean_file" mkdir -p "$(dirname "$out_file")" { echo "---" echo "title: ${src_title}" echo "description: ${src_description}" echo "sourceUrl: ${source_url}" echo "retrievedAt: ${retrieved_at}" echo "---" echo cat "$clean_file" } > "$out_file" echo "Wrote ${out_file}" ``` ### Technical Analysis The script accepts an arbitrary source string wi ...[truncated 2884 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Validate source URLs before making the request** - Parse the source as a URL rather than relying on string checks. - Require the `https` scheme. - Reject embedded credentials, control characters, fragments where unnecessary, and malformed hostnames. - Consider an explicit allowlist of approved official documentation domains. - Resolve redirects carefully and ensure that the final target remains within the approved policy. 2. **Treat the converted response as untrusted** - Parse the result with a maintained Markdown/MDX parser. - Reject ESM imports and exports, JSX, JavaScript expressions, raw HTML, and unknown nodes unless they are explicitly required. - Use an allowlist of permitted Markdown syntax instead of regular-expression cleanup. - Reject the conversion if parsing fails. 3. **Prefer non-executable output** - Generate `.md` rather than `.mdx` when executable MDX features are unnecessary. - If `.mdx` is required, configure the downstream compiler to disable or strictly restrict executable constructs and custom components. 4. **Serialize frontmatter safely** - Use a YAML serializer instead of direct `echo` interpolation. - Ensure `title`, `description`, and `sourceUrl` are emitted as properly escaped scalar values. - Apply length and character restrictions to metadata fields. 5. **Add post-generation verification** - Scan the generated document for prohibited MDX node types before replacing the destination. - Build into a temporary file and atomically move it to the destination only after validation succeeds. - Record the source domain and validation outcome for auditability. 6. **Constrain output destinations at the caller boundary** - If this script is invoked by an agent or service, restrict output paths to an approved documentation directory. - Run the conversion and subsequent build with minimal filesystem, environment, and network privileges. ]]>
