AEV-2026-0046
Vibe-Trading's MCP live order gate priced a buy limit order at the quote alone, five days after the identical gap was fixed on the direct SDK path
Vibe-Trading's MCP order-placing gate, LiveOrderGuardTool, together with the Robinhood connector's own extract_order_intent, sized a buy limit order's notional from the live quote alone, never mapping or comparing against the order's own submitted limit price, even though the direct SDK gate had already been fixed to price a buy limit at the larger of the quote and the limit five days earlier. A mandate capping order notional at 750 dollars allowed and forwarded a 5 unit, 200 dollar buy limit order priced by the gate at 500 dollars, on a 100 dollar quote, while the order's own executable terms permitted a fill of up to 1,000 dollars.
Affected
- Organisation
- HKUDS
- Product
- Vibe-Trading, an open source LLM agent trading framework, MCP live order gate buy limit notional sizing
- Component
- LiveOrderGuardTool._normalize_intent_notional (src.live.order_guard) together with the Robinhood connector's extract_order_intent (src.trading.connectors.robinhood.extractor)
- Versions
- Every commit before merge commit 07ad49f888c7ef658c773eeba4eb0a278d3bc8ea (pull request 1361), fixed in that commit, merged 6 September 2026
- Configurations
- The Robinhood broker connector's MCP order-placing tool (place_equity_order), gated by LiveOrderGuardTool, with a valid, unexpired mandate on file setting max_order_notional_usd; A buy order submitted with order_type limit, a quantity, and a limit_price above the live quote for the symbol
Execution authority facts
Fields the evidence does not establish are shown as unknown rather than guessed.
- Intended task
- Live agent trading under a per order notional mandate that Vibe-Trading's MCP gate is meant to enforce before an order reaches a connected broker
- Agent
- unknown
- Delegating actor
- unknown
- Action
- Submitted a buy limit order, quantity 5, limit price 200 dollars, against a live quote of 100 dollars, under a mandate capping max_order_notional_usd at 750 dollars
- Target resource
- The connected broker's own order execution for the submitted symbol, and the principal's own mandate ceiling on order notional
- Environment
- Vibe-Trading's live trading channel (src.live), MCP order placing path
- Credentials used
- unknown
- Privileges available
- Whatever the connected Robinhood account's own order placing permission allows, mediated through the MCP gate
- Authority presented
- The gate's own notional check, which priced the order at 5 units times the 100 dollar live quote, 500 dollars, inside the 750 dollar mandate
- Authority required
- Authority to place an order whose maximum executable notional, 5 units times the 200 dollar limit, 1,000 dollars, would itself need to fall inside the 750 dollar mandate before the order is authorized
- Applicable policy
- LiveOrderGuardTool._normalize_intent_notional together with the Robinhood connector's extract_order_intent, which this record's own direct read of the pre-fix commit confirms priced a quantity order from the live quote alone and never mapped a limit_price keyword argument into the normalized OrderIntent, even though OrderIntent itself already carried a limit_price field following the separately merged direct SDK fix
- Approval mechanism
- Automated policy check, not human review
- Required approver
- unknown
- Independent approval
- no
- Action binding
- The authorization decision was computed from a 500 dollar quote derived notional while the order forwarded to the broker's own place_equity_order call, unchanged, carried the 200 dollar limit permitting a 1,000 dollar executable fill
- Sequence context
- Order intent extraction, notional normalization and the mandate check ran in one automated pass immediately before the order would have been forwarded to the broker; the direct SDK gate for the same broker had already been fixed for the identical sizing gap five days earlier
Impact
- Consequence
- material
- Reach
- single
- Reversibility
- unknown
- Detectability
- unknown
- Propagation
- potential
- Recovery
- Not established by anything available to this record. Nothing in Vibe-Trading's own repository describes a compensating control, such as an independent post fill reconciliation against the mandate, for an order that executed above the notional the gate believed it was authorizing.
Evidence
Primary sources
- fix(live): size MCP buy-limit orders at the worse of quote and limit (pull request 1361) (GitHub, HKUDS/Vibe-Trading)
- fix(live): size buy-limit orders at the worse of quote and limit (pull request 1312) (GitHub, HKUDS/Vibe-Trading)
- HKUDS/vibe-trading, commit 07ad49f888c7ef658c773eeba4eb0a278d3bc8ea (merge of pull request 1361) (GitHub, HKUDS/Vibe-Trading)
- HKUDS/vibe-trading, commit 789ca2b11255f2abe2c54f83c838e34a123a7702 (merge of pull request 1312) (GitHub, HKUDS/Vibe-Trading)
Supporting sources
- HKUDS/vibe-trading (GitHub)
- Reproduction status
- Independently reproduced for this record, not merely read from the pull request's own description: both merge commits and both pre-fix parent commits were checked out directly, the pull requests' own added gate fixtures were run against each, and the exact stated scenario, quantity 5, quote 100 dollars, limit 200 dollars, mandate 750 dollars, was executed directly against the MCP gate. At the pre-fix commit (cc4774ed) the gate returned an ok, allowed decision sized at 500 dollars and forwarded the order; at the fixed commit (74c16db6) the identical call returned a blocked decision citing the 750 dollar mandate limit with an attempted value of 1,000 dollars, and the order was never forwarded. 8 of the pull request's 29 new or modified test assertions fail at the pre-fix commit and all 29 pass at the fixed commit.
- Evidence state
- Confirmed
Known unknowns
- Whether this exact gap was ever exercised against a real, funded broker account rather than the repository's own test fixtures and mandate mock. Nothing available to this record states that a real order executed above its mandate.
- Whether any broker connector other than Robinhood is registered against the MCP gate's own extractor lookup table with the identical gap, since only Robinhood is registered there as of the fixed commit.
- Whether Vibe-Trading's own broker connectors expose a stop price or other trigger style field whose semantics would require the identical worse of comparison; no such field is mapped by any extractor this record read.
- Whether the five day gap between the two fixes reflects two separate contributors each fixing only the surface they were looking at, or a single contributor who did not initially recognize the MCP gate as a second, independently vulnerable surface; the pull requests' own text does not say.
Limitations
- This record's evidence rests on a direct, independent checkout and test run of the public HKUDS/vibe-trading repository at the exact commits named above, rather than on the pull requests' own descriptions alone. The repository's full dependency set could not be installed unmodified in this session because of one unrelated build failure in a transitive dependency, jsonpath; the specific packages the affected modules and their tests import were installed individually into an isolated virtual environment, and all 29 relevant tests ran successfully under it. This record does not claim to have run the project's complete test suite.
Claim provenance
- verified
Fetched directly by cloning the repository and reading the pull request's merge commit, its parent commits and its diff directly, rather than reading the pull request's rendered page. Confirms the title, the merge commit hash, the merge date, the affected files (order_guard.py, the Robinhood extractor, two test files) and the added tests described throughout this entry.
The Mandate Capped the Trade at $750. The MCP Gate Approved an Order the Broker Could Fill for $1,000. - verified
Fetched directly by cloning the repository and reading the pull request's merge commit, its parent commits and its diff directly. Confirms the direct SDK gate's own fix, merged 1 September 2026, five days before pull request 1361, adding limit_price to OrderIntent and the worse of quote and limit rule to sdk_order_gate._implied_notional.
The Mandate Capped the Trade at $750. The MCP Gate Approved an Order the Broker Could Fill for $1,000. - verified
Both merge commits fetched and diffed directly against their respective parent commits. Confirms the exact source changes to order_guard.py, the Robinhood extractor, enforcement.py, sdk_order_gate.py and trading/service.py described throughout this entry, and that the pre-fix source for each lacks the corresponding worse of quote and limit comparison.
The Mandate Capped the Trade at $750. The MCP Gate Approved an Order the Broker Could Fill for $1,000.
