diff --git a/build/fuzzing/fuzzer.gni b/build/fuzzing/fuzzer.gni
index 9049b53dfea14b944124c81ccbc83b6441174ba6..ac30e113e4316716b44e5f4d489f219dd26c9cb2 100644
--- a/build/fuzzing/fuzzer.gni
+++ b/build/fuzzing/fuzzer.gni
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/host.gni")
 import("//build/package.gni")
 
 # TODO(aarongreen): SEC-224.  Add tests to catch fuzzer building/packaging
@@ -204,9 +205,16 @@ template("fuzz_package") {
     ]
   }
 
+  if (defined(invoker.fuzz_host)) {
+    fuzz_host = invoker.fuzz_host
+  } else {
+    fuzz_host = false
+  }
+
   # Collect the selected fuzz targets listed in this package based on the
   # variants selected in args.gn and filtered by the package's list of
   # supported sanitizers.
+  selected = false
   selected_targets = []
   foreach(fuzz_target, invoker.targets) {
     selected = false
@@ -223,9 +231,6 @@ template("fuzz_package") {
         }
       }
     }
-
-    # When no variants are present, `selected` is unused.
-    not_needed([ "selected" ])
   }
 
   # Assemble the Fuchsia package
@@ -239,12 +244,14 @@ template("fuzz_package") {
             foreach(selected_target, selected_targets) {
               fuzz_targets += [ get_label_info(selected_target, "name") ]
             }
+            fuzz_host = fuzz_host
           },
         ]
         if (defined(invoker.metadata)) {
           forward_variables_from(invoker.metadata, "*", [ "fuzz_spec" ])
         }
       }
+      deps = []
       components = []
       forward_variables_from(invoker, [ "visibility" ])
       forward_variables_from(invoker,
@@ -259,19 +266,32 @@ template("fuzz_package") {
       foreach(selected_target, selected_targets) {
         components += [ "${selected_target}_component" ]
       }
+      if (fuzz_host) {
+        deps += [ ":host_${target_name}" ]
+      }
+    }
+
+    # Treat host fuzzers as tools. If we get to the point of having name
+    # collisions, we'll need to extend `install_host_tools` to allow copying to
+    # specific subdirectories of `host_tools_dir`
+    if (fuzz_host) {
+      install_host_tools("host_${target_name}") {
+        testonly = true
+        deps = selected_targets
+        outputs = []
+        foreach(target, selected_targets) {
+          outputs += [ get_label_info(target, "name") ]
+        }
+      }
     }
   } else {
     # Dummy package for non-fuzzed builds
     group(target_name) {
     }
     not_needed(invoker, "*")
-  }
-
-  # Create a (possibly empty) target for host fuzzers
-  group("host_${target_name}") {
-    testonly = true
-    if (defined(invoker.fuzz_host) && invoker.fuzz_host) {
-      deps = selected_targets
-    }
+    not_needed([
+                 "fuzz_host",
+                 "selected",
+               ])
   }
 }
diff --git a/garnet/packages/tests/BUILD.gn b/garnet/packages/tests/BUILD.gn
index 1bfba83658ea9e562e5baba1b3c0182fb0d4a74f..33c46338a7e4ba4238a04b3ecb405289c134329f 100644
--- a/garnet/packages/tests/BUILD.gn
+++ b/garnet/packages/tests/BUILD.gn
@@ -578,7 +578,6 @@ group("overnet") {
   public_deps = [
     # FIXME(FLK-187, FLK-188): Disabled because of flakes.
     # "//src/connectivity/overnet/examples:overnet_examples_tests",
-    "//src/connectivity/overnet/lib:host_overnet_fuzzers",
     "//src/connectivity/overnet/lib:overnet_fuzzers",
     "//src/connectivity/overnet/lib:overnet_tests",
     "//src/connectivity/overnet/lib:overnet_unittests($host_toolchain)",
diff --git a/src/BUILD.gn b/src/BUILD.gn
index 8ef3c9e28beca470fe43687296ae585e52add5ba..cc5503efcfef270659f368684a4af02e4515b605 100644
--- a/src/BUILD.gn
+++ b/src/BUILD.gn
@@ -29,6 +29,7 @@ group("tests") {
     "cobalt:tests",
     "connectivity:tests",
     "developer:tests",
+    "fuzzing:tests",
     "identity:tests",
     "ledger:tests",
     "lib:tests",
diff --git a/src/fuzzing/BUILD.gn b/src/fuzzing/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..e2c7b803428112421b7e0f97a7f6dfd53170ab56
--- /dev/null
+++ b/src/fuzzing/BUILD.gn
@@ -0,0 +1,24 @@
+# Copyright 2019 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/go/go_library.gni")
+import("//build/go/go_test.gni")
+
+group("tests") {
+  testonly = true
+  public_deps = [
+    ":host_fuzzers_test($host_toolchain)",
+  ]
+}
+
+go_library("host_fuzzers_test_lib") {
+  name = "fuzzing"
+}
+
+go_test("host_fuzzers_test") {
+  gopackage = "fuzzing"
+  deps = [
+    ":host_fuzzers_test_lib",
+  ]
+}
diff --git a/src/fuzzing/OWNERS b/src/fuzzing/OWNERS
new file mode 100644
index 0000000000000000000000000000000000000000..4e1e62c26b879e3b2888540b45f06d01248ecba7
--- /dev/null
+++ b/src/fuzzing/OWNERS
@@ -0,0 +1,3 @@
+aarongreen@google.com
+flowerhack@google.com
+mvanotti@google.com
diff --git a/src/fuzzing/host_test.go b/src/fuzzing/host_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..96e4e80c41120261dc45929e1928138b838e120d
--- /dev/null
+++ b/src/fuzzing/host_test.go
@@ -0,0 +1,91 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package fuzzing
+
+import (
+	"encoding/json"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path"
+	"path/filepath"
+	"testing"
+)
+
+// Created by `fuzz_package` in //build/fuzzing/fuzzer.gni
+type FuzzSpec struct {
+	Host    bool     `json:"fuzz_host"`
+	Package string   `json:"fuzz_package"`
+	Targets []string `json:"fuzz_targets"`
+}
+
+func TestHostFuzzers(t *testing.T) {
+	// Search the build directory structure for host variant fuzzer builds.
+	// This is necessarily sensitive to the layout of the build directory and
+	// will need to be updated if the host tests are moved or the host fuzzer
+	// builds' names change.
+	testBin, err := os.Executable()
+	if err != nil {
+		t.Fatalf("Failed to determine executable path: %v", err)
+	}
+	fxBuildDir := path.Dir(path.Dir(testBin))
+
+	// Find the fuzzers that should have been built for host.
+	jsonPath := path.Join(fxBuildDir, "fuzzers.json")
+	_, err = os.Stat(jsonPath)
+	if err != nil && os.IsNotExist(err) {
+		t.SkipNow()
+	}
+	jsonFile, err := os.Open(jsonPath)
+	if err != nil {
+		t.Fatalf("Failed to find fuzzer.json: %v", err)
+	}
+	defer jsonFile.Close()
+
+	jsonData, err := ioutil.ReadAll(jsonFile)
+	if err != nil {
+		t.Fatalf("Failed to read fuzzer.json: %v", err)
+	}
+
+	var specs []FuzzSpec
+	err = json.Unmarshal(jsonData, &specs)
+	if err != nil {
+		t.Fatalf("Failed to parse fuzzer.json: %v", err)
+	}
+	fuzzers := []string{}
+	for _, spec := range specs {
+		if spec.Host {
+			fuzzers = append(fuzzers, spec.Targets...)
+		}
+	}
+
+	// Create a empty file to act as a single input to each fuzzer.
+	variants, err := filepath.Glob(path.Join(fxBuildDir, "host_*-fuzzer"))
+	if err != nil {
+		t.Fatalf("Failed to glob host fuzzer build directories: %v", err)
+	}
+	if len(variants) == 0 {
+		t.SkipNow()
+	}
+	tempFile, err := ioutil.TempFile("", "empty.input")
+	if err != nil {
+		t.Fatalf("Failed to create empty input: %v", err)
+	}
+	tempName := tempFile.Name()
+	tempFile.Close()
+	defer os.Remove(tempName)
+
+	// Check that each fuzzer runs and exits cleanly.
+	for _, variant := range variants {
+		for _, fuzzer := range fuzzers {
+			cmd := exec.Command(path.Join(variant, fuzzer), tempName)
+			output, err := cmd.CombinedOutput()
+			if err != nil {
+				t.Errorf("Failed to run %s: %v", fuzzer, err)
+			}
+			t.Log(string(output[:]))
+		}
+	}
+}