diff --git a/src/controller/CommissionerDiscoveryController.cpp b/src/controller/CommissionerDiscoveryController.cpp
index 7f13a4323d2f5c..09a22e03e0bcd2 100644
--- a/src/controller/CommissionerDiscoveryController.cpp
+++ b/src/controller/CommissionerDiscoveryController.cpp
@@ -589,12 +589,36 @@ void CommissionerDiscoveryController::Cancel()
         return;
     }
     UDCClientState * client = mUdcServer->GetUDCClients().FindUDCClientState(mCurrentInstance);
-    if (client == nullptr || client->GetUDCClientProcessingState() != UDCClientProcessingState::kPromptingUser)
+
+    if (client == nullptr)
+    {
+        ChipLogError(AppServer, "UX Cancel: client not found");
+        return;
+    }
+
+    auto state = client->GetUDCClientProcessingState();
+
+    bool isCancelableState =
+        (state == UDCClientProcessingState::kPromptingUser || state == UDCClientProcessingState::kObtainingOnboardingPayload ||
+         state == UDCClientProcessingState::kWaitingForCommissionerPasscodeReady);
+
+    if (!isCancelableState)
     {
-        ChipLogError(AppServer, "UX Cancel: invalid state for cancel");
+        ChipLogError(AppServer, "UX Cancel: invalid state for cancel, state: %hhu", static_cast<uint8_t>(state));
         return;
     }
+
     client->SetUDCClientProcessingState(UDCClientProcessingState::kUserDeclined);
+
+    if (state == UDCClientProcessingState::kObtainingOnboardingPayload ||
+        state == UDCClientProcessingState::kWaitingForCommissionerPasscodeReady)
+    {
+        ChipLogDetail(AppServer, "UX Cancel: user cancelled entering PIN code, sending CDC");
+        CommissionerDeclaration cd;
+        cd.SetCancelPasscode(true);
+        mUdcServer->SendCDCMessage(cd, Transport::PeerAddress::UDP(client->GetPeerAddress().GetIPAddress(), client->GetCdPort()));
+    }
+
     mPendingConsent = false;
     ResetState();
 }
diff --git a/src/protocols/user_directed_commissioning/UserDirectedCommissioning.h b/src/protocols/user_directed_commissioning/UserDirectedCommissioning.h
index cf9a55365b9191..fb1aedc03e8d6e 100644
--- a/src/protocols/user_directed_commissioning/UserDirectedCommissioning.h
+++ b/src/protocols/user_directed_commissioning/UserDirectedCommissioning.h
@@ -227,7 +227,6 @@ class DLL_EXPORT IdentificationDeclaration
         {
             ChipLogDetail(AppServer, "\tpairing hint: %d", mPairingHint);
         }
-
         if (mNoPasscode)
         {
             ChipLogDetail(AppServer, "\tno passcode: true");
@@ -349,6 +348,9 @@ class DLL_EXPORT CommissionerDeclaration
     void SetQRCodeDisplayed(bool newValue) { mQRCodeDisplayed = newValue; };
     bool GetQRCodeDisplayed() const { return mQRCodeDisplayed; };
 
+    void SetCancelPasscode(bool newValue) { mCancelPasscode = newValue; };
+    bool GetCancelPasscode() const { return mCancelPasscode; };
+
     /**
      *  Writes the CommissionerDeclaration message to the given buffer.
      *
@@ -390,6 +392,10 @@ class DLL_EXPORT CommissionerDeclaration
         {
             ChipLogDetail(AppServer, "\tQR code displayed: true");
         }
+        if (mCancelPasscode)
+        {
+            ChipLogDetail(AppServer, "\tPasscode cancelled: true");
+        }
         ChipLogDetail(AppServer, "---- Commissioner Declaration End ----");
     }
 
@@ -403,6 +409,7 @@ class DLL_EXPORT CommissionerDeclaration
         kPasscodeDialogDisplayedTag,
         kCommissionerPasscodeTag,
         kQRCodeDisplayedTag,
+        kCancelPasscodeTag,
 
         kMaxNum = UINT8_MAX
     };
@@ -413,6 +420,7 @@ class DLL_EXPORT CommissionerDeclaration
     bool mPasscodeDialogDisplayed = false;
     bool mCommissionerPasscode    = false;
     bool mQRCodeDisplayed         = false;
+    bool mCancelPasscode          = false;
 };
 
 class DLL_EXPORT InstanceNameResolver
diff --git a/src/protocols/user_directed_commissioning/UserDirectedCommissioningClient.cpp b/src/protocols/user_directed_commissioning/UserDirectedCommissioningClient.cpp
index aeb5691be2554c..f0ee3bbe69abfd 100644
--- a/src/protocols/user_directed_commissioning/UserDirectedCommissioningClient.cpp
+++ b/src/protocols/user_directed_commissioning/UserDirectedCommissioningClient.cpp
@@ -223,6 +223,9 @@ CHIP_ERROR CommissionerDeclaration::ReadPayload(uint8_t * udcPayload, size_t pay
         case kQRCodeDisplayedTag:
             err = reader.Get(mQRCodeDisplayed);
             break;
+        case kCancelPasscodeTag:
+            err = reader.Get(mCancelPasscode);
+            break;
         }
     }
 
diff --git a/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp b/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp
index fb31049d1d99a9..118ba7c7c524e4 100644
--- a/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp
+++ b/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp
@@ -435,6 +435,8 @@ uint32_t CommissionerDeclaration::WritePayload(uint8_t * payloadBuffer, size_t p
                  LogErrorOnFailure(err));
     VerifyOrExit(CHIP_NO_ERROR == (err = writer.PutBoolean(chip::TLV::ContextTag(kQRCodeDisplayedTag), mQRCodeDisplayed)),
                  LogErrorOnFailure(err));
+    VerifyOrExit(CHIP_NO_ERROR == (err = writer.PutBoolean(chip::TLV::ContextTag(kCancelPasscodeTag), mCancelPasscode)),
+                 LogErrorOnFailure(err));
 
     VerifyOrExit(CHIP_NO_ERROR == (err = writer.EndContainer(outerContainerType)), LogErrorOnFailure(err));
     VerifyOrExit(CHIP_NO_ERROR == (err = writer.Finalize()), LogErrorOnFailure(err));