T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/deposit-rewards.sh:34
- Finding
- Arbitrary Python Code Execution Through Unsanitized Reward Amounts<![CDATA[ ## Vulnerability Details **File Location**: `scripts/deposit-rewards.sh`, lines 34–36 **Vulnerability Type**: Command injection through dynamically constructed Python source **Risk Level**: High ### Vulnerable Code ```bash # Convert amounts to wei ETH_WEI=$(python3 -c "print(int(float('$ETH_AMOUNT') * 10**18))") CLAWMEGLE_WEI=$(python3 -c "print(int(float('$CLAWMEGLE_AMOUNT') * 10**18))") ``` Related unsafe interpolation also occurs at lines 47 and 68: ```bash CLAWMEGLE_HEX=$(python3 -c "print(format($CLAWMEGLE_WEI, '064x'))") ``` ### Technical Analysis The script accepts `ETH_AMOUNT` and `CLAWMEGLE_AMOUNT` from command-line arguments and directly inserts them into source code supplied to `python3 -c`. Shell quoting does not make this safe because the untrusted value becomes part of the Python program. A crafted argument can terminate the Python string passed to `float()`, add another Python statement, and comment out or otherwise neutralize the remaining syntax. Python then executes the injected statement with the privileges of the user running the script. The script performs no strict decimal validation before constructing the Python program. Consequently, this is not limited to malformed numeric input or denial of service; it creates a general local code-execution primitive. The subsequent interpolation of `CLAWMEGLE_WEI` into additional Python source should also be removed as a defense-in-depth measure. ### Attack Path 1. An attacker influences an argument passed to `scripts/deposit-rewards.sh`. This may occur through direct invocation, an automation workflow, or an agent that forwards an untrusted amount. 2. The attacker supplies text that closes the quoted Python value and introduces an additional Python statement, such as importing an operating-system interface and invoking a local command. 3. Bash substitutes the crafted value into the `python3 -c` source string. 4. Python parses and executes the injected statement while converting ...[truncated 1134 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Never interpolate untrusted values into executable Python source. Pass each amount as a positional argument and parse it as data: ```bash ETH_WEI=$(python3 - "$ETH_AMOUNT" <<'PY' from decimal import Decimal, InvalidOperation import re import sys raw = sys.argv[1] if not re.fullmatch(r"(?:0|[1-9][0-9]*)(?:\.[0-9]{1,18})?", raw): raise SystemExit("Invalid ETH amount") try: value = Decimal(raw) except InvalidOperation: raise SystemExit("Invalid ETH amount") if value < 0: raise SystemExit("Amount must not be negative") wei = value * Decimal(10**18) if wei != wei.to_integral_value(): raise SystemExit("Amount has more than 18 decimal places") print(int(wei)) PY ) ``` Apply equivalent validation to `CLAWMEGLE_AMOUNT`. Additional hardening should include: 1. Use `decimal.Decimal` rather than binary floating-point arithmetic to avoid rounding errors in financial values. 2. Reject negative values, signs, exponent notation, `NaN`, infinity, whitespace, and more than 18 decimal places. 3. Enforce an application-appropriate maximum amount to prevent oversized transactions and resource abuse. 4. Pass `CLAWMEGLE_WEI` as a Python argument when formatting it, rather than embedding it in Python source: ```bash CLAWMEGLE_HEX=$(python3 - "$CLAWMEGLE_WEI" <<'PY' import sys value = int(sys.argv[1]) if value < 0 or value >= 2**256: raise SystemExit("Amount is outside uint256 range") print(format(value, "064x")) PY ) ``` 5. Add automated tests using malformed input containing quotes, semicolons, newlines, shell metacharacters, exponent notation, negative values, and values outside the `uint256` range. 6. Require explicit transaction confirmation displaying the validated decimal amount, wei amount, chain, token, and destination contract before submitting a deposit. ]]>
