Component: finbot/mcp/servers/finstripe/server.py → create_transfer
Root cause: The invoice_id parameter is passed directly to repo.create_transaction() without ever fetching the invoice record to compare amounts.
txn = repo.create_transaction(invoice_id=invoice_id, amount=amount, ...)
# invoice.amount is never fetched or compared
Steps to reproduce:
- Create an invoice with amount=1000.0
- Call create_transfer(amount=9999.0, invoice_id=invoice.id, ...)
Expected: {"error": "..."} — amount must match invoice
Actual: transfer created for $9,999
How to execute:
pytest tests/unit/mcp/test_finstripe.py::TestFloatEdgeCases::test_mcp_float_007_amount_matches_invoice_amount_not_enforced -v
Proposed fix:
Add an invoice lookup in create_transfer inside the db_session block, before creating the transaction:
from finbot.core.data.models import Invoice
invoice = db.query(Invoice).filter(
Invoice.id == invoice_id,
Invoice.namespace == session_context.namespace
).first()
if not invoice:
return {"error": f"Invoice {invoice_id} not found"}
if round(amount, 2) != round(invoice.amount, 2):
return {"error": f"Amount {amount} does not match invoice amount {invoice.amount}"}
Impact:
Over-payment wastes funds; under-payment leaves vendor debts unresolved. Both are exploitable via prompt injection.
Acceptance criteria:
- test_mcp_float_007_amount_matches_invoice_amount_not_enforced passes
- test_mcp_create_transfer_001_successful_transfer continues to pass (matching amounts accepted)
Component: finbot/mcp/servers/finstripe/server.py → create_transfer
Root cause: The invoice_id parameter is passed directly to repo.create_transaction() without ever fetching the invoice record to compare amounts.
Steps to reproduce:
Expected: {"error": "..."} — amount must match invoice
Actual: transfer created for $9,999
How to execute:
Proposed fix:
Add an invoice lookup in create_transfer inside the db_session block, before creating the transaction:
Impact:
Over-payment wastes funds; under-payment leaves vendor debts unresolved. Both are exploitable via prompt injection.
Acceptance criteria: