# Inter-canister messages and inspect\_message, cycles burn with no way to reject?

**URL:** <https://forum.dfinity.org/t/inter-canister-messages-and-inspect-message-cycles-burn-with-no-way-to-reject/66149>\
**Category:** Developers\
**Tags:** security, cycles\
**Created:** [March 28, 2026, 3:37pm UTC](https://forum.dfinity.org/t/inter-canister-messages-and-inspect-message-cycles-burn-with-no-way-to-reject/66149 "2026-03-28T15:37:59Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![da5id](https://avatars.discourse-cdn.com/v4/letter/d/5f8ce5/32.png) [@da5id](https://forum.dfinity.org/u/da5id)\
**Post date:** [March 28, 2026, 3:37pm UTC](https://forum.dfinity.org/t/inter-canister-messages-and-inspect-message-cycles-burn-with-no-way-to-reject/66149/1 "2026-03-28T15:37:59Z")

</div>

I’m trying to understand if this is really true. According to some previous conversations I have seen on the forums, and [The Internet Computer Interface Specification | Internet Computer](https://docs.internetcomputer.org/references/ic-interface-spec) it seems clear that :

> The `canister_inspect_message` is _not_ invoked for query calls, inter-canister calls or calls to the management canister.

So I’m a bit puzzled, as this seems like a gaping hole for a cycles burn attack, even if I trap on the first line of a call, I’m still paying the base-fee = 5M cycles.

I have an application in mind where the user pays for usage, but seems a bit pointless if any malicious user can spin up a canister and burn cycles by spamming calls anyway.

If this is true, all I can say is, please give us the ability to use inspect\_message on inter-canister calls (and query calls as well, if (when) queries become chargeable), as this is untenable.

---

<div class="post-metadata">

**Author:** ![GigaverseLabs](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/gigaverselabs/32/34831_2.png) [@GigaverseLabs](https://forum.dfinity.org/u/GigaverseLabs)\
**Post date:** [March 28, 2026, 3:47pm UTC](https://forum.dfinity.org/t/inter-canister-messages-and-inspect-message-cycles-burn-with-no-way-to-reject/66149/2 "2026-03-28T15:47:36Z")

</div>

You’re not wrong to question it, but it’s not quite the “gaping hole” it might look like at first glance.

Yes, `canister_inspect_message` doesn’t run for inter-canister or query calls, and you still pay the base cost for ingress messages—but that’s kind of by design. The model assumes that **canisters interacting with other canisters are already part of a trust or incentive system** , rather than completely untrusted spam sources.

For actual abuse scenarios:

- A malicious actor still has to **spend cycles on their side** to generate traffic

- You can mitigate by designing your canister to **fail fast and cheap** (minimal execution before reject)

- Rate-limiting, access control, or requiring some form of **prepaid / whitelisted interaction** can help

So it’s less “unprotected” and more that **the responsibility shifts to canister design and economic incentives** rather than protocol-level filtering in those cases.

That said, your point is valid—having `inspect_message` for inter-canister calls (and eventually queries) would give developers much finer control and reduce unnecessary cycle burn. It’s a reasonable feature request, especially for pay-per-use models.

---

<div class="post-metadata">

**Author:** ![da5id](https://avatars.discourse-cdn.com/v4/letter/d/5f8ce5/32.png) [@da5id](https://forum.dfinity.org/u/da5id)\
**Post date:** [March 28, 2026, 4:07pm UTC](https://forum.dfinity.org/t/inter-canister-messages-and-inspect-message-cycles-burn-with-no-way-to-reject/66149/3 "2026-03-28T16:07:38Z")

</div>

> [@GigaverseLabs](#):
>
> A malicious actor still has to **spend cycles on their side** to generate traffic

If my napkin math is correct, looks like about 360K cycles for them to spend 5M of mine. Doesn’t seem like a winning situation to be in.

> The model assumes that **canisters interacting with other canisters are already part of a trust or incentive system** , rather than completely untrusted spam sources.

> **responsibility shifts to canister design and economic incentives**

Sure, if there was some way to gate to canisters I trust. But there isn’t. What canister design options do I have? Or am I missing something?

---

<div class="post-metadata">

**Author:** ![Seb](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/seb/32/10340_2.png) [@Seb](https://forum.dfinity.org/u/Seb)\
**Post date:** [March 28, 2026, 4:38pm UTC](https://forum.dfinity.org/t/inter-canister-messages-and-inspect-message-cycles-burn-with-no-way-to-reject/66149/4 "2026-03-28T16:38:29Z")

</div>

One thing to nuance. If the call comes from an inter-canister call, the attacker’s canister must also be executing. So they also pay the 5M base fee on their side, plus 260K for the xnet call. So it’s closer to 5.3M vs 5M (not counting the instruction cost on their side), a bit more balanced. Also if the canister is not in your subnet you have additional protection (xnet call cost).

Edit: Actually, this might be unbalanced again if as an attacker you use notify/one-way calls to skip callbacks and you batch multiple calls to an external canister inside one update call on your side. Then you pay 5M once + N×260K, while the victim pays N×5M. Back to ~20:1 at scale. I have to admit, I haven’t thought through this scenario before. 🤔

---

<div class="post-metadata">

**Author:** ![SSS](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/sss/32/35888_2.png) [@SSS](https://forum.dfinity.org/u/SSS)\
**Post date:** [March 29, 2026, 2:51am UTC](https://forum.dfinity.org/t/inter-canister-messages-and-inspect-message-cycles-burn-with-no-way-to-reject/66149/5 "2026-03-29T02:51:40Z")

</div>

This is exactly why execution-system design matters.

If anti-abuse is pushed up to the application layer, then prepaid paths, rate limits, and cheap-fail execution become part of core infra — not optional app logic.

---

<div class="post-metadata">

**Author:** ![mraszyk](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/mraszyk/32/7945_2.png) [@mraszyk](https://forum.dfinity.org/u/mraszyk)\
**Post date:** [April 1, 2026, 5:58pm UTC](https://forum.dfinity.org/t/inter-canister-messages-and-inspect-message-cycles-burn-with-no-way-to-reject/66149/6 "2026-04-01T17:58:12Z")

</div>

> [@Seb](#):
>
> Actually, this might be unbalanced again if as an attacker you use notify/one-way calls to skip callbacks and you batch multiple calls to an external canister inside one update call on your side. Then you pay 5M once + N×260K, while the victim pays N×5M. Back to ~20:1 at scale. I have to admit, I haven’t thought through this scenario before.

Even if an attacker sends multiple calls in parallel, each call will have its own (response) callback and there will be a base cost of 5M per callback (cycles for instructions are prepaid before making each of the calls - otherwise the calls fail to be sent - so they are available for every response callback). So the cost of parallel cost does not amortize the way you described it above.

---

<div class="post-metadata">

**Author:** ![da5id](https://avatars.discourse-cdn.com/v4/letter/d/5f8ce5/32.png) [@da5id](https://forum.dfinity.org/u/da5id)\
**Post date:** [April 2, 2026, 5:19am UTC](https://forum.dfinity.org/t/inter-canister-messages-and-inspect-message-cycles-burn-with-no-way-to-reject/66149/7 "2026-04-02T05:19:13Z")

</div>

> [@mraszyk](#):
>
> each call will have its own (response) callback and there will be a base cost of 5M per callback

This is very unexpected, but looking at the source I do see it, update\_message\_execution\_fee (5M) is charged along with instructions\_to\_cycles(max\_num\_instructions). The instruction cycles are refunded as they are not used, but the update\_message\_execution\_fee is not. I’m assuming this is intended, since you referenced it, but it’s not documented, and isn’t intuitively what I would expect sending a Call::oneway(). Is it there for this reason?

A way to control which canisters can send me inbound messages (inspect\_message or something else) is still needed, because even if they burn at the same rate as me, it’s something I can’t control, and a DoS unless I am willing to spend to keep up with it.

---

<div class="post-metadata">

**Author:** ![mraszyk](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/mraszyk/32/7945_2.png) [@mraszyk](https://forum.dfinity.org/u/mraszyk)\
**Post date:** [April 2, 2026, 8:30am UTC](https://forum.dfinity.org/t/inter-canister-messages-and-inspect-message-cycles-burn-with-no-way-to-reject/66149/8 "2026-04-02T08:30:49Z")

</div>

> [@da5id](#):
>
> Is it there for this reason?

The reason is that one-way calls are not natively supported by the IC and thus the CDK “emulates” them by passing an invalid function pointer which results in a trap.
