T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/jules.sh:77
- Finding
- Unsafe JSON Construction Permits Request-Body Manipulation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/jules.sh`, lines 77-103 **Vulnerability Type**: Improper escaping of user-controlled JSON values **Risk Level**: Medium ### Vulnerable Code ```bash SOURCE_ID="$2" BRANCH="$3" PROMPT="$4" TITLE="${5:-}" REQUIRE_APPROVAL="false" AUTOMATION_MODE="" shift 4 for arg in "$@"; do case "$arg" in --approve) REQUIRE_APPROVAL="true" ;; --auto-pr) AUTOMATION_MODE="AUTO_CREATE_PR" ;; *) TITLE="$arg" ;; esac done # Build JSON body BODY="{\"prompt\":$(echo "$PROMPT" | jq -Rs .),\"sourceContext\":{\"source\":\"sources/$SOURCE_ID\",\"githubRepoContext\":{\"startingBranch\":\"$BRANCH\"}},\"requirePlanApproval\":$REQUIRE_APPROVAL" if [ -n "$TITLE" ] && [ "$TITLE" != "--approve" ] && [ "$TITLE" != "--auto-pr" ]; then BODY="$BODY,\"title\":$(echo "$TITLE" | jq -Rs .)" fi if [ -n "$AUTOMATION_MODE" ]; then BODY="$BODY,\"automationMode\":\"$AUTOMATION_MODE\"" fi BODY="$BODY}" post "$BASE_URL/sessions" "$BODY" | pretty ``` ### Technical Analysis The script incorporates the user-controlled `SOURCE_ID` and `BRANCH` arguments directly into a JSON string without JSON encoding them. In contrast, `PROMPT` and `TITLE` are encoded using `jq -Rs .`. An argument containing quotation marks or JSON structural characters can terminate the intended string and inject additional JSON properties. Depending on how the Jules API handles duplicate fields, an attacker may be able to alter the source context, branch, approval requirement, automation mode, or other supported session properties. Even if the API rejects duplicate or unknown properties, malformed input can reliably invalidate the request and cause denial of service. This is JSON injection rather than shell command injection: shell quoting prevents the arguments from becoming shell syntax, but it does not make them safe for insertion into JSON. ### Attack Path 1. An attacker gains influence over arguments passed to the `create` command, such as through ...[truncated 895 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Construct the entire request with `jq` rather than concatenating JSON strings. Pass every string value through `--arg`, and pass booleans through `--argjson`. For example: ```bash BODY=$(jq -n \ --arg prompt "$PROMPT" \ --arg source "sources/$SOURCE_ID" \ --arg branch "$BRANCH" \ --arg title "$TITLE" \ --arg automationMode "$AUTOMATION_MODE" \ --argjson requirePlanApproval "$REQUIRE_APPROVAL" \ '{ prompt: $prompt, sourceContext: { source: $source, githubRepoContext: {startingBranch: $branch} }, requirePlanApproval: $requirePlanApproval } + if $title != "" then {title: $title} else {} end + if $automationMode != "" then {automationMode: $automationMode} else {} end') ``` Additionally: - Validate `SOURCE_ID` against the exact resource-name format expected by the API. - Validate branch names using an allowlist or Git-compatible branch-name rules. - Reject control characters and unexpected resource path separators. - Treat API-side validation as defense in depth, not as a substitute for correct JSON encoding. ]]>
