diff --git a/archive.c b/archive.c
index 2ae740a71e6..164bbd014a8 100644
--- a/archive.c
+++ b/archive.c
@@ -247,7 +247,8 @@ static void parse_pathspec_arg(const char **pathspec,
 }
 
 static void parse_treeish_arg(const char **argv,
-		struct archiver_args *ar_args, const char *prefix)
+		struct archiver_args *ar_args, const char *prefix,
+		int remote)
 {
 	const char *name = argv[0];
 	const unsigned char *commit_sha1;
@@ -256,8 +257,17 @@ static void parse_treeish_arg(const char **argv,
 	const struct commit *commit;
 	unsigned char sha1[20];
 
-	if (get_sha1(name, sha1))
-		die("Not a valid object name");
+	/* Remotes are only allowed to fetch actual refs */
+	if (remote) {
+		char *ref = NULL;
+		if (!dwim_ref(name, strlen(name), sha1, &ref))
+			die("no such ref: %s", name);
+		free(ref);
+	}
+	else {
+		if (get_sha1(name, sha1))
+			die("Not a valid object name");
+	}
 
 	commit = lookup_commit_reference_gently(sha1, 1);
 	if (commit) {
@@ -414,7 +424,7 @@ int write_archive(int argc, const char **argv, const char *prefix,
 		setup_git_directory();
 	}
 
-	parse_treeish_arg(argv, &args, prefix);
+	parse_treeish_arg(argv, &args, prefix, remote);
 	parse_pathspec_arg(argv + 1, &args);
 
 	return ar->write_archive(ar, &args);
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index d9068981f84..c05c676ca20 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -242,6 +242,14 @@ test_expect_success \
     'git archive --list outside of a git repo' \
     'GIT_DIR=some/non-existing/directory git archive --list'
 
+test_expect_success 'clients cannot access unreachable commits' '
+	test_commit unreachable &&
+	sha1=`git rev-parse HEAD` &&
+	git reset --hard HEAD^ &&
+	git archive $sha1 >remote.tar &&
+	test_must_fail git archive --remote=. $sha1 >remote.tar
+'
+
 test_expect_success 'git-archive --prefix=olde-' '
 	git archive --prefix=olde- >h.tar HEAD &&
 	(