diff --git a/Makefile.dep b/Makefile.dep
index 3cecda907ee9492dcca651517b7bdbccd6fedd3e..e324203adeacf885f96a750fbfac775d0aa68a80 100644
--- a/Makefile.dep
+++ b/Makefile.dep
@@ -689,6 +689,7 @@ endif
 
 ifneq (,$(filter sock_dns,$(USEMODULE)))
   USEMODULE += sock_util
+  USEMODULE += posix
 endif
 
 ifneq (,$(filter sock_util,$(USEMODULE)))
diff --git a/sys/include/net/dns.h b/sys/include/net/dns.h
new file mode 100644
index 0000000000000000000000000000000000000000..09ee148e16f072c5d5cdb7cd5c870e9d3b658c04
--- /dev/null
+++ b/sys/include/net/dns.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2019 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @defgroup    net_dns DNS defines
+ * @ingroup     net
+ * @brief       Generic DNS values
+ * @{
+ *
+ * @file
+ * @brief   Generic DNS values
+ *
+ * @author  Martine Lenders <m.lenders@fu-berlin.de>
+ */
+#ifndef NET_DNS_H
+#define NET_DNS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @name    Field lengths
+ * @{
+ */
+#define RR_TYPE_LENGTH      (2U)
+#define RR_CLASS_LENGTH     (2U)
+#define RR_TTL_LENGTH       (4U)
+#define RR_RDLENGTH_LENGTH  (2U)
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NET_DNS_H */
+/** @} */
diff --git a/sys/net/application_layer/dns/dns.c b/sys/net/application_layer/dns/dns.c
index adef0df244ac69ce76d12b9aaa5310c966f7f5ae..639b30f5113cd2bb8a4d1250a763e83a69007c12 100644
--- a/sys/net/application_layer/dns/dns.c
+++ b/sys/net/application_layer/dns/dns.c
@@ -15,9 +15,11 @@
  * @}
  */
 
+#include <arpa/inet.h>
 #include <string.h>
 #include <stdio.h>
 
+#include "net/dns.h"
 #include "net/sock/udp.h"
 #include "net/sock/dns.h"
 
@@ -73,55 +75,91 @@ static unsigned _get_short(uint8_t *buf)
     return _tmp;
 }
 
-static size_t _skip_hostname(uint8_t *buf)
+static ssize_t _skip_hostname(const uint8_t *buf, size_t len, uint8_t *bufpos)
 {
-    uint8_t *bufpos = buf;
+    const uint8_t *buflim = buf + len;
+    unsigned res = 0;
 
+    if (bufpos >= buflim) {
+        /* out-of-bound */
+        return -EBADMSG;
+    }
     /* handle DNS Message Compression */
     if (*bufpos >= 192) {
+        if ((bufpos + 2) >= buflim) {
+            return -EBADMSG;
+        }
         return 2;
     }
 
-    while(*bufpos) {
-        bufpos += *bufpos + 1;
+    while (bufpos[res]) {
+        res += bufpos[res] + 1;
+        if ((&bufpos[res]) >= buflim) {
+            /* out-of-bound */
+            return -EBADMSG;
+        }
     }
-    return (bufpos - buf + 1);
+    return res + 1;
 }
 
 static int _parse_dns_reply(uint8_t *buf, size_t len, void* addr_out, int family)
 {
+    const uint8_t *buflim = buf + len;
     sock_dns_hdr_t *hdr = (sock_dns_hdr_t*) buf;
     uint8_t *bufpos = buf + sizeof(*hdr);
 
     /* skip all queries that are part of the reply */
     for (unsigned n = 0; n < ntohs(hdr->qdcount); n++) {
-        bufpos += _skip_hostname(bufpos);
-        bufpos += 4;    /* skip type and class of query */
+        ssize_t tmp = _skip_hostname(buf, len, bufpos);
+        if (tmp < 0) {
+            return tmp;
+        }
+        bufpos += tmp;
+        /* skip type and class of query */
+        bufpos += (RR_TYPE_LENGTH + RR_CLASS_LENGTH);
     }
 
     for (unsigned n = 0; n < ntohs(hdr->ancount); n++) {
-        bufpos += _skip_hostname(bufpos);
+        ssize_t tmp = _skip_hostname(buf, len, bufpos);
+        if (tmp < 0) {
+            return tmp;
+        }
+        bufpos += tmp;
+        if ((bufpos + RR_TYPE_LENGTH + RR_CLASS_LENGTH + RR_TTL_LENGTH) >= buflim) {
+            return -EBADMSG;
+        }
         uint16_t _type = ntohs(_get_short(bufpos));
-        bufpos += 2;
+        bufpos += RR_TYPE_LENGTH;
         uint16_t class = ntohs(_get_short(bufpos));
-        bufpos += 2;
-        bufpos += 4; /* skip ttl */
+        bufpos += RR_CLASS_LENGTH;
+        bufpos += RR_TTL_LENGTH; /* skip ttl */
 
         unsigned addrlen = ntohs(_get_short(bufpos));
-        bufpos += 2;
-        if ((bufpos + addrlen) > (buf + len)) {
-            return -EBADMSG;
-        }
-
         /* skip unwanted answers */
         if ((class != DNS_CLASS_IN) ||
                 ((_type == DNS_TYPE_A) && (family == AF_INET6)) ||
                 ((_type == DNS_TYPE_AAAA) && (family == AF_INET)) ||
                 ! ((_type == DNS_TYPE_A) || ((_type == DNS_TYPE_AAAA))
                     )) {
+            if (addrlen > len) {
+                /* buffer wraps around memory space */
+                return -EBADMSG;
+            }
             bufpos += addrlen;
+            /* other out-of-bound is checked in `_skip_hostname()` at start of
+             * loop */
             continue;
         }
+        if (((addrlen != INADDRSZ) && (family == AF_INET)) ||
+            ((addrlen != IN6ADDRSZ) && (family == AF_INET6)) ||
+            ((addrlen != IN6ADDRSZ) && (addrlen != INADDRSZ) &&
+             (family == AF_UNSPEC))) {
+            return -EBADMSG;
+        }
+        bufpos += RR_RDLENGTH_LENGTH;
+        if ((bufpos + addrlen) >= buflim) {
+            return -EBADMSG;
+        }
 
         memcpy(addr_out, bufpos, addrlen);
         return addrlen;
@@ -174,7 +212,6 @@ int sock_dns_query(const char *domain_name, void *addr_out, int family)
 
     ssize_t res = sock_udp_create(&sock_dns, NULL, &sock_dns_server, 0);
     if (res) {
-            puts("a");
         goto out;
     }