diff --git a/CHANGES b/CHANGES
index 542dfd5ff19acdc1899667d4f9eaf921d8aff975..88772d4492bf7bfddcaf46a5b5af45310bdb57f1 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,7 @@
 OpenLDAP 2.4 Change Log
 
 OpenLDAP 2.4.20 Engineering
+	Fixed liblber embedded NUL values in BerValues (ITS#6353)
 	Fixed liblber inverted LBER_USE_DER test (ITS#6348)
 	Fixed liblber to return failure on certain failures (ITS#6344)
 	Fixed libldap sasl buffer sizing (ITS#6327,ITS#6334)
diff --git a/include/lber.h b/include/lber.h
index 00ffa881d9b1a08207d28c9c2701cb38c1968ae2..6e1a905fe4c1041a0b2503da468dfd90cee91d8b 100644
--- a/include/lber.h
+++ b/include/lber.h
@@ -278,6 +278,7 @@ ber_get_stringb LDAP_P((
 
 #define	LBER_BV_ALLOC	0x01	/* allocate/copy result, otherwise in-place */
 #define	LBER_BV_NOTERM	0x02	/* omit NUL-terminator if parsing in-place */
+#define	LBER_BV_STRING	0x04	/* fail if berval contains embedded \0 */
 
 LBER_F( ber_tag_t )
 ber_get_stringbv LDAP_P((
diff --git a/libraries/liblber/decode.c b/libraries/liblber/decode.c
index 386f3761eefe9170c3a864d77eb9a7baded6860d..151a188f6ff63dcfc487dbe082cda12f919ac2b8 100644
--- a/libraries/liblber/decode.c
+++ b/libraries/liblber/decode.c
@@ -345,7 +345,7 @@ enum bgbvc { ChArray, BvArray, BvVec, BvOff };
  */
 typedef struct bgbvr {
 	const enum bgbvc choice;
-	const int alloc;	/* choice == BvOff ? 0 : LBER_ALLOC */
+	const int option;	/* (ALLOC unless BvOff) | (STRING if ChArray) */
 	ber_len_t siz;		/* input array element size, output count */
 	ber_len_t off;		/* BvOff offset to the struct berval */
 	void *result;
@@ -418,9 +418,9 @@ ber_get_stringbvl( BerElement *ber, bgbvr *b )
 
 	n = 0;
 	do {
-		tag = ber_get_stringbv( ber, &bv, b->alloc );
+		tag = ber_get_stringbv( ber, &bv, b->option );
 		if ( tag == LBER_DEFAULT ) {
-			goto nomem;
+			goto failed;
 		}
 
 		/* store my result */
@@ -436,7 +436,7 @@ ber_get_stringbvl( BerElement *ber, bgbvr *b )
 				ber->ber_memctx );
 			if ( !bvp ) {
 				ber_memfree_x( bv.bv_val, ber->ber_memctx );
-				goto nomem;
+				goto failed;
 			}
 			res.bv[n] = bvp;
 			*bvp = bv;
@@ -449,8 +449,8 @@ ber_get_stringbvl( BerElement *ber, bgbvr *b )
 	} while (++n < i);
 	return tag;
 
-nomem:
-	if (b->choice != BvOff) {	/* BvOff does not have b->alloc set */
+failed:
+	if (b->choice != BvOff) { /* BvOff does not have LBER_BV_ALLOC set */
 		while (--n >= 0) {
 			switch(b->choice) {
 			case ChArray:
@@ -480,9 +480,11 @@ ber_get_stringbv( BerElement *ber, struct berval *bv, int option )
 	char		*data;
 
 	tag = ber_skip_element( ber, bv );
-	if ( tag == LBER_DEFAULT ) {
+	if ( tag == LBER_DEFAULT ||
+		(( option & LBER_BV_STRING ) && memchr( bv->bv_val, 0, bv->bv_len )))
+	{
 		bv->bv_val = NULL;
-		return tag;
+		return LBER_DEFAULT;
 	}
 
 	data = bv->bv_val;
@@ -516,6 +518,11 @@ ber_get_stringbv_null( BerElement *ber, struct berval *bv, int option )
 		return tag;
 	}
 
+	if (( option & LBER_BV_STRING ) && memchr( bv->bv_val, 0, bv->bv_len )) {
+		bv->bv_val = NULL;
+		return LBER_DEFAULT;
+	}
+
 	data = bv->bv_val;
 	if ( option & LBER_BV_ALLOC ) {
 		bv->bv_val = (char *) ber_memalloc_x( bv->bv_len + 1,
@@ -541,7 +548,7 @@ ber_get_stringa( BerElement *ber, char **buf )
 
 	assert( buf != NULL );
 
-	tag = ber_get_stringbv( ber, &bv, LBER_BV_ALLOC );
+	tag = ber_get_stringbv( ber, &bv, LBER_BV_ALLOC | LBER_BV_STRING );
 	*buf = bv.bv_val;
 
 	return tag;
@@ -555,7 +562,7 @@ ber_get_stringa_null( BerElement *ber, char **buf )
 
 	assert( buf != NULL );
 
-	tag = ber_get_stringbv_null( ber, &bv, LBER_BV_ALLOC );
+	tag = ber_get_stringbv_null( ber, &bv, LBER_BV_ALLOC | LBER_BV_STRING );
 	*buf = bv.bv_val;
 
 	return tag;
@@ -608,6 +615,10 @@ ber_get_bitstringa(
 		goto fail;
 	}
 
+	if ( memchr( data.bv_val, 0, data.bv_len )) {
+		goto fail;
+	}
+
 	*buf = (char *) ber_memalloc_x( data.bv_len, ber->ber_memctx );
 	if ( *buf == NULL ) {
 		return LBER_DEFAULT;
@@ -811,7 +822,7 @@ ber_scanf ( BerElement *ber,
 		case 'v':	/* sequence of strings */
 		{
 			bgbvr cookie = {
-				ChArray, LBER_BV_ALLOC, sizeof( char * )
+				ChArray, LBER_BV_ALLOC | LBER_BV_STRING, sizeof( char * )
 			};
 			rc = ber_get_stringbvl( ber, &cookie );
 			*(va_arg( ap, char *** )) = cookie.result;