diff --git a/fuzz/Makefile.am b/fuzz/Makefile.am
index cf5da3b0..d2af32c4 100644
--- a/fuzz/Makefile.am
+++ b/fuzz/Makefile.am
@@ -21,6 +21,8 @@ WGET_TESTS = \
  wget_robots_fuzzer$(EXEEXT) \
  wget_url_fuzzer$(EXEEXT)
 
+EXTRA_DIST = test-runner.sh
+
 if WITH_NTLM
   WGET_TESTS += wget_ntlm_fuzzer$(EXEEXT)
 endif
@@ -33,6 +35,7 @@ if FUZZING
 else
   AM_CPPFLAGS += -DTEST_RUN
   AM_TESTS_ENVIRONMENT = export VALGRIND_TESTS"=@VALGRIND_TESTS@";
+  LOG_COMPILER = $(top_srcdir)/fuzz/test-runner.sh
   TESTS = $(WGET_TESTS)
   check_PROGRAMS = $(WGET_TESTS)
   MAIN = main.c fuzzer.h
diff --git a/fuzz/main.c b/fuzz/main.c
index b6157cd4..26cfc99e 100644
--- a/fuzz/main.c
+++ b/fuzz/main.c
@@ -68,26 +68,9 @@ static int test_all_from(const char *dirname)
 
 int main(int argc, char **argv)
 {
-	// if VALGRIND testing is enabled, we have to call ourselves with valgrind checking
-	const char *valgrind = getenv("VALGRIND_TESTS");
 	const char *target;
 	size_t target_len;
 
-	if (!valgrind || !*valgrind || !strcmp(valgrind, "0")) {
-		// fallthrough
-	}
-	else if (!strcmp(valgrind, "1")) {
-		char cmd[strlen(argv[0]) + 256];
-
-		snprintf(cmd, sizeof(cmd), "VALGRIND_TESTS=\"\" valgrind --error-exitcode=301 --leak-check=yes --show-reachable=yes --track-origins=yes %s", argv[0]);
-		return system(cmd) != 0;
-	} else {
-		char cmd[strlen(valgrind) + strlen(argv[0]) + 32];
-
-		snprintf(cmd, sizeof(cmd), "VALGRIND_TESTS="" %s %s", valgrind, argv[0]);
-		return system(cmd) != 0;
-	}
-
 	if ((target = strrchr(argv[0], SLASH))) {
 		if (strrchr(target, '/'))
 			target = strrchr(target, '/');
diff --git a/fuzz/test-runner.sh b/fuzz/test-runner.sh
new file mode 100755
index 00000000..a29531b6
--- /dev/null
+++ b/fuzz/test-runner.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env sh
+
+WRAPPER=""
+
+if [ -n "$VALGRIND_TESTS" ]; then
+    WRAPPER="valgrind --error-exitcode=301 --leak-check=yes --show-reachable=yes --track-origins=yes"
+fi
+
+exec $WRAPPER "$@"