How-to

Handle a denied message

Applies to: .NET SDK, Node.js SDK Last updated: 2026-06-11

Goal

Detect denied inbound messages and react with appropriate logging, alerting, or fallback behaviour.

Inbound deny — body is redacted

When a policy rule denies an inbound message, the SDK still returns a result, but the body is replaced and the status reflects the deny:

var msg = await client.DecryptEnvelopeAsync(envelope);

if (msg.Authorized == AuthorizationStatus.Denied)
{
    logger.LogWarning(
        "Denied inbound from {Sender}: {Reason}",
        msg.Sender, msg.DenialReason);

    // msg.Body is the literal string:
    // "redacted due to authorization enforcement"
    return;
}

// Allowed — process the real body
ProcessMessage(msg.Sender, msg.Body);

Outbound deny — exception is thrown

When a policy rule denies an outbound message, EncryptEnvelopeAsync throws:

try
{
    string envelope = await client.EncryptEnvelopeAsync(recipient, body);
    await transport.SendAsync(envelope);
}
catch (UnauthorizedAccessException ex)
{
    logger.LogWarning(
        "Outbound to {Recipient} blocked: {Reason}",
        recipient, ex.Message);

    // No envelope was produced.
    // Decide whether to retry with different content,
    // notify the user, or fail the operation.
}

Reading the deny reason

The DenialReason property contains a human-readable string identifying the matching rule:

// Sample DenialReason:
// "denied by tier Default (default): p, [email protected], self, default, inbound, deny"

The DenyTier property tells you which tier the deny came from:

switch (msg.DenyTier)
{
    case PolicyTier.Default:  // Tier 4 — baseline rules
    case PolicyTier.App:      // Tier 3 — app-specific
    case PolicyTier.Session:  // Tier 2 — session-specific
    case PolicyTier.User:     // Tier 1 — user-specific
}

Logging deny events for review

A reasonable production pattern is to keep a queue of denied messages for human review:

if (msg.Authorized == AuthorizationStatus.Denied)
{
    await reviewQueue.AddAsync(new DeniedMessage
    {
        Sender    = msg.Sender,
        Reason    = msg.DenialReason,
        ReceivedAt = DateTime.UtcNow,
    });
    return;
}

See also