T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/deploy_site.sh:1
- Finding
- Unvalidated Subdomain Allows Docker Compose YAML Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/deploy_site.sh:1` **Vulnerability Type**: Docker Compose YAML injection through unvalidated input **Risk Level**: High ### Vulnerable Code ```bash SUBDOMAIN=\"$2\" DOMAIN=\"sites.friendify.cloud\" FULL_DOMAIN=\"${SUBDOMAIN}.${DOMAIN}\" TEMP_DIR=\"/tmp/traefik-deploy-${SUBDOMAIN}-$(date +%s)\" mkdir -p \"$TEMP_DIR\" || { echo \"Failed to create temporary directory\"; exit 1; } cat <<EOF > \"$TEMP_DIR/docker-compose.yml\" version: '3.8' services: nginx: image: nginx:alpine container_name: \"${SUBDOMAIN}-web\" labels: - \"traefik.enable=true\" - \"traefik.http.routers.${SUBDOMAIN}-router.rule=Host(\`${FULL_DOMAIN}\`)\" - \"traefik.http.routers.${SUBDOMAIN}-router.entrypoints=websecure\" - \"traefik.http.routers.${SUBDOMAIN}-router.tls=true\" - \"traefik.http.routers.${SUBDOMAIN}-router.tls.certresolver=le\" - \"traefik.http.services.${SUBDOMAIN}-service.loadbalancer.server.port=80\" networks: - web networks: web: external: true EOF pushd \"$TEMP_DIR\" || { echo \"Failed to change directory to $TEMP_DIR\"; exit 1; } docker compose up -d || { echo \"Failed to start docker compose services\"; popd; exit 1; } ``` ### Technical Analysis The second positional argument is accepted as `SUBDOMAIN` without validation and interpolated directly into a generated Docker Compose YAML document. Shell quoting around the variable does not protect the structure of the generated YAML because variable expansion occurs while processing the heredoc. A subdomain containing quote characters, line breaks, or YAML syntax can potentially terminate an existing scalar and inject additional Compose properties. Depending on the crafted structure, an attacker could attempt to introduce properties such as: - Host filesystem bind mounts - An attacker-controlled container command or entry point - Additional environment variables - Privileged container mode - Ho ...[truncated 1792 chars]
- Remediation
- <?$ ]]; then echo "Invalid subdomain" exit 1 fi ``` 2. Explicitly reject line breaks, carriage returns, tabs, quotes, slashes, backslashes, and control characters. 3. Generate Compose configuration using a structured YAML or JSON serializer rather than interpolating untrusted values into a heredoc. 4. Use an independently generated deployment identifier for Compose project, service, container, and temporary-directory names. Do not derive operational identifiers directly from user input. 5. Validate the generated Compose file before execution: ```bash docker compose -f "$TEMP_DIR/docker-compose.yml" config --quiet ``` 6. Run deployments through a narrowly scoped service rather than granting general Docker permissions to callers. 7. Pin the Nginx image to a reviewed immutable digest. 8. Restore real newline bytes in the script and add tests covering malicious quotes, control characters, multiline values, and oversized subdomains before making it executable. ]]>
