T09 · Insecure Skill Coding Practices
- Location
scripts/fxusd_morpho.py:460- Finding
Untrusted remote market metadata controls approval spenders and transaction destinations
- Content
View full analysis
Vulnerability Details
File Location:
scripts/fxusd_morpho.py:214-232,scripts/fxusd_morpho.py:460-507,scripts/fxusd_morpho.py:553-557,scripts/fxusd_morpho.py:664-687, andscripts/fxusd_morpho.py:1078-1151
Vulnerability Type: Insufficient validation of execution-critical remote data
Risk Level: HighVulnerable Code
The Morpho GraphQL response is accepted directly:
python def request_graphql(query: str, variables: dict[str, Any]) -> Any: last_error: Exception | None = None payload = json.dumps({"query": query, "variables": variables}).encode("utf-8") for delay in (0.0, 0.4, 1.0): if delay: time.sleep(delay) request = urllib.request.Request( GRAPHQL_URL, data=payload, headers={ "Content-Type": "application/json", "Accept": "application/json", "User-Agent": USER_AGENT, }, method="POST", ) try: with urllib.request.urlopen(request, timeout=20) as response: decoded = json.loads(response.read().decode("utf-8")) if decoded.get("errors"): raise ValueError(f"GraphQL error: {decoded['errors']}") return decoded["data"]Remote metadata supplies the contract destination:
python def normalize_market(market: dict[str, Any]) -> dict[str, Any]: state = market.get("state") or {} collateral_asset = market.get("collateralAsset") or {} loan_asset = market.get("loanAsset") or {} morpho_blue = market.get("morphoBlue") or {} oracle = market.get("oracle") or {} warnings = market.get("warnings") or [] collateral_symbol = collateral_asset.get("symbol") risk_class, risk_summary = classify_collateral(collateral_symbol) return { "uniqueKey": market.get("uniqueKey"), "tit ...[truncated 5922 chars]- Remediation
View remediation
Remediation Suggestions
-
Require the normalized Morpho destination to exactly match the known Base deployment:
python remote_morpho = validate_address( morpho_blue.get("address") or "", "Morpho Blue address", ) if remote_morpho.lower() != MORPHO_BLUE_ADDRESS.lower(): raise ValueError("Unexpected Morpho Blue contract address.") -
Maintain chain-specific allowlists for all contracts capable of receiving approvals or write transactions.
-
Verify market parameters independently on-chain before transaction construction. Recompute the market identifier from the loan token, collateral token, oracle, IRM, and LLTV, then compare it with the API result.
-
Ensure the returned loan-token address exactly matches the token requested by the user. Verify token decimals on-chain rather than trusting remote metadata.
-
Validate that the API response identifies Base chain ID
8453and reject absent, malformed, or inconsistent chain metadata. -
Decode every generated transaction before presenting it as Bankr-ready. Display and require confirmation of:
- Destination contract
- Function selector
- Approval spender
- Token and amount
- Receiver and beneficiary
- Market parameters
-
For fxSAVE, validate the hosted backend's returned approval spender and main transaction destination against deployment-specific allowlists before execution.
-
Treat API data as advisory only. Fail closed when independent contract verification cannot be completed.
-
