diff --git a/meta-oe/recipes-devtools/android-tools/android-tools/0022-adbd-optionally-require-authorization-unless-the-bui.patch b/meta-oe/recipes-devtools/android-tools/android-tools/0022-adbd-optionally-require-authorization-unless-the-bui.patch
new file mode 100644
index 000000000000..e4115348fd31
--- /dev/null
+++ b/meta-oe/recipes-devtools/android-tools/android-tools/0022-adbd-optionally-require-authorization-unless-the-bui.patch
@@ -0,0 +1,138 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Alex Kiernan <alex.kiernan@gmail.com>
+Date: Fri, 6 Nov 2026 09:38:18 +0000
+Subject: [PATCH] adbd: optionally require authorization unless the build is
+ debuggable
+
+On a Linux build adbd accepts every connection without a key check:
+Debian's "don't require authorization on Linux" sets auth_required to
+false unconditionally, because there is no property service to relax it
+on development builds the way Android does.
+
+When make is given ADBD_AUTH_UNLESS_DEBUGGABLE=1, leave auth_required alone
+and decide per connection instead: a host must authenticate unless
+__android_log_is_debuggable() says the build is debuggable. Deciding per
+connection rather than once at startup lets a debuggable state that
+appears while adbd runs (LIBLOG_DEBUGGABLE_PROP_FILES re-reads its files)
+take effect without a restart. The TLS client-certificate checks make
+the same decision.
+
+Without the define nothing changes.
+
+Upstream-Status: Pending
+
+AI-Generated: Claude Opus 5.5 (Claude Code)
+Signed-off-by: Alex Kiernan <alex.kiernan@gmail.com>
+---
+ debian/system/adbd.mk                |  4 ++++
+ packages/modules/adb/adb.cpp         |  2 +-
+ packages/modules/adb/adb_auth.h      |  4 ++++
+ packages/modules/adb/daemon/auth.cpp | 17 +++++++++++++++--
+ packages/modules/adb/daemon/main.cpp |  2 +-
+ 5 files changed, 25 insertions(+), 4 deletions(-)
+
+diff --git a/debian/system/adbd.mk b/debian/system/adbd.mk
+index a3f88f169b9b..5e2c5ccaea30 100644
+--- a/debian/system/adbd.mk
++++ b/debian/system/adbd.mk
+@@ -109,6 +109,10 @@ LDFLAGS += -lsystemd
+ CPPFLAGS += -DHAVE_SYSTEMD
+ endif
+ 
++ifeq ($(ADBD_AUTH_UNLESS_DEBUGGABLE),1)
++CPPFLAGS += -DADBD_AUTH_UNLESS_DEBUGGABLE
++endif
++
+ STATIC_LIBS = \
+   debian/out/system/libadb.a \
+   debian/out/system/libcrypto_utils.a \
+diff --git a/packages/modules/adb/adb.cpp b/packages/modules/adb/adb.cpp
+index 78bbfb6df48f..6e753484971c 100644
+--- a/packages/modules/adb/adb.cpp
++++ b/packages/modules/adb/adb.cpp
+@@ -392,7 +392,7 @@ static void handle_new_connection(atransport* t, apacket* p) {
+         // we'll just not verify the client's certificate. This should be the
+         // first packet the client receives to indicate the new protocol.
+         send_tls_request(t);
+-    } else if (!auth_required) {
++    } else if (!adbd_connection_auth_required()) {
+         LOG(INFO) << "authentication not required";
+         handle_online(t);
+         send_connect(t);
+diff --git a/packages/modules/adb/adb_auth.h b/packages/modules/adb/adb_auth.h
+index 38312211f3ad..e23ad2b089c7 100644
+--- a/packages/modules/adb/adb_auth.h
++++ b/packages/modules/adb/adb_auth.h
+@@ -51,6 +51,10 @@ void adb_auth_tls_handshake(atransport* t);
+ extern bool auth_required;
+ extern bool socket_access_allowed;
+ 
++// Whether a connection made now must authenticate. auth_required is decided
++// once at startup; this can also depend on state that changes while adbd runs.
++bool adbd_connection_auth_required();
++
+ void adbd_auth_init();
+ void adbd_auth_verified(atransport *t);
+ 
+diff --git a/packages/modules/adb/daemon/auth.cpp b/packages/modules/adb/daemon/auth.cpp
+index 7df15aedd58a..2bb0fa65aad5 100644
+--- a/packages/modules/adb/daemon/auth.cpp
++++ b/packages/modules/adb/daemon/auth.cpp
+@@ -37,6 +37,7 @@
+ #include <adb/tls/adb_ca_list.h>
+ #include <adbd_auth.h>
+ #include <android-base/file.h>
++#include <log/log_properties.h>
+ #include <android-base/no_destructor.h>
+ #include <android-base/strings.h>
+ #include <crypto_utils/android_pubkey.h>
+@@ -157,6 +158,18 @@ static uint32_t transport_auth_id = 0;
+ bool auth_required = true;
+ bool socket_access_allowed = true;
+ 
++bool adbd_connection_auth_required() {
++#if !defined(__ANDROID__) && defined(ADBD_AUTH_UNLESS_DEBUGGABLE)
++    // Off Android there is no property service to relax auth_required at
++    // startup, and whether the build is debuggable can change while adbd runs
++    // (see LIBLOG_DEBUGGABLE_PROP_FILES), so decide per connection: a
++    // debuggable build accepts any host, and anything else authenticates.
++    return auth_required && !__android_log_is_debuggable();
++#else
++    return auth_required;
++#endif
++}
++
+ static void* transport_to_callback_arg(atransport* transport) {
+     uint32_t id = transport_auth_id++;
+     (*transports)[id] = transport->weak();
+@@ -196,7 +209,7 @@ static void IteratePublicKeys(std::function<bool(std::string_view public_key)> f
+ }
+ 
+ bssl::UniquePtr<STACK_OF(X509_NAME)> adbd_tls_client_ca_list() {
+-    if (!auth_required) {
++    if (!adbd_connection_auth_required()) {
+         return nullptr;
+     }
+ 
+@@ -390,7 +403,7 @@ void adbd_notify_framework_connected_key(atransport* t) {
+ }
+ 
+ int adbd_tls_verify_cert(X509_STORE_CTX* ctx, std::string* auth_key) {
+-    if (!auth_required) {
++    if (!adbd_connection_auth_required()) {
+         // Any key will do.
+         LOG(INFO) << __func__ << ": auth not required";
+         return 1;
+diff --git a/packages/modules/adb/daemon/main.cpp b/packages/modules/adb/daemon/main.cpp
+index a5b1d6b3e0eb..d309e235b947 100644
+--- a/packages/modules/adb/daemon/main.cpp
++++ b/packages/modules/adb/daemon/main.cpp
+@@ -313,7 +313,7 @@ int adbd_main(int server_port) {
+         auth_required = android::base::GetBoolProperty("ro.adb.secure", false);
+ #endif
+     }
+-#else
++#elif !defined(ADBD_AUTH_UNLESS_DEBUGGABLE)
+     auth_required = false;
+ #endif
+ 
diff --git a/meta-oe/recipes-devtools/android-tools/android-tools_35.0.2.bb b/meta-oe/recipes-devtools/android-tools/android-tools_35.0.2.bb
index d3d60b514721..1a939b503601 100644
--- a/meta-oe/recipes-devtools/android-tools/android-tools_35.0.2.bb
+++ b/meta-oe/recipes-devtools/android-tools/android-tools_35.0.2.bb
@@ -66,6 +66,7 @@ SRC_URI = "https://deb.debian.org/debian/pool/main/a/android-platform-tools/andr
            file://0019-adb-daemon-exit-after-adb-root-unroot-so-an-init-sup.patch \
            file://0020-adbd-signal-readiness-once-functionfs-is-serviced.patch \
            file://0021-liblog-optionally-read-ro.debuggable-from-build.prop.patch \
+           file://0022-adbd-optionally-require-authorization-unless-the-bui.patch \
            "
 
 SRC_URI[orig.md5sum] = "352376965cdef7bd7505d8fefdd43d50"
@@ -221,7 +222,8 @@ do_compile() {
 
     for tool in ${TOOLS_TO_BUILD}; do
         oe_runmake -f ${S}/debian/system/${tool}.mk -C ${S} \
-            ${@'HAVE_SYSTEMD=1' if bb.utils.contains('PACKAGECONFIG', 'systemd', True, False, d) else ''}
+            ${@'HAVE_SYSTEMD=1' if bb.utils.contains('PACKAGECONFIG', 'systemd', True, False, d) else ''} \
+            ${@'ADBD_AUTH_UNLESS_DEBUGGABLE=1' if bb.utils.contains('PACKAGECONFIG', 'auth-unless-debuggable', True, False, d) else ''}
     done
 }
 
@@ -277,4 +279,8 @@ PACKAGECONFIG[fs-config] = ""
 # build.prop format), so `adb root` is refused unless one of them sets
 # ro.debuggable=1. Off by default: every build is debuggable.
 PACKAGECONFIG[debuggable-prop] = ""
+# Require hosts to authenticate unless the build is debuggable, decided per
+# connection. Off by default, as in Debian: no host is asked for a key. Only
+# meaningful with debuggable-prop, without which every build is debuggable.
+PACKAGECONFIG[auth-unless-debuggable] = ""
 PACKAGECONFIG[systemd] = ",,systemd"
