v0.2.0 · live
CAPFRAME
§ serverhttpfindings.v2

SpaceMolt

https://game.spacemolt.com/mcp

Score
D0
Findings
340
Tools
210
Last scan
2026-07-20

Severity breakdown

Critical1
High79
Medium260
Low0
Info0

Worst finding

Tool `find_route` exposes a code/command execution surface

· find_route

`find_route` looks like it executes code or shell commands (Find the shortest route to a destination system, POI, or base (Uses BFS to find the shortest path from your current system. Accepts a system ID, POI ID, or base ID. If a POI or base is given, the response includes target_poi and target_poi_name for the final travel step within the destination system. Use search_systems to find system IDs. Response includes fuel_per_jump, estimated_fuel, fuel_available, and cargo_used for trip planning. Route steps may include via_wormhole: true and entrance_poi when a hop uses a known wormhole shortcut — execute those hops with jump({target_system}) from anywhere in the entrance system.)). Arbitrary execution is the maximal authority a tool can hold -- it subsumes every other caveat, so it should never be exposed to an agent without a hard sandbox and an explicit, narrowly-scoped capability.

fix: Do not expose raw code/shell execution to an agent. If unavoidable, run it in a disposable sandbox with no network + no host FS, gate it behind a capframe-bind capability scoped to an allow-list of commands, and require holder-of-key proof per call.

All 340 findings

  1. critical
    Tool `find_route` exposes a code/command execution surface· find_routeexcessive agency

    `find_route` looks like it executes code or shell commands (Find the shortest route to a destination system, POI, or base (Uses BFS to find the shortest path from your current system. Accepts a system ID, POI ID, or base ID. If a POI or base is given, the response includes target_poi and target_poi_name for the final travel step within the destination system. Use search_systems to find system IDs. Response includes fuel_per_jump, estimated_fuel, fuel_available, and cargo_used for trip planning. Route steps may include via_wormhole: true and entrance_poi when a hop uses a known wormhole shortcut — execute those hops with jump({target_system}) from anywhere in the entrance system.)). Arbitrary execution is the maximal authority a tool can hold -- it subsumes every other caveat, so it should never be exposed to an agent without a hard sandbox and an explicit, narrowly-scoped capability.

    fix: Do not expose raw code/shell execution to an agent. If unavoidable, run it in a disposable sandbox with no network + no host FS, gate it behind a capframe-bind capability scoped to an allow-list of commands, and require holder-of-key proof per call.

  2. high
    Tool `shipping` accepts an unbounded monetary / quota value· shippingexcessive agency

    The numeric parameter(s) `amount`, `max_total_cost` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  3. high
    Tool `set_status` name implies a side effect that is not declared· set_statusexcessive agency

    `set_status` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  4. high
    Tool `delete_note` name implies a side effect that is not declared· delete_noteexcessive agency

    `delete_note` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  5. high
    Tool `estimate_purchase` name implies a side effect that is not declared· estimate_purchaseexcessive agency

    `estimate_purchase` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  6. high
    Tool `estimate_purchase` accepts an unbounded monetary / quota value· estimate_purchaseexcessive agency

    The numeric parameter(s) `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  7. high
    Tool `prepay_tax` accepts an unbounded monetary / quota value· prepay_taxexcessive agency

    The numeric parameter(s) `amount` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  8. high
    Tool `faction_withdraw_items` accepts an unbounded monetary / quota value· faction_withdraw_itemsexcessive agency

    The numeric parameter(s) `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  9. high
    Tool `faction_remove_ally` name implies a side effect that is not declared· faction_remove_allyexcessive agency

    `faction_remove_ally` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  10. high
    Tool `forum_delete_thread` name implies a side effect that is not declared· forum_delete_threadexcessive agency

    `forum_delete_thread` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  11. high
    Tool `place_ship_buy_order` name implies a side effect that is not declared· place_ship_buy_orderexcessive agency

    `place_ship_buy_order` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  12. high
    Tool `place_ship_buy_order` accepts an unbounded monetary / quota value· place_ship_buy_orderexcessive agency

    The numeric parameter(s) `price` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  13. high
    Tool `faction_remove_enemy` name implies a side effect that is not declared· faction_remove_enemyexcessive agency

    `faction_remove_enemy` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  14. high
    Tool `write_note` name implies a side effect that is not declared· write_noteexcessive agency

    `write_note` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  15. high
    Tool `write_note` writes to or deletes from the host filesystem· write_notefilesystem egress

    `write_note` appears to write, create, move, or delete files on the host filesystem (Overwrite an existing note's full content (full REPLACE, not append) (Replaces the entire content of a note you own — the 'content' field overwrites the whole note body. There is no append mode. To grow a note, call read_note first, concatenate locally, and pass the combined text. Requires docking.)). An agent manipulated by an indirect-injection payload can target sensitive paths (SSH keys, shell configs, application secrets) or establish persistence via cron / systemd.

    fix: Restrict the tool to an explicit allow-list of safe directories. Validate all path parameters server-side, reject traversal sequences (`../`), and gate write / delete operations behind a capframe-bind `path starts_with /safe/dir` caveat.

  16. high
    Tool `faction_post_mission` name implies a side effect that is not declared· faction_post_missionexcessive agency

    `faction_post_mission` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  17. high
    Tool `sell` name implies a side effect that is not declared· sellexcessive agency

    `sell` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  18. high
    Tool `sell` accepts an unbounded monetary / quota value· sellexcessive agency

    The numeric parameter(s) `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  19. high
    Tool `cloak` accepts an unbounded monetary / quota value· cloakexcessive agency

    The numeric parameter(s) `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  20. high
    Tool `faction_write_room` name implies a side effect that is not declared· faction_write_roomexcessive agency

    `faction_write_room` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  21. high
    Tool `captains_log_delete` name implies a side effect that is not declared· captains_log_deleteexcessive agency

    `captains_log_delete` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  22. high
    Tool `faction_edit_role` name implies a side effect that is not declared· faction_edit_roleexcessive agency

    `faction_edit_role` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  23. high
    Tool `faction_cancel_mission` name implies a side effect that is not declared· faction_cancel_missionexcessive agency

    `faction_cancel_mission` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  24. high
    Tool `sell_ship_to_order` name implies a side effect that is not declared· sell_ship_to_orderexcessive agency

    `sell_ship_to_order` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  25. high
    Tool `faction_create_role` name implies a side effect that is not declared· faction_create_roleexcessive agency

    `faction_create_role` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  26. high
    Tool `supply_commission` accepts an unbounded monetary / quota value· supply_commissionexcessive agency

    The numeric parameter(s) `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  27. high
    Tool `use_item` accepts an unbounded monetary / quota value· use_itemexcessive agency

    The numeric parameter(s) `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  28. high
    Tool `withdraw_items` accepts an unbounded monetary / quota value· withdraw_itemsexcessive agency

    The numeric parameter(s) `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  29. high
    Tool `facility` accepts an unbounded monetary / quota value· facilityexcessive agency

    The numeric parameter(s) `max_price`, `price`, `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  30. high
    Tool `loot_wreck` accepts an unbounded monetary / quota value· loot_wreckexcessive agency

    The numeric parameter(s) `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  31. high
    Tool `buy_listed_ship` name implies a side effect that is not declared· buy_listed_shipexcessive agency

    `buy_listed_ship` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  32. high
    Tool `list_ship_for_sale` accepts an unbounded monetary / quota value· list_ship_for_saleexcessive agency

    The numeric parameter(s) `price` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  33. high
    Tool `buy` name implies a side effect that is not declared· buyexcessive agency

    `buy` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  34. high
    Tool `buy` accepts an unbounded monetary / quota value· buyexcessive agency

    The numeric parameter(s) `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  35. high
    Tool `refuel` accepts an unbounded monetary / quota value· refuelexcessive agency

    The numeric parameter(s) `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  36. high
    Tool `forum_get_thread` accepts an unbounded monetary / quota value· forum_get_threadexcessive agency

    The numeric parameter(s) `limit` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  37. high
    Tool `cancel_order` name implies a side effect that is not declared· cancel_orderexcessive agency

    `cancel_order` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  38. high
    Tool `station` accepts an unbounded monetary / quota value· stationexcessive agency

    The numeric parameter(s) `fee_percent`, `price` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  39. high
    Tool `craft` accepts an unbounded monetary / quota value· craftexcessive agency

    The numeric parameter(s) `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  40. high
    Tool `forum_delete_reply` name implies a side effect that is not declared· forum_delete_replyexcessive agency

    `forum_delete_reply` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  41. high
    Tool `recycle` accepts an unbounded monetary / quota value· recycleexcessive agency

    The numeric parameter(s) `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  42. high
    Tool `send_gift` name implies a side effect that is not declared· send_giftexcessive agency

    `send_gift` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  43. high
    Tool `send_gift` accepts an unbounded monetary / quota value· send_giftexcessive agency

    The numeric parameter(s) `credits`, `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  44. high
    Tool `buy_insurance` name implies a side effect that is not declared· buy_insuranceexcessive agency

    `buy_insurance` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  45. high
    Tool `create_buy_order` name implies a side effect that is not declared· create_buy_orderexcessive agency

    `create_buy_order` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  46. high
    Tool `create_buy_order` accepts an unbounded monetary / quota value· create_buy_orderexcessive agency

    The numeric parameter(s) `price_each`, `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  47. high
    Tool `modify_order` name implies a side effect that is not declared· modify_orderexcessive agency

    `modify_order` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  48. high
    Tool `modify_order` accepts an unbounded monetary / quota value· modify_orderexcessive agency

    The numeric parameter(s) `new_price` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  49. high
    Tool `cancel_commission` name implies a side effect that is not declared· cancel_commissionexcessive agency

    `cancel_commission` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  50. high
    Tool `browse_ships` accepts an unbounded monetary / quota value· browse_shipsexcessive agency

    The numeric parameter(s) `max_price` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  51. high
    Tool `set_colors` name implies a side effect that is not declared· set_colorsexcessive agency

    `set_colors` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  52. high
    Tool `create_sell_order` name implies a side effect that is not declared· create_sell_orderexcessive agency

    `create_sell_order` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  53. high
    Tool `create_sell_order` accepts an unbounded monetary / quota value· create_sell_orderexcessive agency

    The numeric parameter(s) `price_each`, `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  54. high
    Tool `faction_set_enemy` name implies a side effect that is not declared· faction_set_enemyexcessive agency

    `faction_set_enemy` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  55. high
    Tool `faction_delete_room` name implies a side effect that is not declared· faction_delete_roomexcessive agency

    `faction_delete_room` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  56. high
    Tool `create_note` name implies a side effect that is not declared· create_noteexcessive agency

    `create_note` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  57. high
    Tool `faction_create_buy_order` name implies a side effect that is not declared· faction_create_buy_orderexcessive agency

    `faction_create_buy_order` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  58. high
    Tool `faction_create_buy_order` accepts an unbounded monetary / quota value· faction_create_buy_orderexcessive agency

    The numeric parameter(s) `price_each`, `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  59. high
    Tool `set_drone_name` name implies a side effect that is not declared· set_drone_nameexcessive agency

    `set_drone_name` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  60. high
    Tool `faction_deposit_items` accepts an unbounded monetary / quota value· faction_deposit_itemsexcessive agency

    The numeric parameter(s) `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  61. high
    Tool `jettison` accepts an unbounded monetary / quota value· jettisonexcessive agency

    The numeric parameter(s) `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  62. high
    Tool `faction_prepay_tax` accepts an unbounded monetary / quota value· faction_prepay_taxexcessive agency

    The numeric parameter(s) `amount` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  63. high
    Tool `faction_withdraw_credits` accepts an unbounded monetary / quota value· faction_withdraw_creditsexcessive agency

    The numeric parameter(s) `amount` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  64. high
    Tool `faction_delete_role` name implies a side effect that is not declared· faction_delete_roleexcessive agency

    `faction_delete_role` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  65. high
    Tool `repair` accepts an unbounded monetary / quota value· repairexcessive agency

    The numeric parameter(s) `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  66. high
    Tool `cancel_ship_buy_order` name implies a side effect that is not declared· cancel_ship_buy_orderexcessive agency

    `cancel_ship_buy_order` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  67. high
    Tool `sell_wreck` name implies a side effect that is not declared· sell_wreckexcessive agency

    `sell_wreck` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  68. high
    Tool `faction_edit` name implies a side effect that is not declared· faction_editexcessive agency

    `faction_edit` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  69. high
    Tool `set_home_base` name implies a side effect that is not declared· set_home_baseexcessive agency

    `set_home_base` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  70. high
    Tool `deposit_items` accepts an unbounded monetary / quota value· deposit_itemsexcessive agency

    The numeric parameter(s) `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  71. high
    Tool `view_ship_buy_orders` name implies a side effect that is not declared· view_ship_buy_ordersexcessive agency

    `view_ship_buy_orders` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  72. high
    Tool `forum_create_thread` name implies a side effect that is not declared· forum_create_threadexcessive agency

    `forum_create_thread` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  73. high
    Tool `trade_offer` accepts an unbounded monetary / quota value· trade_offerexcessive agency

    The numeric parameter(s) `offer_credits`, `request_credits` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  74. high
    Tool `faction_create_sell_order` name implies a side effect that is not declared· faction_create_sell_orderexcessive agency

    `faction_create_sell_order` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  75. high
    Tool `faction_create_sell_order` accepts an unbounded monetary / quota value· faction_create_sell_orderexcessive agency

    The numeric parameter(s) `price_each`, `quantity` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  76. high
    Tool `cancel_ship_listing` name implies a side effect that is not declared· cancel_ship_listingexcessive agency

    `cancel_ship_listing` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  77. high
    Tool `create_faction` name implies a side effect that is not declared· create_factionexcessive agency

    `create_faction` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  78. high
    Tool `trade_cancel` name implies a side effect that is not declared· trade_cancelexcessive agency

    `trade_cancel` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  79. high
    Tool `faction_deposit_credits` accepts an unbounded monetary / quota value· faction_deposit_creditsexcessive agency

    The numeric parameter(s) `amount` have a money/quota-shaped name but no `maximum` constraint. An LLM tricked by indirect-injection can call the tool with arbitrarily large values.

    fix: Add a `maximum` (and ideally `minimum`) to each money/quota numeric, OR enforce the cap via a capframe-bind `--limit` caveat at the agent boundary.

  80. high
    Tool `buy_ship_license` name implies a side effect that is not declared· buy_ship_licenseexcessive agency

    `buy_ship_license` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.

    fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).

  81. medium
    Tool `analyze_market` accepts unconstrained string input· analyze_marketunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  82. medium
    Tool `get_insurance_quote` accepts unconstrained string input· get_insurance_quoteunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  83. medium
    Tool `unmute_notifications` accepts unconstrained string input· unmute_notificationsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  84. medium
    Tool `get_cargo` accepts unconstrained string input· get_cargounconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  85. medium
    Tool `view_completed_mission` accepts unconstrained string input· view_completed_missionunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `template_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  86. medium
    Tool `join_faction` accepts unconstrained string input· join_factionunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `faction_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  87. medium
    Tool `claim_insurance` accepts unconstrained string input· claim_insuranceunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  88. medium
    Tool `shipping` accepts unconstrained string input· shippingunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `destination_base_id`, `filter_destination`, `filter_shipper`, `invited_carrier_id`, `package_id`, `recipient_id`, `session_id`, `shipment_id`, `source_bucket_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  89. medium
    Tool `shipping` description mentions money but no `money` side-effect is declared· shippingexcessive agency

    Description: "Quote, post, haul, track, and settle sealed-package freight contracts through station mission services (Action-dispatched freight contracting for sealed packages. facility access: Any operational mission-service facility provides the full station-gated freight system: quote, post, list, accept, pay_debt, and insurance. Mission-service level does not unlock additional freight actions. Faction quote/post, faction acceptance, and faction debt payment additionally require Manage Treasury and an active local Market Runner service (faction_market); at its own station, a faction's active station market supplies that service. Reads and settlement escape paths do not require a Market Runner. quote / post: While docked at a station with an operational mission service, select package_id and a destination_base_id that is a different station; another station in the same system is valid. You set the price: base_reward is the flat reward the carrier is paid on delivery and is required to post; speed_bonus is an optional extra paid for fast delivery, decaying linearly from full at the on-time target tick to zero at the deadline. Carriers choose which contracts to haul by the reward you offer, so a fair market sets the going rate. quote returns estimated_reward — the median base_reward of recently-completed contracts of similar distance — with estimate_samples telling you how much real data backs it (0 = not enough completed contracts yet, so name your own price). shipper defaults to player; faction means your current faction and requires its local Market Runner service plus Manage Treasury. recipient_type + recipient_id may name a player, faction, or station; omit both to deliver back to the shipper. source is cargo (default), storage, or faction; source_bucket_id selects a faction Storage Extension bucket. service_level is standard or priority and sets only the delivery window (priority is tighter); the money is set by base_reward and speed_bonus. visibility is public, faction, allies, or invited. invited listings require invited_carrier_type + invited_carrier_id; invitation controls who can see and accept the listing but does not by itself waive carrier standing or liability limits. insured=true requests dynamic cargo insurance at any mission-service facility; goods without useful completed-fill VWAP may still ship uninsured. On top of the reward the shipper also pays a service_fee (5% of reward + bonus, 25-credit floor) and any insurance premium. quote is informational; post recomputes terms, and max_total_cost can reject an unexpectedly higher total. list / get / track: list is the freight board for the station you are docked at — it shows only posted contracts originating here that the carrier selected by eligible_as=player|faction can actually accept right now (outstanding freight debt, insufficient standing, or a missing faction Market Runner empties the board rather than listing runs you cannot take). Results are sorted by base_reward highest-first by default; set sort=distance to order by fewest route hops or sort=age for oldest-first. Narrow the board with filter_destination (a station id or name), filter_service_level (standard or priority), and filter_shipper (a posting player username, faction name/tag, or station name). page and per_page paginate (per_page max 50). When the board comes back empty the response carries empty_reason_code and empty_reason explaining why — no_shipments (nothing posted here), no_matching_shipments (your filters excluded everything), or no_eligible_shipments (runs exist but you cannot take them, with the blocking reason: unpaid freight debt, insufficient standing, or a missing faction Market Runner). get returns one visible contract. track returns its sampled seal-beacon history so shippers and recipients can follow the route without restricting handoffs, warehouses, or detours. accept / deliver / return / cancel: carrier=player|faction selects who permanently owns the consequences when accepting; it never accepts an arbitrary faction ID. Faction acceptance requires its local Market Runner service plus Manage Treasury. Self-shipping covers the same player/faction actor and either direction of a current player/faction membership relationship. It bypasses standing and tier liability-limit gates, but unpaid freight debt still blocks it; it earns no delivery count, delivered value, priority credit, or tier progress. reputation_eligible freezes that result when accepted so later membership changes cannot alter it. Acceptance deposits the sealed package into the selected carrier's personal or faction storage at the origin, bypassing the ordinary package cap, so it can be withdrawn for hauling later. The prime carrier remains liable through every handoff. failure_debt is the exact debt that carrier will owe if the package is breached or defaulted: 500 credits uninsured, or the insured covered value plus 10% (minimum 100-credit surcharge). deliver deposits the still-sealed package directly into destination storage even if that exceeds the recipient's ordinary package cap. return is always available to surrender freight back to the origin station. Opening the seal or missing the deadline breaches/defaults the contract, forfeits payment, damages the global carrier record, creates the displayed freight debt, and blocks new acceptances until paid. cancel applies only while still posted. profile / pay_debt: view the selected player/faction's separate global freight-carrier record, tier history and next-tier requirements, active contracts, current liability usage, per-package/aggregate limits, remaining allowance, and outstanding freight debts. Contract count itself is uncapped; acceptance capacity is liability-based. pay_debt repays the requested amount, or the full balance when amount is omitted. Paying faction debt requires its local Market Runner service plus Manage Treasury. Outstanding debt blocks new acceptances; repayment does not erase breach/default history.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  90. medium
    Tool `set_status` accepts unconstrained string input· set_statusunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  91. medium
    Tool `get_tax_estimate` accepts unconstrained string input· get_tax_estimateunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  92. medium
    Tool `get_tax_estimate` description mentions money but no `money` side-effect is declared· get_tax_estimateexcessive agency

    Description: "Preview what taxes you'd owe right now (Returns the income-tax assessment you would face if the weekly cycle ran this instant (taxable income accrued since your last assessment, per-empire breakdown with foreign-tax deductions, total owed), the property-tax assessment against your assessed_property_value (hull + fitted modules across every ship you own, computed via the same CalculateFittedShipValue helper used by insurance and salvage; bills the full rate per citizenship empire independently with no mutual-deduction credits), and the current sales-tax rate every empire would charge you at buy time. The taxable_income_by_source array splits your pending taxable income across the five activity categories that count: mission (mission rewards including distress completions), market (selling goods to NPCs or via exchange order fills), salvage (selling salvaged wrecks), ship_sale (selling a ship to any buyer), rescue (rescue payouts). The assessed_property_by_ship array shows each owned ship's contribution to the total assessed value. Gifts, refunds, insurance payouts, and treasury subsidies are not taxable and do not appear. When an empire publishes a progressive schedule (income or property), its row carries a brackets array showing the marginal rate, your income/value, and the tax produced for each bracket. last_property_assessed_at is stamped at the end of every weekly property cycle even when zero owed. All rate_bps fields are basis points: 100 = 1%, 10000 = 100%. Pure read — no escrow, no notifications.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  93. medium
    Tool `delete_note` accepts unconstrained string input· delete_noteunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `note_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  94. medium
    Tool `help` accepts unconstrained string input· helpunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `topic`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  95. medium
    Tool `view_orders` accepts unconstrained string input· view_ordersunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `item_id`, `search`, `session_id`, `station_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  96. medium
    Tool `view_orders` description mentions money but no `money` side-effect is declared· view_ordersexcessive agency

    Description: "View your own orders at a station (Shows your active buy and sell orders at a station, including fill progress. Provide station_id to view without being docked; omit to use your current docked station. Supports pagination, filtering, and sorting. Options: scope ('personal' or 'faction', default 'personal'), page (default 1), page_size (default 20, max 50), order_type ('buy' or 'sell'), item_id (exact match on item name or ID), search (substring match on item names), sort_by ('newest', 'oldest', 'price_asc', 'price_desc', default 'newest').)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  97. medium
    Tool `estimate_purchase` accepts unconstrained string input· estimate_purchaseunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `item_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  98. medium
    Tool `estimate_purchase` description mentions money but no `money` side-effect is declared· estimate_purchaseexcessive agency

    Description: "Preview what buying would cost without executing (Read-only. Shows available quantity, total cost, and price breakdown across sellers. Accepts item_id or item name (e.g. 'Iron Ore').)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  99. medium
    Tool `logout` accepts unconstrained string input· logoutunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  100. medium
    Tool `prepay_tax` accepts unconstrained string input· prepay_taxunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  101. medium
    Tool `prepay_tax` description mentions money but no `money` side-effect is declared· prepay_taxexcessive agency

    Description: "Prepay credits toward your next tax assessment (Moves credits from your wallet into a tax-prepayment pool. On tax day the pool covers your combined income- and property-tax assessment before your wallet is touched, so you can't be caught short and incriminated for tax delinquency. Any surplus left after the cycle is refunded to your wallet alongside the weekly tax return. Use get_tax_estimate to see your current obligation and prepaid balance (tax_prepaid). amount must be a positive number of credits and is escrowed, not spent — it is not taxable and not counted toward lifetime spending.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  102. medium
    Tool `distress_signal` accepts unconstrained string input· distress_signalunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  103. medium
    Tool `captains_log_list` accepts unconstrained string input· captains_log_listunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  104. medium
    Tool `scrap_wreck` accepts unconstrained string input· scrap_wreckunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  105. medium
    Tool `get_skills` accepts unconstrained string input· get_skillsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  106. medium
    Tool `faction_withdraw_items` accepts unconstrained string input· faction_withdraw_itemsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `item_id`, `session_id`, `target`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  107. medium
    Tool `claim` accepts unconstrained string input· claimunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `registration_code`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  108. medium
    Tool `faction_remove_ally` accepts unconstrained string input· faction_remove_allyunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `target_faction_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  109. medium
    Tool `faction_propose_peace` accepts unconstrained string input· faction_propose_peaceunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `target_faction_id`, `terms`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  110. medium
    Tool `forum_delete_thread` accepts unconstrained string input· forum_delete_threadunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `thread_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  111. medium
    Tool `faction_accept_ally` accepts unconstrained string input· faction_accept_allyunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `target_faction_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  112. medium
    Tool `forum_list` accepts unconstrained string input· forum_listunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `author`, `date_from`, `date_to`, `faction_tag`, `search`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  113. medium
    Tool `faction_list_missions` accepts unconstrained string input· faction_list_missionsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  114. medium
    Tool `place_ship_buy_order` accepts unconstrained string input· place_ship_buy_orderunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `class_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  115. medium
    Tool `place_ship_buy_order` description mentions money but no `money` side-effect is declared· place_ship_buy_orderexcessive agency

    Description: "Place a standing buy order for a ship class at this base (Escrows your offered price plus sales tax. The order fills when another player sells a matching ship into it (sell_ship_to_order), or when the station shipyard decides your offer covers its build costs with margin and builds one for you — the finished ship is delivered docked at this base. Requires a base with a shipyard. One open order per ship class per base. Cancel anytime with cancel_ship_buy_order for a full refund. If a listing already exists at or below your offer, you'll be pointed at buy_listed_ship instead.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  116. medium
    Tool `faction_remove_enemy` accepts unconstrained string input· faction_remove_enemyunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `target_faction_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  117. medium
    Tool `get_ship` accepts unconstrained string input· get_shipunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  118. medium
    Tool `write_note` accepts unconstrained string input· write_noteunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `note_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  119. medium
    Tool `view_market` accepts unconstrained string input· view_marketunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `category`, `item_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  120. medium
    Tool `view_market` description mentions money but no `money` side-effect is declared· view_marketexcessive agency

    Description: "View the market at the current station (Without item_id: returns a compact summary (best prices, quantities) for all items — use category to filter (e.g. 'ore', 'commodity', 'module'). With item_id: returns full order book depth for that item. Accepts item_id or item name (e.g. 'Iron Ore'). Every response includes current_tick. Pass that value back as 'since' on a later call to poll for changes: the response then lists only items whose book changed since that tick (incremental:true), with emptied items shown carrying no orders. This is a stateless alternative to subscribe_market — no persistent connection needed. Re-baseline (call without 'since') after changing stations or if you get a 'stale_cursor' error. Fuel and contraband are excluded from incremental diffs. Set company_store:true to see ONLY your faction's private Company Store listings here (members-only buy/sell orders); these are hidden from non-members and excluded from the normal view.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  121. medium
    Tool `faction_query_intel` accepts unconstrained string input· faction_query_intelunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `poi_type`, `resource_type`, `session_id`, `source_faction_id`, `system_id`, `system_name`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  122. medium
    Tool `recall_drone` accepts unconstrained string input· recall_droneunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `drone_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  123. medium
    Tool `find_route` accepts unconstrained string input· find_routeunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `target_system`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  124. medium
    Tool `get_active_missions` accepts unconstrained string input· get_active_missionsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  125. medium
    Tool `load_drone` accepts unconstrained string input· load_droneunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `item_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  126. medium
    Tool `faction_visit_room` accepts unconstrained string input· faction_visit_roomunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `room_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  127. medium
    Tool `faction_post_mission` accepts unconstrained string input· faction_post_missionunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `description`, `giver_name`, `giver_title`, `session_id`, `title`, `type`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  128. medium
    Tool `trade_decline` accepts unconstrained string input· trade_declineunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `trade_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  129. medium
    Tool `register` accepts unconstrained string input· registerunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `registration_code`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  130. medium
    Tool `sell` accepts unconstrained string input· sellunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `item_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  131. medium
    Tool `get_faction_achievements` accepts unconstrained string input· get_faction_achievementsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  132. medium
    Tool `login` accepts unconstrained string input· loginunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `password`, `username`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  133. medium
    Tool `cloak` accepts unconstrained string input· cloakunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  134. medium
    Tool `faction_get_invites` accepts unconstrained string input· faction_get_invitesunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  135. medium
    Tool `get_system` accepts unconstrained string input· get_systemunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  136. medium
    Tool `view_storage` accepts unconstrained string input· view_storageunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `station_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  137. medium
    Tool `faction_write_room` accepts unconstrained string input· faction_write_roomunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `description`, `name`, `room_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  138. medium
    Tool `faction_write_room` fetches external web content -- indirect-injection surface· faction_write_roomindirect injection

    Description: "Create or update a room in your faction's common space — this is your chance to worldbuild (This is your faction's creative canvas. Write immersive descriptions that bring your rooms to life — what does the space look like, sound like, smell like? What's on the walls? What's the atmosphere? Show the personality of your faction through the spaces you build. Other players will visit these rooms and experience the world you've created. Description up to 4000 characters. Access: public (anyone docked), members (faction only), officers (leadership only). Requires `manage_facilities` permission. Omit room_id to create new; include room_id to update existing.)" -- this tool pulls externally-controlled content into the agent's context window, the canonical indirect-injection vector. Even when the user supplies the URL, content at that URL can carry hostile instructions.

    fix: Sandbox the fetched content: strip prompts before forwarding to the model, constrain to an allow-list of domains, and route through capframe-guard with a `domain in [...]` caveat.

  139. medium
    Tool `captains_log_delete` accepts unconstrained string input· captains_log_deleteunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  140. medium
    Tool `release_tow` accepts unconstrained string input· release_towunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  141. medium
    Tool `get_trades` accepts unconstrained string input· get_tradesunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  142. medium
    Tool `faction_accept_invite` accepts unconstrained string input· faction_accept_inviteunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `faction_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  143. medium
    Tool `faction_edit_role` accepts unconstrained string input· faction_edit_roleunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `name`, `role_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  144. medium
    Tool `faction_cancel_mission` accepts unconstrained string input· faction_cancel_missionunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `template_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  145. medium
    Tool `faction_cancel_mission` description mentions money but no `money` side-effect is declared· faction_cancel_missionexcessive agency

    Description: "Cancel a posted faction mission and refund escrowed rewards (Cancels the mission and returns escrowed credits and items to faction storage. Cannot cancel if a player is actively working on it. Requires `manage_treasury` permission.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  146. medium
    Tool `sell_ship_to_order` accepts unconstrained string input· sell_ship_to_orderunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `order_id`, `session_id`, `ship_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  147. medium
    Tool `sell_ship_to_order` description mentions money but no `money` side-effect is declared· sell_ship_to_orderexcessive agency

    Description: "Sell a stored ship directly into a buy order at this base (Instantly sells a ship stored at this base into a matching buy order (see buy_orders in browse_ships). You are paid the order price immediately — no listing fee. The ship class must match the order exactly. Cannot sell your active ship, a listed ship, or one with passengers or ships in its carrier bays.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  148. medium
    Tool `build_base` accepts unconstrained string input· build_baseunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  149. medium
    Tool `list_station_passengers` accepts unconstrained string input· list_station_passengersunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  150. medium
    Tool `list_station_passengers` description mentions money but no `money` side-effect is declared· list_station_passengersexcessive agency

    Description: "List citizens waiting for transport at your current station (You must be docked. Shows each waiting citizen's name, accommodation class, citizenship, where they want to go (destination station and system), and an estimated base fare for carrying them there — use this to decide which destinations to load with 'load_passenger'. Also reports the station's passenger market conditions: fare_surge (0.6x–2.0x) rises where passengers have waited a long time for pickup and falls where service is prompt, demand_level summarizes it, and market_conditions explains why. Underserved stations pay premium fares; well-served stations pay less but generate more travelers over time. If your faction has a Transit Lounge here, a transit_lounge section lists the connecting passengers laid over in it (with their live fares and remaining deadline ticks) ready to board an onward leg.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  151. medium
    Tool `faction_create_role` accepts unconstrained string input· faction_create_roleunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `name`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  152. medium
    Tool `read_note` accepts unconstrained string input· read_noteunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `note_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  153. medium
    Tool `unload_drone` accepts unconstrained string input· unload_droneunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `drone_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  154. medium
    Tool `get_missions` accepts unconstrained string input· get_missionsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  155. medium
    Tool `espionage` accepts unconstrained string input· espionageunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  156. medium
    Tool `espionage` description mentions money but no `money` side-effect is declared· espionageexcessive agency

    Description: "Send a spy to gather intelligence on the station you're docked at, using your faction's Espionage HQ (Requires faction membership, an active Espionage HQ facility built anywhere by your faction, and being docked at the target station. Takes about 80 seconds; no other actions can be taken until it resolves. Returns a short narrative account of the operation, not structured data — sometimes it turns up real intelligence about recent activity at the station (ship orders, facility construction, large purchases), sometimes it turns up nothing, and sometimes your spy is spotted and has to escape empty-handed.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  157. medium
    Tool `supply_commission` accepts unconstrained string input· supply_commissionunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `commission_id`, `item_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  158. medium
    Tool `supply_commission` description mentions money but no `money` side-effect is declared· supply_commissionexcessive agency

    Description: "Donate materials directly to a credits-only commission that is stuck sourcing (Supplies one material type to a commission in sourcing state. Items are taken from your cargo first, then station storage. No credit refund is issued for donated materials. If donating completes all sourcing, the commission immediately advances to pending and any unused earmarked credits are refunded to you.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  159. medium
    Tool `use_item` accepts unconstrained string input· use_itemunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `item_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  160. medium
    Tool `abandon_mission` accepts unconstrained string input· abandon_missionunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `mission_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  161. medium
    Tool `abandon_mission` description mentions money but no `money` side-effect is declared· abandon_missionexcessive agency

    Description: "Abandon an active mission (Removes the mission from your active list. Most mission cargo stays in your hold, but goods a mission provided on accept (e.g. smuggling courier contraband) are reclaimed: held units are confiscated and the base value of any you no longer carry is charged, so only delivery pays out.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  162. medium
    Tool `dock` accepts unconstrained string input· dockunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  163. medium
    Tool `get_wrecks` accepts unconstrained string input· get_wrecksunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  164. medium
    Tool `get_battle_summary` accepts unconstrained string input· get_battle_summaryunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `battle_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  165. medium
    Tool `withdraw_items` accepts unconstrained string input· withdraw_itemsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `item_id`, `session_id`, `target`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  166. medium
    Tool `view_faction_storage` accepts unconstrained string input· view_faction_storageunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `station_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  167. medium
    Tool `view_faction_storage` description mentions money but no `money` side-effect is declared· view_faction_storageexcessive agency

    Description: "View your faction's shared storage at a station (Shows the faction's global treasury balance, items at the station, and recent activity. Must be in a faction. Provide station_id to view without being docked; omit to use your current docked station (must have storage service).)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  168. medium
    Tool `undock` accepts unconstrained string input· undockunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  169. medium
    Tool `leave_faction` accepts unconstrained string input· leave_factionunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  170. medium
    Tool `get_notes` accepts unconstrained string input· get_notesunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  171. medium
    Tool `facility` accepts unconstrained string input· facilityunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `bucket`, `custom_name`, `deliver_to`, `description`, `facility_id`, `facility_type`, `job_id`, `listing_id`, `name`, `package_id`, `player_id`, `recipe_id`, `session_id`, `source`, `species`, `target`, `username`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  172. medium
    Tool `facility` description mentions money but no `money` side-effect is declared· facilityexcessive agency

    Description: "Manage facilities at stations (production, faction, personal, sales, and more) (Actions: types, build, list, owned, upgrades, upgrade, dismantle, repair, faction_build, faction_dismantle, faction_upgrade, faction_list, faction_owned, transfer, personal_build, personal_decorate, personal_visit, list_for_sale, browse_for_sale, buy_listing, cancel_listing, job_add, job_list, job_cancel, job_reorder, set_output_price, set_access, set_name, set_description, ranch_status, ranch_set_cull. Call with no action or action 'help' for full documentation. WILDLIFE RANCH: build a ranch on your faction's outpost at a habitat POI (faction_build, facility_type=wildlife_corral, species=<grazer species id>; needs Xenobiology and a live wild population — survey_system shows what lives where). Keep faction storage at the outpost stocked with the workers' supplies and the species' diet resource: the local wildlife domesticates into your branded herd, breeds, and yields diet secretions plus a managed cull (ranch_set_cull with cull_target) into faction storage each cycle. Mining the anchor POI's diet nodes shrinks your own range. Branded animals remain huntable by anyone — you are notified who shot them. DISMANTLE: 'dismantle' (facility_id) packages 100% of every build material across the facility's full upgrade chain after the cumulative build time, one package group per tier; 'faction_dismantle' does the same for faction facilities (needs ManageFacilities). Costs one cargo_container per package produced. The facility goes offline immediately and is removed when done. Move and unpack the resulting packages normally, OR pass their package_ids straight to 'build'/'upgrade'/'faction_build'/'faction_upgrade' to source materials directly from them — each package must contain exactly what that action still needs of an item (no more) or it's rejected up front. Credits are not refunded, and the normal credit/skill requirements still apply. Foundational facilities (Personal Quarters and Faction Storage) cannot be dismantled. Damaged or repairing facilities must be repaired first. FACTION SHIP GARAGE: build a faction_ship_garage (faction_build; holds 20 ships, upgrades to faction_ship_hangar=50 then faction_fleet_yard=100) to give your faction a shared fleet pool at a station. Gift a ship to your faction to store it; switch_ship to a pooled ship while docked there to claim it; list_ships shows the garage at your current station. REPAIR: 'repair' (facility_id) restores a facility damaged when its station was wrecked, costing 30% of its original build materials and 30% of its build time. Use 'owned' and 'faction_owned' for cross-station facility and rent views. Production jobs use job_add/job_list/job_cancel/job_reorder; set_access and set_output_price control rentals; set_name and set_description customize owned facilities. PACKAGE JOBS: job_add also runs pack_package with items, label, source, and target, or unpack_package with package_id, source, and target. Logistics rental pricing is per-operation for package jobs rather than per produced item.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  173. medium
    Tool `catalog` accepts unconstrained string input· catalogunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `category`, `class`, `empire`, `id`, `search`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  174. medium
    Tool `loot_wreck` accepts unconstrained string input· loot_wreckunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `item_id`, `module_id`, `session_id`, `wreck_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  175. medium
    Tool `faction_promote` accepts unconstrained string input· faction_promoteunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `player_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  176. medium
    Tool `faction_promote` description mentions money but no `money` side-effect is declared· faction_promoteexcessive agency

    Description: "Promote or demote a faction member (player_id accepts a player ID or username. Leader can change any member's role. Members with Promote permission can assign roles below their own priority. Only the leader can transfer leadership (role_id=leader). Roles: recruit, member, officer, leader.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  177. medium
    Tool `captains_log_get` accepts unconstrained string input· captains_log_getunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  178. medium
    Tool `buy_listed_ship` accepts unconstrained string input· buy_listed_shipunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `listing_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  179. medium
    Tool `buy_listed_ship` description mentions money but no `money` side-effect is declared· buy_listed_shipexcessive agency

    Description: "Purchase a ship from the exchange (Buy a ship from the exchange. Must be docked at the same base. Your current ship is stored at the base and the purchased ship becomes your active ship. Credits go directly to the seller.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  180. medium
    Tool `tow_wreck` accepts unconstrained string input· tow_wreckunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `wreck_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  181. medium
    Tool `captains_log_add` accepts unconstrained string input· captains_log_addunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  182. medium
    Tool `faction_submit_trade_intel` accepts unconstrained string input· faction_submit_trade_intelunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  183. medium
    Tool `list_ship_for_sale` accepts unconstrained string input· list_ship_for_saleunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `ship_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  184. medium
    Tool `list_ship_for_sale` description mentions money but no `money` side-effect is declared· list_ship_for_saleexcessive agency

    Description: "List a stored ship for sale on the exchange (List a ship stored at this base for other players to buy. Charges a 1% listing fee (non-refundable). Cannot list your active ship.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  185. medium
    Tool `travel` accepts unconstrained string input· travelunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `target_poi`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  186. medium
    Tool `chat` accepts unconstrained string input· chatunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `target_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  187. medium
    Tool `faction_kick` accepts unconstrained string input· faction_kickunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `player_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  188. medium
    Tool `faction_garages` accepts unconstrained string input· faction_garagesunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  189. medium
    Tool `faction_accept_peace` accepts unconstrained string input· faction_accept_peaceunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `target_faction_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  190. medium
    Tool `inspect` accepts unconstrained string input· inspectunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  191. medium
    Tool `name_ship` accepts unconstrained string input· name_shipunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `name`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  192. medium
    Tool `buy` accepts unconstrained string input· buyunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `item_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  193. medium
    Tool `buy` description mentions money but no `money` side-effect is declared· buyexcessive agency

    Description: "Buy items at market price from the station exchange (No fees for instant fills. Items delivered to cargo (or storage if cargo full). Use deliver_to=storage to send directly to storage. Use auto_list=true to automatically place a buy order for any unfilled quantity (listing fee applies — 1% default, higher at pirate strongholds and stations with a custom market fee). Accepts item_id or item name (e.g. 'Iron Ore').)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  194. medium
    Tool `refuel` accepts unconstrained string input· refuelunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `item_id`, `session_id`, `target`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  195. medium
    Tool `refuel` description mentions money but no `money` side-effect is declared· refuelexcessive agency

    Description: "Refuel your ship or transfer fuel to another ship (Four modes: (1) target=fleet shows fleet fuel status (all members' fuel levels and fuel/jump). (2) target=<player> transfers fuel to target ship at same POI (requires Refueling Pump module). (3) Docked at refuel station → station refueling: draws free fuel from your faction's bunker (then allied bunkers) first, then charges 2-20 credits/fuel based on the station's reserve level, plus any empire fuel tax (player-owned stations may set their own flat price). (4) Otherwise → fuel cells from cargo. Auto-selects cheapest fuel cell unless item_id specified. Station refueling always fills the tank to full — it ignores quantity and charges only for the fuel needed to top off (cost = your remaining tank capacity). quantity applies only to fuel-cell purchases and ship-to-ship transfers: it sets how many cells to burn or units to transfer (default 1). Fuel cells can be cracked open mid-flight — useful for recovering from a Pathfinder Drive miscalculation.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  196. medium
    Tool `faction_decline_invite` accepts unconstrained string input· faction_decline_inviteunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `faction_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  197. medium
    Tool `forum_get_thread` accepts unconstrained string input· forum_get_threadunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `thread_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  198. medium
    Tool `get_guide` accepts unconstrained string input· get_guideunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  199. medium
    Tool `cancel_order` accepts unconstrained string input· cancel_orderunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `order_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  200. medium
    Tool `cancel_order` description mentions money but no `money` side-effect is declared· cancel_orderexcessive agency

    Description: "Cancel an active order and return escrow (Sell orders: remaining items returned to station storage. Buy orders: remaining credits returned to wallet. Partially filled orders keep their fills. Use order_id 'all' or '*' to cancel all your orders at this station. Bulk mode: pass 'order_ids' array to cancel up to 50 orders in one call.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  201. medium
    Tool `station` accepts unconstrained string input· stationunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `description`, `faction`, `name`, `player`, `service`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  202. medium
    Tool `station` description mentions money but no `money` side-effect is declared· stationexcessive agency

    Description: "Administer one of your faction's stations or outposts: rename, access control, and build policy (Must be docked at a station or outpost your faction owns. Action 'info' (any member) shows the current configuration; all other actions need the ManageBases permission. Outposts support only 'info', 'set_name', and 'set_description' (they have no services and are members-only by design); the remaining actions are station-only. Actions: set_name (name), set_description (description, max 500 chars), set_public (public: true/false — when false only the owning faction, allowed factions, and allowed players may dock), set_build_policy (allow_outsiders: true/false — whether non-members may build their own facilities here), set_service_access (service=market|refuel|repair|shipyard|crafting|salvage_yard|missions + access=public|allies|faction — gate an individual service to the owning faction and optionally allies), set_market_fee (fee_percent 0-10 — listing fee outside traders pay, to your treasury), set_refuel_price (price per fuel unit) and set_repair_price (price per hull point — outside-pilot charges that flow to your treasury), set_auto_buy_fuel (auto_buy_fuel: true/false — off by default; when on, any docked pilot can sell fuel from their ship's tank into your shared tank at live scarcity-based prices, paid from your faction's treasury, capped to what it can afford), allow_player/remove_player/ban/unban (player: id or username), allow_faction/remove_faction (faction: id). Banning a player also drops them from the allow list and immediately blocks docking.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  203. medium
    Tool `craft` accepts unconstrained string input· craftunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `deliver_to`, `facility_id`, `job_id`, `package_id`, `recipe_id`, `session_id`, `source`, `target`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  204. medium
    Tool `craft` description mentions money but no `money` side-effect is declared· craftexcessive agency

    Description: "Queue a crafting job (auto-routes to your own/faction facility, or hand-crafts at the Station Workshop) (Must be docked. Ordinary recipes require crafting and storage service; package recipes use the rules described below. Crafting is no longer instant: it queues a job that runs over subsequent ticks (check progress with craft action=queue). You do NOT need to poll: each tick a job deposits finished output you get a 'crafting_update' notification (category 'crafting' in get_notifications) naming exactly what was made and where, with runs_remaining and a completed flag — so re-issuing the same craft because 'nothing happened yet' only stacks a duplicate job. 'quantity' is the number of OUTPUT ITEMS you want, rounded up to a whole number of production runs (a recipe that yields several items per run may make a few extra). Materials are escrowed from your station storage at enqueue (NOT cargo) and outputs are delivered to station storage on completion — deposit your inputs to storage first. Auto-routing prefers your OWN facility, then your FACTION's, then one an ALLIED faction has granted you access to (free to you, but queued at external priority), then a public rental, and only hand-crafts at the Station Workshop (speed scales with crafting/refining skill) when none is available — pass preset "workshop" to force hand-crafting, or facility_id to target one, plus optional preset "fast" (soonest finish globally, so a busy own facility may route to an idle public rental), "cheap" (lowest fee you would actually pay — your own and your faction's facilities are free to you, so they always win), or "prefer_own" (keep the job on your own/faction/ally-granted facility, renting a public one only when you have none that can run it). The Station Workshop is hand-crafting (your own labor, not the station's facility): its jobs advance only while you stay docked at that base and pause if you undock, resuming when you return — whereas a job at a real production facility you own or rent keeps running while you're away. deliver_to=faction crafts from/to faction storage (needs manage treasury permission), and deliver_to=faction:<bucket name or id> pulls inputs from and deposits outputs into a specific faction Storage Extension bucket; and if you leave deliver_to off and your own storage/credits can't cover the job, it automatically draws from your faction's storage/treasury when you're allowed to spend them. Renting another player's public facility prepays a per-run fee. COST CHECK: add dry_run=true to get a quote — the materials, labor, and rental fee the job would cost, the venue it auto-routes to, whether you can afford it, and the ETA — without queuing or spending anything (not supported with bulk jobs). Use 'recycle' to reverse a recipe at a recycler. BULK: pass jobs=[{recipe_id, quantity, facility_id?, preset?, deliver_to?, source?}, ...] to queue many crafts in one action (up to 50 facilities at once instead of one job per tick) — each entry is queued independently and the response reports per-job success/failure. QUEUE & CANCEL: call craft with no recipe (action=queue) to list your queued jobs and their IDs; pass job_id=<id> to cancel a queued job and refund its unconsumed inputs, labor, and fees (the same operation as facility action=job_cancel). Pass job_ids=[id1,id2,...] to cancel several at once (per-job success/failure). PACKAGE RECIPES: recipe_id=pack_package takes items, label, source, and target; it consumes one cargo_container, packs at most 100 total item size, and requires Logistics. recipe_id=unpack_package takes package_id, source, and target; A Logistics facility is fast, returns the container, and uses that facility's normal access/rental rules without requiring the station's generic crafting service. preset="workshop" is much slower, consumes the container, and requires the station's crafting service. source/target accept storage, cargo, faction, or faction:<bucket>; target defaults to source (deliver_to is an alias). Package jobs use this same queue and job_id cancellation.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  205. medium
    Tool `forum_delete_reply` accepts unconstrained string input· forum_delete_replyunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `reply_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  206. medium
    Tool `list_passengers` accepts unconstrained string input· list_passengersunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  207. medium
    Tool `list_passengers` description mentions money but no `money` side-effect is declared· list_passengersexcessive agency

    Description: "List the passengers currently aboard your ship (Shows each passenger's destination station and system, accommodation class, base fare due on delivery, the speed bonus they would pay if delivered right now (it decays as the guarantee window runs down), and the ticks remaining before their fare guarantee expires. Also reports your ship's passenger berths as berths: {"economy": {"total": N, "free": N}, "business": {...}, "first": {...}} — free counts what load_passenger can still fill, remembering that a passenger seated in a higher-class berth occupies that class. Omitted entirely if your ship has no berths.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  208. medium
    Tool `recycle` accepts unconstrained string input· recycleunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `deliver_to`, `facility_id`, `job_id`, `recipe_id`, `session_id`, `source`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  209. medium
    Tool `recycle` description mentions money but no `money` side-effect is declared· recycleexcessive agency

    Description: "Queue a recycling job: consume a recipe's outputs to recover a fraction of its inputs (Must be docked at a base with a recycler facility (auto-routed to your own, then your faction's, then one an ALLIED faction has granted you access to (free to you, but queued at external priority); or pass facility_id, plus optional preset "fast" to pick the soonest-finishing recycler globally, "cheap" to pick the lowest fee you would actually pay (your own and your faction's recyclers are free to you, so they always win), or "prefer_own" to keep the job on your own/faction/ally-granted recycler; "workshop" doesn't apply — recycling always needs a real recycler facility). 'quantity' is the number of the recipe's output items to feed in and break down, rounded up to whole recycling runs. Escrows those OUTPUT items from your station storage and returns a lossy fraction of its inputs over subsequent ticks (you get a 'crafting_update' notification each tick recovered inputs land in storage). Recycling is always a net loss by design. Use deliver_to=faction for faction storage. COST CHECK: add dry_run=true for a quote (feedstock consumed, fees, venue, ETA) without queuing anything (not supported with bulk jobs). BULK: pass jobs=[{recipe_id, quantity, facility_id?, preset?, deliver_to?, source?}, ...] to recycle many recipes in one action (up to 50) — each entry is processed independently with per-job success/failure. CANCEL: pass job_id=<id> to cancel a queued job and refund its unconsumed feedstock and fees. Pass job_ids=[...] to cancel several at once.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  210. medium
    Tool `send_gift` accepts unconstrained string input· send_giftunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `item_id`, `recipient`, `session_id`, `ship_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  211. medium
    Tool `send_gift` description mentions money but no `money` side-effect is declared· send_giftexcessive agency

    Description: "Send items, credits, or a ship to another player or to an empire at this station (recipient accepts a player username/ID, an empire alias ('solarian', 'voidborn', 'crimson', 'nebula', 'outerrim' — also accepts long names like 'Solarian Confederacy' or 'empire:crimson'), or 'faction:TAG' for another faction. Provide item_id+quantity to gift items from cargo, credits to gift from wallet, or ship_id to transfer a ship — these are mutually exclusive (one per call). For item gifts to a player, set source="storage" to pull the items straight from your personal station storage instead of cargo (default "cargo"), skipping the withdraw-to-cargo round-trip — same source param as deposit_items. Gifting a ship works remotely: the ship can be parked at any station and you don't need to be docked or travel to it (you can even send it mid-flight) — it just must not be your active ship. The transferred ship stays parked where it is and the recipient finds it (and your pink-slip note) at that station. Gifting items or credits still requires you to be docked at a base with storage service. Empire donations require docking at one of that empire's stations; credits go to the empire treasury, materials to the empire's quartermaster, and ships into the empire's donated fleet. Each empire donation files an automated, system-authored petition confirming the donation. For player gifts, the recipient does NOT need to be online — async delivery shows on their next storage view.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  212. medium
    Tool `faction_scan_poi` accepts unconstrained string input· faction_scan_poiunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `poi_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  213. medium
    Tool `refit_ship` accepts unconstrained string input· refit_shipunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  214. medium
    Tool `refit_ship` description mentions money but no `money` side-effect is declared· refit_shipexcessive agency

    Description: "Refit your active ship to its latest class specifications (Resets your ship to the current class definition: hull stats are reset and the class's current default loadout is installed. Use this to pick up a balance pass — either a hull-stat rebalance or a change to the class's canonical default loadout (its standard-issue fit). You get the new stats plus the current default fit. All installed modules are returned to station storage (so a customized fit is recoverable). All cargo is moved to station storage. Free of charge. Irreversible. Requires a shipyard. Returns already_current if your ship already matches the current class stats and default-loadout version (nothing to apply). Offered to every ship of a re-specced class, including ones you customized — your old modules come back to storage, so refit and re-fit if you prefer your own setup.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  215. medium
    Tool `buy_insurance` accepts unconstrained string input· buy_insuranceunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  216. medium
    Tool `buy_insurance` description mentions money but no `money` side-effect is declared· buy_insuranceexcessive agency

    Description: "Purchase ship insurance (Purchases insurance at your current risk-based rate. Coverage equals fitted ship value (hull + modules). Premium paid to the station insurer. Use get_insurance_quote first to see your rate.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  217. medium
    Tool `get_poi` accepts unconstrained string input· get_poiunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  218. medium
    Tool `get_base` accepts unconstrained string input· get_baseunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  219. medium
    Tool `complete_mission` accepts unconstrained string input· complete_missionunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `mission_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  220. medium
    Tool `create_buy_order` accepts unconstrained string input· create_buy_orderunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `item_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  221. medium
    Tool `create_buy_order` description mentions money but no `money` side-effect is declared· create_buy_orderexcessive agency

    Description: "Place a buy offer on the station exchange (Listing fee on the portion that goes on the order book (1% default; pirate strongholds and stations with a custom market fee charge more). Instant fills incur no fee. Items from instant fills delivered to cargo by default (use deliver_to=storage for storage). Accepts item_id or item name (e.g. 'Iron Ore'). Bulk mode: pass 'orders' array of {item_id, quantity, price_each} to create up to 50 orders in one call. If you already have an order for the same item at the same price, the new quantity is added to your existing order instead of creating a duplicate (response includes consolidated=true and the existing order_id).)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  222. medium
    Tool `modify_order` accepts unconstrained string input· modify_orderunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `order_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  223. medium
    Tool `modify_order` description mentions money but no `money` side-effect is declared· modify_orderexcessive agency

    Description: "Change the price on an existing order (Updates the price and re-sorts in the order book. Buy order price changes adjust escrow (increase costs more, decrease refunds difference). Bulk mode: pass 'orders' array of {order_id, new_price} to modify up to 50 orders in one call.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  224. medium
    Tool `get_notification_settings` accepts unconstrained string input· get_notification_settingsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  225. medium
    Tool `commission_status` accepts unconstrained string input· commission_statusunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `base_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  226. medium
    Tool `cancel_commission` accepts unconstrained string input· cancel_commissionunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `commission_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  227. medium
    Tool `cancel_commission` description mentions money but no `money` side-effect is declared· cancel_commissionexcessive agency

    Description: "Cancel a pending or in-progress ship commission (Cancel a commission that hasn't finished yet. You receive a 50% refund. If you provided materials, they are returned to station storage.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  228. medium
    Tool `browse_ships` accepts unconstrained string input· browse_shipsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `base_id`, `class_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  229. medium
    Tool `build_outpost` accepts unconstrained string input· build_outpostunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  230. medium
    Tool `fleet` accepts unconstrained string input· fleetunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `player_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  231. medium
    Tool `list_ships` accepts unconstrained string input· list_shipsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  232. medium
    Tool `subscribe_observation` accepts unconstrained string input· subscribe_observationunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  233. medium
    Tool `faction_intel_status` accepts unconstrained string input· faction_intel_statusunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  234. medium
    Tool `faction_withdraw_invite` accepts unconstrained string input· faction_withdraw_inviteunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `player_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  235. medium
    Tool `set_colors` accepts unconstrained string input· set_colorsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `text`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  236. medium
    Tool `get_drone` accepts unconstrained string input· get_droneunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `drone_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  237. medium
    Tool `accept_mission` accepts unconstrained string input· accept_missionunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `mission_id`, `session_id`, `template_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  238. medium
    Tool `create_sell_order` accepts unconstrained string input· create_sell_orderunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `item_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  239. medium
    Tool `create_sell_order` description mentions money but no `money` side-effect is declared· create_sell_orderexcessive agency

    Description: "List items for sale on the station exchange (Listing fee on the portion that goes on the order book (1% default; pirate strongholds and stations with a custom market fee charge more). Instant fills incur no fee. Items escrowed from cargo first, then station storage. Accepts item_id or item name (e.g. 'Iron Ore'). Bulk mode: pass 'orders' array of {item_id, quantity, price_each} to create up to 50 orders in one call. If you already have an order for the same item at the same price, the new quantity is added to your existing order instead of creating a duplicate (response includes consolidated=true and the existing order_id).)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  240. medium
    Tool `commission_quote` accepts unconstrained string input· commission_quoteunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `ship_class`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  241. medium
    Tool `commission_quote` description mentions money but no `money` side-effect is declared· commission_quoteexcessive agency

    Description: "Get a cost estimate for commissioning a ship (Returns detailed pricing for both payment modes (credits-only vs provide-materials) and lists any blockers (wrong empire, shipyard tier, skills). Does not place an order.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  242. medium
    Tool `attack` accepts unconstrained string input· attackunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `target_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  243. medium
    Tool `switch_ship` accepts unconstrained string input· switch_shipunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `ship_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  244. medium
    Tool `get_achievements` accepts unconstrained string input· get_achievementsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  245. medium
    Tool `forum_upvote` accepts unconstrained string input· forum_upvoteunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `reply_id`, `session_id`, `thread_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  246. medium
    Tool `upload_drone_script` accepts unconstrained string input· upload_drone_scriptunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `drone_id`, `script`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  247. medium
    Tool `completed_missions` accepts unconstrained string input· completed_missionsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  248. medium
    Tool `get_faction_tax_estimate` accepts unconstrained string input· get_faction_tax_estimateunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  249. medium
    Tool `get_faction_tax_estimate` description mentions money but no `money` side-effect is declared· get_faction_tax_estimateexcessive agency

    Description: "Preview the corporate income tax your faction would owe right now (Returns the corporate income-tax assessment your faction would face if the weekly cycle ran this instant. A faction has no citizenship, so jurisdiction is hybrid: the domicile empire (your faction's founder's birth empire) taxes the faction's worldwide earnings since the last cycle, while every empire where the faction owns a facility (a permanent establishment) taxes the profit sourced in its territory. Faction income tax is profit-based: deductible business expenses — the cost of goods and fuel the faction buys on the exchange to resell, treasury-funded facility builds and upgrades, and facility rent — are netted against income before the rate applies (income minus expenses, floored at zero; a net loss carries forward to offset future cycles, so goods bought in one cycle still shelter the sale proceeds when they land in a later one). The domicile then grants foreign-tax credits (the same foreign_income_tax_deduction treaty rates that apply to citizens) for source taxes already counted, so cross-border factions are not blindly double-taxed. taxable_income_to_date, deductible_expenses_to_date, and net_taxable_profit summarize the period; each income_tax row carries basis ('domicile' or 'source'), the effective rate_bps, the taxed_profit, gross before credit, the credit applied, and the net owed. carried_debt lists any tax an under-funded treasury could not pay in a prior cycle (added to the next assessment). Taxable income is genuine earnings only — faction exchange sell-order proceeds, fuel-bunker sales, and facility sales; member deposits, gifts, and refunds are not. The corporate rate defaults to the empire's personal income tax rate until a distinct one is set (see faction_income_tax_bps in get_empire_info). All rate_bps fields are basis points: 100 = 1%, 10000 = 100%. Pure read — no credits move, no notifications.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  250. medium
    Tool `get_faction_tax_estimate` fetches external web content -- indirect-injection surface· get_faction_tax_estimateindirect injection

    Description: "Preview the corporate income tax your faction would owe right now (Returns the corporate income-tax assessment your faction would face if the weekly cycle ran this instant. A faction has no citizenship, so jurisdiction is hybrid: the domicile empire (your faction's founder's birth empire) taxes the faction's worldwide earnings since the last cycle, while every empire where the faction owns a facility (a permanent establishment) taxes the profit sourced in its territory. Faction income tax is profit-based: deductible business expenses — the cost of goods and fuel the faction buys on the exchange to resell, treasury-funded facility builds and upgrades, and facility rent — are netted against income before the rate applies (income minus expenses, floored at zero; a net loss carries forward to offset future cycles, so goods bought in one cycle still shelter the sale proceeds when they land in a later one). The domicile then grants foreign-tax credits (the same foreign_income_tax_deduction treaty rates that apply to citizens) for source taxes already counted, so cross-border factions are not blindly double-taxed. taxable_income_to_date, deductible_expenses_to_date, and net_taxable_profit summarize the period; each income_tax row carries basis ('domicile' or 'source'), the effective rate_bps, the taxed_profit, gross before credit, the credit applied, and the net owed. carried_debt lists any tax an under-funded treasury could not pay in a prior cycle (added to the next assessment). Taxable income is genuine earnings only — faction exchange sell-order proceeds, fuel-bunker sales, and facility sales; member deposits, gifts, and refunds are not. The corporate rate defaults to the empire's personal income tax rate until a distinct one is set (see faction_income_tax_bps in get_empire_info). All rate_bps fields are basis points: 100 = 1%, 10000 = 100%. Pure read — no credits move, no notifications.)" -- this tool pulls externally-controlled content into the agent's context window, the canonical indirect-injection vector. Even when the user supplies the URL, content at that URL can carry hostile instructions.

    fix: Sandbox the fetched content: strip prompts before forwarding to the model, constrain to an allow-list of domains, and route through capframe-guard with a `domain in [...]` caveat.

  251. medium
    Tool `forum_reply` accepts unconstrained string input· forum_replyunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `thread_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  252. medium
    Tool `get_notifications` accepts unconstrained string input· get_notificationsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  253. medium
    Tool `get_map` accepts unconstrained string input· get_mapunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `system_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  254. medium
    Tool `faction_set_enemy` accepts unconstrained string input· faction_set_enemyunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `target_faction_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  255. medium
    Tool `get_system_agents` accepts unconstrained string input· get_system_agentsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  256. medium
    Tool `faction_delete_room` accepts unconstrained string input· faction_delete_roomunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `room_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  257. medium
    Tool `create_note` accepts unconstrained string input· create_noteunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  258. medium
    Tool `faction_create_buy_order` accepts unconstrained string input· faction_create_buy_orderunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `bucket`, `item_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  259. medium
    Tool `faction_create_buy_order` description mentions money but no `money` side-effect is declared· faction_create_buy_orderexcessive agency

    Description: "Create a buy order on behalf of your faction (credits from faction treasury) (Credits are escrowed from the faction treasury. Purchased items go to faction storage. Use item_id 'fuel' to post a buy order for fuel — filled by players selling fuel from their ships, routed to faction fuel reserve. Requires `manage_treasury` permission. Accepts item_id or item name. If the faction already has an order for the same item at the same price, the new quantity is added to the existing order instead of creating a duplicate. Set private:true to post a Company Store listing — a members-only buy order visible to and fillable by faction members only (requires a Company Store facility here; counts against its own listing cap, separate from the market cap). Bulk mode: pass 'orders' array of {item_id, quantity, price_each, bucket, private} to create up to 50 orders in one call.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  260. medium
    Tool `faction_info` accepts unconstrained string input· faction_infounconstrained input

    The following string parameter(s) have no `maxLength` constraint: `faction_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  261. medium
    Tool `get_drones` accepts unconstrained string input· get_dronesunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  262. medium
    Tool `set_drone_name` accepts unconstrained string input· set_drone_nameunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `drone_id`, `name`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  263. medium
    Tool `unsubscribe_market` accepts unconstrained string input· unsubscribe_marketunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  264. medium
    Tool `faction_deposit_items` accepts unconstrained string input· faction_deposit_itemsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `item_id`, `session_id`, `target`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  265. medium
    Tool `get_empire_info` accepts unconstrained string input· get_empire_infounconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  266. medium
    Tool `get_empire_info` fetches external web content -- indirect-injection surface· get_empire_infoindirect injection

    Description: "Get the live policy snapshot for one or all empires (Returns fees, tax rates, criminal-law parameters, reputation dynamics, citizenship requirements, and contraband lists for empires. Optional payload: {"empire_id": "solarian"} to fetch a single empire; omit to get all five. Valid empire_id values: solarian, voidborn, crimson, nebula, outerrim. No authentication required. Policies are empire-wide — every station in an empire's space uses the same snapshot. Use get_tax_estimate for a personalised tax projection based on your citizenships.)" -- this tool pulls externally-controlled content into the agent's context window, the canonical indirect-injection vector. Even when the user supplies the URL, content at that URL can carry hostile instructions.

    fix: Sandbox the fetched content: strip prompts before forwarding to the model, constrain to an allow-list of domains, and route through capframe-guard with a `domain in [...]` caveat.

  267. medium
    Tool `subscribe_market` accepts unconstrained string input· subscribe_marketunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  268. medium
    Tool `subscribe_market` description mentions money but no `money` side-effect is declared· subscribe_marketexcessive agency

    Description: "Subscribe to live market updates at the current station (Best over a persistent connection (WebSocket v2). Returns a full snapshot of the station's order book (same per-item depth as view_market: aggregated price levels with quantities) as a baseline, then pushes 'market_update' messages whenever an item's book changes — instead of polling view_market repeatedly. Each market_update carries only the items that changed, with their current sell/buy levels. Fuel and contraband are excluded from the feed. The subscription is automatically dropped when you undock or disconnect.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  269. medium
    Tool `faction_trade_intel_status` accepts unconstrained string input· faction_trade_intel_statusunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  270. medium
    Tool `jettison` accepts unconstrained string input· jettisonunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `item_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  271. medium
    Tool `load_passenger` accepts unconstrained string input· load_passengerunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `destination`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  272. medium
    Tool `load_passenger` description mentions money but no `money` side-effect is declared· load_passengerexcessive agency

    Description: "Load all waiting passengers bound for a destination into your passenger berths (You must be docked and have passenger berths (built into liner-class ships, or from an installed passenger cabin module). Loads every waiting passenger here whose destination matches, up to your available berths (a higher-class berth can seat a lower-class passenger). Run it again for other destinations to fill berths for multiple stops. Each passenger has a generous travel-time guarantee: deliver them to their destination before it expires to collect the fare, plus a speed bonus of up to +50% that shrinks as the guarantee window runs down. Fares = (base + per-jump) x accommodation class x destination remoteness x origin fare surge. Fares are funded by the origin station's economy: it escrows the payout when a passenger boards, so at a broke station some passengers may be unable to board (reported as skipped_unfunded). If your faction has a Transit Lounge here, connecting passengers laid over in it who match the destination board too (marked connecting: true) — their original fares and deadlines simply continue, no new escrow. Call multiple times before undocking to build a route.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  273. medium
    Tool `faction_list` accepts unconstrained string input· faction_listunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  274. medium
    Tool `get_base_cost` accepts unconstrained string input· get_base_costunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  275. medium
    Tool `scan` accepts unconstrained string input· scanunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `target_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  276. medium
    Tool `battle` accepts unconstrained string input· battleunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `target_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  277. medium
    Tool `get_chat_history` accepts unconstrained string input· get_chat_historyunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `after`, `before`, `session_id`, `target_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  278. medium
    Tool `citizenship` accepts unconstrained string input· citizenshipunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  279. medium
    Tool `citizenship` description mentions money but no `money` side-effect is declared· citizenshipexcessive agency

    Description: "View and manage your empire citizenships (list, apply, renounce, withdraw) (Action-dispatched. Empire IDs: solarian, voidborn, crimson, nebula, outerrim. Concepts - Origin: the empire you picked at character creation (player.empire). Immutable — affects empire-restricted skills and ship classes. - Citizenship: a separate, mutable membership in an empire. You can hold zero or more citizenships in any combination. New players start with citizenship in their origin empire only. - Citizenship decides which empire taxes you and at what rate: an empire charges its own citizens one sales-tax rate, citizens of other empires another, and the stateless a third. Income and property tax are assessed by the empires you hold citizenship in. Holding no citizenship does not mean paying nothing — check get_tax_estimate before you assume. Actions list (default; query, no empire_id needed): Returns your origin, current citizenships, pending and recent applications, and a per-empire 'empires' summary. Each summary includes: - open: whether the empire accepts applications at all (closed empires reject everyone) - exclusive: see "Exclusive empires" below - auto_approve: whether meeting numeric criteria grants citizenship immediately, or only files a petition for review - fee: credit fee held in escrow when you apply - min_balance: credits you must hold at application time - min_reputation: reputation with that empire you must hold at application time - your_reputation: your current reputation with that empire - eligible: whether you can apply right now - ineligible_reason: when eligible=false, the specific gate you failed apply (mutation; requires empire_id): Submit an application. The fee is deducted immediately and held in escrow. You must hold (min_balance + fee) in credits and your reputation must be >= min_reputation. Only one pending application per empire at a time. Outcomes: - If the empire's policy is auto_approve and you meet every numeric gate, citizenship is granted on the spot. The petition is recorded with status=granted for the audit trail. - Otherwise the application enters the empire's petition queue with status=pending for a manual decision by the empire. The fee stays in escrow until decision. Decision outcomes (set by the empire, not you): - granted: citizenship added. Fee is kept (paid into the empire's treasury). - rejected: fee refunded to you. Citizenship not added. Exclusive empires: When citizenship is granted in an exclusive empire (CitizenshipExclusive=true), every other citizenship you currently hold is automatically renounced. This applies to both the auto-approve path and a manual grant via petition. You may re-apply elsewhere afterwards — exclusivity is only checked at the moment of grant. If you want to be a citizen of multiple empires, do not pursue exclusive ones. renounce (mutation; requires empire_id): Drops the citizenship in the given empire. You may renounce any citizenship including your origin empire's. Your player.empire (birthright/origin) is unchanged either way — only the active citizenship is removed. Renunciation is permanent unless you re-apply; there is no undo. Going stateless (holding zero citizenships) is allowed, but empires may treat you differently under their policies. Renouncing does not refund anything. withdraw (mutation; requires empire_id): Cancels your pending application for that empire and refunds the held fee. No effect on any citizenship you already hold. Errors you may see on apply: citizenship_closed, already_citizen, already_pending, insufficient_balance, insufficient_credits (balance+fee), insufficient_reputation, invalid_empire.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  280. medium
    Tool `faction_prepay_tax` accepts unconstrained string input· faction_prepay_taxunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  281. medium
    Tool `faction_prepay_tax` description mentions money but no `money` side-effect is declared· faction_prepay_taxexcessive agency

    Description: "Prepay credits from the faction treasury toward the next corporate tax assessment (Moves credits from the faction treasury into a tax-prepayment pool. On tax day the pool covers the faction's corporate income-tax assessment before the treasury is touched, so the faction can't be caught short. Any surplus left after the cycle is refunded to the treasury. Requires the ManageTreasury permission. Use get_faction_tax_estimate to see the current obligation and prepaid balance (tax_prepaid). amount must be a positive number of credits.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  282. medium
    Tool `faction_withdraw_credits` accepts unconstrained string input· faction_withdraw_creditsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  283. medium
    Tool `faction_withdraw_credits` description mentions money but no `money` side-effect is declared· faction_withdraw_creditsexcessive agency

    Description: "Transfer credits from the faction treasury to your wallet (Requires `manage_treasury` permission. Tracked in the audit log.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  284. medium
    Tool `faction_delete_role` accepts unconstrained string input· faction_delete_roleunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `role_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  285. medium
    Tool `commission_ship` accepts unconstrained string input· commission_shipunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `ship_class`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  286. medium
    Tool `commission_ship` description mentions money but no `money` side-effect is declared· commission_shipexcessive agency

    Description: "Commission a ship to be built at this shipyard (Place a build order at the current base's shipyard. At an empire/NPC shipyard, two payment modes: credits only (default, pay markup for materials + labor) or provide_materials (cheaper, supply build materials and required modules yourself). Both modes also pay the shipyard a yard fee — the station's profit for building the hull — refunded in full if you cancel. At your own faction's station, commissions are faction-funded instead: set fund_from_faction=true (requires ManageTreasury) — materials come from faction storage and the treasury pays labor and any licensed-hull royalty; the credits-only/provide_materials modes are rejected there. The finished hull is delivered to you and can be resold. Use commission_quote to see requirements. Build time depends on ship class and shipyard level. On completion the server pushes ship_commission_complete, the only frame carrying both commission_id and ship_id — listen for it rather than diffing list_ships.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  287. medium
    Tool `hunt` accepts unconstrained string input· huntunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `target_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  288. medium
    Tool `petition` accepts unconstrained string input· petitionunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  289. medium
    Tool `repair` accepts unconstrained string input· repairunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `item_id`, `session_id`, `target`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  290. medium
    Tool `faction_rooms` accepts unconstrained string input· faction_roomsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  291. medium
    Tool `cancel_ship_buy_order` accepts unconstrained string input· cancel_ship_buy_orderunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `order_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  292. medium
    Tool `cancel_ship_buy_order` description mentions money but no `money` side-effect is declared· cancel_ship_buy_orderexcessive agency

    Description: "Cancel one of your ship buy orders and refund the escrow (Refunds the full escrowed amount (price + sales tax). Works from anywhere. If the shipyard was already building for your order, the finished ship goes to the showroom instead.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  293. medium
    Tool `sell_wreck` accepts unconstrained string input· sell_wreckunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  294. medium
    Tool `unload_passenger` accepts unconstrained string input· unload_passengerunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `name`, `session_id`, `target`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  295. medium
    Tool `unload_passenger` description mentions money but no `money` side-effect is declared· unload_passengerexcessive agency

    Description: "Put a passenger (or everyone) off the ship here — or hand them off to another ship or your faction's transit lounge for a connecting flight (You must be docked. If this station is the passenger's destination they are delivered and pay their fare (base fare plus a speed bonus for prompt delivery); otherwise they are stranded here, pay nothing, and you take a small reputation hit with their empire. Pass "all" to put every passenger off at once (delivered ones pay, the rest are stranded) in a single combined operation. CONNECTING FLIGHTS: pass target to hand passengers off mid-journey instead of debarking — target="lounge" checks them into your faction's Transit Lounge at this station (any faction member can board them onward with load_passenger; L2+ lounges also extend their fare deadline, once per journey), while target=<ship id or name> transfers them straight onto that ship (docked here, owned by you or a faction mate, with free berths of an acceptable class). Either way the fare, its escrow, and the deadline continue unchanged, and whoever finally delivers the passenger collects the full fare. Expired passengers can't be handed off, and a lounge passenger whose deadline expires walks out to the ordinary pickup queue — your faction gets a departure-board warning (notification + faction action log) when a layover is about to miss their connection. Checked-in passengers also spend a little at the station's dining/leisure amenities, credited to whoever operates them (first two lounge stops of a journey only). Use 'list_passengers' to see who is aboard.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  296. medium
    Tool `get_battle_status` accepts unconstrained string input· get_battle_statusunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  297. medium
    Tool `faction_edit` accepts unconstrained string input· faction_editunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  298. medium
    Tool `faction_edit` description mentions money but no `money` side-effect is declared· faction_editexcessive agency

    Description: "Update faction description, charter, colors, and ally-sharing toggles (Shape your faction's identity. The description (max 500 chars) is your faction's public tagline — a short summary that appears in listings. The charter (max 4000 chars) is your faction's founding document: a manifesto, code of conduct, origin story, or declaration of purpose. Colors are hex codes for your faction's visual identity. Three boolean toggles control what your allies can use: ally_intel_opt_out=true withholds your intel pool (default false → sharing on); ally_fuel_access=true lets allied members refuel for free from your bunker reserves (default false → opt-in); ally_facility_access=true lets allied members use your faction's facilities for free, their jobs queuing on excess capacity behind your own members' (default false → allies pay the public rental price, or have no access when the facility is private). All fields optional. Requires leader or `manage_roles` permission. Requires Faction Admin Office at current station.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  299. medium
    Tool `get_status` accepts unconstrained string input· get_statusunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  300. medium
    Tool `faction_submit_intel` accepts unconstrained string input· faction_submit_intelunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  301. medium
    Tool `set_home_base` accepts unconstrained string input· set_home_baseunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `base_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  302. medium
    Tool `mute_notifications` accepts unconstrained string input· mute_notificationsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  303. medium
    Tool `get_version` accepts unconstrained string input· get_versionunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `id`, `session_id`, `text`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  304. medium
    Tool `search_systems` accepts unconstrained string input· search_systemsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `query`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  305. medium
    Tool `deposit_items` accepts unconstrained string input· deposit_itemsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `item_id`, `session_id`, `target`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  306. medium
    Tool `deploy_drone` accepts unconstrained string input· deploy_droneunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `drone_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  307. medium
    Tool `get_commands` accepts unconstrained string input· get_commandsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  308. medium
    Tool `uninstall_mod` accepts unconstrained string input· uninstall_modunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `module_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  309. medium
    Tool `reload` accepts unconstrained string input· reloadunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `ammo_item_id`, `session_id`, `weapon_instance_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  310. medium
    Tool `faction_query_trade_intel` accepts unconstrained string input· faction_query_trade_intelunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `base_id`, `item_id`, `session_id`, `source_faction_id`, `station_name`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  311. medium
    Tool `view_ship_buy_orders` accepts unconstrained string input· view_ship_buy_ordersunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  312. medium
    Tool `view_ship_buy_orders` description mentions money but no `money` side-effect is declared· view_ship_buy_ordersexcessive agency

    Description: "View your open ship buy orders across all bases (Shows each order's base, ship class, escrowed price, and whether the station shipyard is currently building a ship to fill it.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  313. medium
    Tool `forum_create_thread` accepts unconstrained string input· forum_create_threadunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  314. medium
    Tool `scrap_ship` accepts unconstrained string input· scrap_shipunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `ship_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  315. medium
    Tool `view_insurance` accepts unconstrained string input· view_insuranceunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  316. medium
    Tool `trade_offer` accepts unconstrained string input· trade_offerunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `target_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  317. medium
    Tool `install_mod` accepts unconstrained string input· install_modunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `module_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  318. medium
    Tool `faction_propose_ally` accepts unconstrained string input· faction_propose_allyunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `target_faction_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  319. medium
    Tool `survey_system` accepts unconstrained string input· survey_systemunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  320. medium
    Tool `decline_mission` accepts unconstrained string input· decline_missionunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `mission_id`, `session_id`, `template_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  321. medium
    Tool `faction_create_sell_order` accepts unconstrained string input· faction_create_sell_orderunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `bucket`, `item_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  322. medium
    Tool `cancel_ship_listing` accepts unconstrained string input· cancel_ship_listingunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `listing_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  323. medium
    Tool `cancel_ship_listing` description mentions money but no `money` side-effect is declared· cancel_ship_listingexcessive agency

    Description: "Remove your ship listing from the exchange (Cancel a ship listing. The listing's seller — or the ship's current owner — may cancel it. The listing fee is not refunded.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  324. medium
    Tool `repair_module` accepts unconstrained string input· repair_moduleunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `module_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  325. medium
    Tool `create_faction` accepts unconstrained string input· create_factionunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  326. medium
    Tool `faction_declare_war` accepts unconstrained string input· faction_declare_warunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `reason`, `session_id`, `target_faction_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  327. medium
    Tool `self_destruct` accepts unconstrained string input· self_destructunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  328. medium
    Tool `get_battle_log` accepts unconstrained string input· get_battle_logunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `battle_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  329. medium
    Tool `trade_cancel` accepts unconstrained string input· trade_cancelunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `trade_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  330. medium
    Tool `get_nearby` accepts unconstrained string input· get_nearbyunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  331. medium
    Tool `jump` accepts unconstrained string input· jumpunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `target_system`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  332. medium
    Tool `mine` accepts unconstrained string input· mineunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  333. medium
    Tool `trade_accept` accepts unconstrained string input· trade_acceptunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `trade_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  334. medium
    Tool `faction_invite` accepts unconstrained string input· faction_inviteunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `player_id`, `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  335. medium
    Tool `faction_deposit_credits` accepts unconstrained string input· faction_deposit_creditsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  336. medium
    Tool `faction_deposit_credits` description mentions money but no `money` side-effect is declared· faction_deposit_creditsexcessive agency

    Description: "Transfer credits from your wallet to the faction treasury (Any faction member can deposit credits. Tracked in the audit log.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  337. medium
    Tool `unsubscribe_observation` accepts unconstrained string input· unsubscribe_observationunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  338. medium
    Tool `buy_ship_license` accepts unconstrained string input· buy_ship_licenseunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`, `ship_class`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

  339. medium
    Tool `buy_ship_license` description mentions money but no `money` side-effect is declared· buy_ship_licenseexcessive agency

    Description: "License a specific ship design so your faction can build it at its own stations (Empire and pirate hulls are normally exclusive to their own territory. A per-design shipbuilding license lets your faction build that one hull at its own stations, in exchange for a per-build royalty of 10% of the hull's raw material value paid to the hull's empire treasury (pirate hulls: the royalty is a sink). License cost comes from the faction treasury and scales with tier: T1=1M, T2=5M, T3=10M, T4=20M, T5=50M. Requires the ManageTreasury permission. Buy as many designs as you can afford — including pirate hulls (no stronghold needed) — but not starter or prestige hulls. At a faction station ships are then built faction-funded (commission_ship with fund_from_faction=true): materials come from faction storage and the treasury pays labor and royalty. The finished hull goes to the commissioning member, who may resell it.)" -- this references money/payment/refund/etc., but the declared side_effects ([]) don't include `money`. A capframe-bind policy that relies on declared side_effects to scope spend caveats will under-scope this tool.

    fix: Add `money` to the tool's `side_effects` declaration, or rewrite the description to clarify that no actual money moves.

  340. medium
    Tool `get_notifications` accepts unconstrained string input· get_notificationsunconstrained input

    The following string parameter(s) have no `maxLength` constraint: `session_id`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.

    fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.

How this was scored

Source http live HTTP MCP endpoint, classified against every rule. Findings are emitted by the public capframe.findings.v1 schema. Score = 100 − (10·Critical + 4·High + 2·Medium + 1·Low), clamped to [0, 100].

Disagree with a finding? Open an issue.