diff --git a/src/knot/events/handlers/ds_push.c b/src/knot/events/handlers/ds_push.c
index 6bcaa92ef4733a268f74113eea439a06a2f4d838..f8559af7e230deb4cff2684e0f278f3ed84da479 100644
--- a/src/knot/events/handlers/ds_push.c
+++ b/src/knot/events/handlers/ds_push.c
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@
 
 struct ds_push_data {
 	const knot_dname_t *zone;
+	const knot_dname_t *parent_query;
 	knot_dname_t *parent_soa;
 	knot_rrset_t del_old_ds;
 	knot_rrset_t new_ds;
@@ -49,9 +50,10 @@ static int ds_push_begin(knot_layer_t *layer, void *params)
 
 static int parent_soa_produce(struct ds_push_data *data, knot_pkt_t *pkt)
 {
-	const knot_dname_t *query_name = knot_wire_next_label(data->zone, NULL);
+	assert(data->parent_query[0] != '\0');
+	data->parent_query = knot_wire_next_label(data->parent_query, NULL);
 
-	int ret = knot_pkt_put_question(pkt, query_name, KNOT_CLASS_IN, KNOT_RRTYPE_SOA);
+	int ret = knot_pkt_put_question(pkt, data->parent_query, KNOT_CLASS_IN, KNOT_RRTYPE_SOA);
 	if (ret != KNOT_EOK) {
 		return KNOT_STATE_FAIL;
 	}
@@ -123,18 +125,20 @@ static int ds_push_consume(knot_layer_t *layer, knot_pkt_t *pkt)
 	}
 
 	const knot_rrset_t *parent_soa = sect_soa(pkt, KNOT_ANSWER);
-	if (parent_soa == NULL) {
-		parent_soa = sect_soa(pkt, KNOT_AUTHORITY);
+	if (parent_soa != NULL) {
+		// parent SOA obtained, continue with DS push
+		data->parent_soa = knot_dname_copy(parent_soa->owner, NULL);
+		return KNOT_STATE_RESET;
 	}
-	if (parent_soa == NULL) {
+
+	if (data->parent_query[0] == '\0') {
+		// query for parent SOA systematicly fails
 		DS_PUSH_LOG(LOG_WARNING, data->zone, data->remote,
-		            "malformed message");
+		            "unable to query parent SOA");
 		return KNOT_STATE_FAIL;
 	}
 
-	data->parent_soa = knot_dname_copy(parent_soa->owner, NULL);
-
-	return KNOT_STATE_RESET;
+	return KNOT_STATE_RESET; // cut off one more label and re-query
 }
 
 static int ds_push_reset(knot_layer_t *layer)
@@ -170,6 +174,7 @@ static int send_ds_push(conf_t *conf, zone_t *zone,
 
 	struct ds_push_data data = {
 		.zone = zone->name,
+		.parent_query = zone->name,
 		.new_ds = zone_cds,
 		.remote = (struct sockaddr *)&parent->addr,
 	};
diff --git a/tests-extra/tests/dnssec/ds_push/data/com.zone b/tests-extra/tests/dnssec/ds_push/data/com.zone
index 34859ad30ceedf225a754e4ac78f928ccb8ad156..d340e010a8c9134a6fa6c94640233f185df8ee2a 100644
--- a/tests-extra/tests/dnssec/ds_push/data/com.zone
+++ b/tests-extra/tests/dnssec/ds_push/data/com.zone
@@ -4,3 +4,4 @@ $TTL 1200
 @ SOA ns admin 20110100 7 7 16 600
 ns AAAA ::0
 
+example.com. CNAME intentionally.disruptive.cname.
diff --git a/tests-extra/tests/dnssec/ds_push/data/example.com.zone b/tests-extra/tests/dnssec/ds_push/data/example.com.zone
deleted file mode 100644
index ecd27e06e967ddb34a7420fd99137c0eec1dbdb2..0000000000000000000000000000000000000000
--- a/tests-extra/tests/dnssec/ds_push/data/example.com.zone
+++ /dev/null
@@ -1,9 +0,0 @@
-example.com.        	3	SOA	dns1.example.com. hostmaster.example.com. 2010111227 21600 3600 604800 3
-example.com.        	0	NS	dns1.example.com.
-example.com.        	2	MX	10 mail.example.com.
-dns1.example.com.   	4	A	192.0.2.1
-dns1.example.com.   	3	AAAA	2001:db8::1
-foo.example.com.    	5	A	192.0.2.4
-mail.example.com.   	3	A	192.0.2.3
-mail.example.com.   	1	AAAA	2001:db8::3
-
diff --git a/tests-extra/tests/dnssec/ds_push/data/sub.example.com.zone b/tests-extra/tests/dnssec/ds_push/data/sub.example.com.zone
new file mode 100644
index 0000000000000000000000000000000000000000..28f75708dbb88f5dc2e08ba2ee5bd1382ad8e123
--- /dev/null
+++ b/tests-extra/tests/dnssec/ds_push/data/sub.example.com.zone
@@ -0,0 +1,9 @@
+sub.example.com.        	3	SOA	dns1 hostmaster 2010111227 21600 3600 604800 3
+sub.example.com.        	0	NS	dns1
+sub.example.com.        	2	MX	10 mail
+dns1   	4	A	192.0.2.1
+dns1   	3	AAAA	2001:db8::1
+foo    	5	A	192.0.2.4
+mail   	3	A	192.0.2.3
+mail   	1	AAAA	2001:db8::3
+
diff --git a/tests-extra/tests/dnssec/ds_push/test.py b/tests-extra/tests/dnssec/ds_push/test.py
index 9c3b2837ec28689410ad4f38880c65d2bb3d96ff..f09c686ef86a17ac914784e851141959a9e630d4 100644
--- a/tests-extra/tests/dnssec/ds_push/test.py
+++ b/tests-extra/tests/dnssec/ds_push/test.py
@@ -15,6 +15,8 @@ from dnstest.utils import *
 from dnstest.keys import Keymgr
 from dnstest.test import Test
 
+ZONE = "sub.example.com."
+
 def pregenerate_key(server, zone, alg):
     class a_class_with_name:
         def __init__(self, name):
@@ -25,16 +27,16 @@ def pregenerate_key(server, zone, alg):
 
 # check zone if keys are present and used for signing
 def check_zone(server, zone, dnskeys, dnskey_rrsigs, cdnskeys, soa_rrsigs, msg):
-    qdnskeys = server.dig("example.com", "DNSKEY", bufsize=4096)
+    qdnskeys = server.dig(ZONE, "DNSKEY", bufsize=4096)
     found_dnskeys = qdnskeys.count("DNSKEY")
 
-    qdnskeyrrsig = server.dig("example.com", "DNSKEY", dnssec=True, bufsize=4096)
+    qdnskeyrrsig = server.dig(ZONE, "DNSKEY", dnssec=True, bufsize=4096)
     found_rrsigs = qdnskeyrrsig.count("RRSIG")
 
-    qcdnskey = server.dig("example.com", "CDNSKEY", bufsize=4096)
+    qcdnskey = server.dig(ZONE, "CDNSKEY", bufsize=4096)
     found_cdnskeys = qcdnskey.count("CDNSKEY")
 
-    qsoa = server.dig("example.com", "SOA", dnssec=True, bufsize=4096)
+    qsoa = server.dig(ZONE, "SOA", dnssec=True, bufsize=4096)
     found_soa_rrsigs = qsoa.count("RRSIG")
 
     check_log("DNSKEYs: %d (expected %d)" % (found_dnskeys, dnskeys));
@@ -66,7 +68,7 @@ def check_zone(server, zone, dnskeys, dnskey_rrsigs, cdnskeys, soa_rrsigs, msg):
 def wait_for_rrsig_count(t, server, rrtype, rrsig_count, timeout):
     rtime = 0.0
     while True:
-        qdnskeyrrsig = server.dig("example.com", rrtype, dnssec=True, bufsize=4096)
+        qdnskeyrrsig = server.dig(ZONE, rrtype, dnssec=True, bufsize=4096)
         found_rrsigs = qdnskeyrrsig.count("RRSIG")
         if found_rrsigs == rrsig_count:
             break
@@ -78,7 +80,7 @@ def wait_for_rrsig_count(t, server, rrtype, rrsig_count, timeout):
 def wait_for_dnskey_count(t, server, dnskey_count, timeout):
     rtime = 0.0
     while True:
-        qdnskeyrrsig = server.dig("example.com", "DNSKEY", dnssec=True, bufsize=4096)
+        qdnskeyrrsig = server.dig(ZONE, "DNSKEY", dnssec=True, bufsize=4096)
         found_dnskeys = qdnskeyrrsig.count("DNSKEY")
         if found_dnskeys == dnskey_count:
             break
@@ -107,7 +109,7 @@ t.link(parent_zone, parent, ddns=True)
 parent.dnssec(parent_zone).enable = True
 
 child = t.server("knot")
-child_zone = t.zone("example.com.", storage=".")
+child_zone = t.zone(ZONE, storage=".")
 t.link(child_zone, child)
 
 child.zonefile_sync = 24 * 60 * 60
@@ -125,9 +127,6 @@ child.dnssec(child_zone).ds_push = parent
 child.dnssec(child_zone).ksk_shared = True
 child.dnssec(child_zone).cds_publish = "always"
 
-# parameters
-ZONE = "example.com."
-
 #t.start()
 t.generate_conf()
 parent.start()
@@ -140,7 +139,7 @@ t.sleep(5)
 pregenerate_key(child, child_zone, "ECDSAP256SHA256")
 watch_ksk_rollover(t, child, child_zone, 2, 2, 3, "KSK rollover")
 
-resp = parent.dig("example.com.", "DS")
+resp = parent.dig(ZONE, "DS")
 resp.check_count(1, rtype="DS")
 
 t.end()