unicity-aos/aos-ce · warning

Dropped ingress message to blocked topic

Error message

Dropped ingress message to blocked topic: {topic}

What it means

The message's topic failed is_allowed_ingress_topic, so the library drops it entirely: it is not forwarded AND it does not retarget the connection's session (session_id: None). This blocks a spoofing vector where an unforwarded message could otherwise redirect a connection onto another session's stream.

Solutions

  1. Check the logged topic against is_allowed_ingress_topic / the current allowlist and correct the client's topic name
  2. Update the ingress topic allowlist if this is a legitimate new topic
  3. Upgrade the client if it uses an outdated topic naming scheme
  4. If malicious activity is suspected, investigate the client sending off-allowlist topics

Example fix

// before
send(topic: "internal/debug-dump") // blocked
// after
send(topic: "events") // allowlisted topic
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED: &[&str] = &["events", "logs"];
if !ALLOWED.contains(&msg.topic.as_str()) {
    return Err(format!("topic {} is not allowlisted", msg.topic));
}

Prevention

When it happens

Trigger: A client sends an ingress message whose topic is not in the allowed set; the `if !is_allowed_ingress_topic(topic)` check logs this warning and returns IngressOutcome with newly_bound kept but session_id None.

Common situations: Clients subscribing to topics that were removed or renamed in the allowlist; typos in topic names; a malicious or buggy client probing internal topics; config changes tightening the ingress allowlist after a deploy.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13). Data as JSON: /api/errors/d86d2a3bb2148431. Report an issue: GitHub.

Appendix: source

Thrown at capsules/capsule-cli/src/lib.rs:596

    let (Some(topic), Some(payload)) = (
        msg.get("topic").and_then(|t| t.as_str()),
        msg.get("payload"),
    ) else {
        // No forwardable body, but the principal still binds the connection
        // (e.g. a bare handshake establishes identity for connect-tracking).
        // Nothing is forwarded, so the connection's session is never retargeted.
        log::warn("Ingress message has no topic/payload; binding only, nothing forwarded");
        return IngressOutcome {
            newly_bound,
            session_id: None,
        };
    };

    if !is_allowed_ingress_topic(topic) {
        // A blocked-topic message is neither forwarded nor allowed to retarget
        // the connection's session — otherwise a client could spoof itself onto
        // another session's stream with an unforwarded message.
        log::warn(format!("Dropped ingress message to blocked topic: {topic}"));
        return IngressOutcome {
            newly_bound,
            session_id: None,
        };
    }

    // Always forward under the connection's bound principal. There is no
    // `publish_json` (proxy self-identity) fallback for client traffic:
    // publishing without a principal would attribute the request to the
    // proxy capsule's own (admin-seeded) identity, so any socket client
    // could run admin commands (privilege escalation) — or, if the router
    // gates on the envelope principal, every admin request would be denied
    // for lacking one. A bound connection's traffic always attributes to
    // its principal (auto-attribution for un-stamped messages).
    if let Err(e) = ipc::publish_json_as(topic, payload, &forward_as) {
        log::error(format!("Failed to publish IPC: {e:?}"));
    }

View on GitHub (pinned to f6f22024fb)