diff --git a/substrate/utils/wasm-builder/README.md b/substrate/utils/wasm-builder/README.md
index 3868faf1acab5a1e1c4f50d4671073f658d82cf7..547468c7ca11d960b1ad62f26954ec7fc087b047 100644
--- a/substrate/utils/wasm-builder/README.md
+++ b/substrate/utils/wasm-builder/README.md
@@ -64,6 +64,7 @@ By using environment variables, you can configure which Wasm binaries are built
                            to be absolute.
 - `WASM_BUILD_TOOLCHAIN` - The toolchain that should be used to build the Wasm binaries. The
                            format needs to be the same as used by cargo, e.g. `nightly-2020-02-20`.
+- `CARGO_NET_OFFLINE` - If `true`, `--offline` will be passed to all processes launched to prevent network access. Useful in offline environments.
 
 Each project can be skipped individually by using the environment variable `SKIP_PROJECT_NAME_WASM_BUILD`.
 Where `PROJECT_NAME` needs to be replaced by the name of the cargo project, e.g. `node-runtime` will
diff --git a/substrate/utils/wasm-builder/src/lib.rs b/substrate/utils/wasm-builder/src/lib.rs
index 6a7f0d7ca3cd5672d83937729f03908eb140e7b5..919290655368b1872102ed469d44d683aee43118 100644
--- a/substrate/utils/wasm-builder/src/lib.rs
+++ b/substrate/utils/wasm-builder/src/lib.rs
@@ -87,6 +87,8 @@
 //!   required as we walk up from the target directory until we find a `Cargo.toml`. If the target
 //!   directory is changed for the build, this environment variable can be used to point to the
 //!   actual workspace.
+//! - `CARGO_NET_OFFLINE` - If `true`, `--offline` will be passed to all processes launched to
+//!   prevent network access. Useful in offline environments.
 //!
 //! Each project can be skipped individually by using the environment variable
 //! `SKIP_PROJECT_NAME_WASM_BUILD`. Where `PROJECT_NAME` needs to be replaced by the name of the
@@ -119,6 +121,9 @@ pub use builder::{WasmBuilder, WasmBuilderSelectProject};
 /// Environment variable that tells us to skip building the wasm binary.
 const SKIP_BUILD_ENV: &str = "SKIP_WASM_BUILD";
 
+/// Environment variable that tells us whether we should avoid network requests
+const OFFLINE: &str = "CARGO_NET_OFFLINE";
+
 /// Environment variable to force a certain build type when building the wasm binary.
 /// Expects "debug", "release" or "production" as value.
 ///
diff --git a/substrate/utils/wasm-builder/src/wasm_project.rs b/substrate/utils/wasm-builder/src/wasm_project.rs
index be84f2fecfb53c4c4c548f6679986c5b6dc85fea..197c1d1b220bbcf5c4589b28490057f1c5a09b5d 100644
--- a/substrate/utils/wasm-builder/src/wasm_project.rs
+++ b/substrate/utils/wasm-builder/src/wasm_project.rs
@@ -15,7 +15,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-use crate::{write_file_if_changed, CargoCommandVersioned};
+use crate::{write_file_if_changed, CargoCommandVersioned, OFFLINE};
 
 use build_helper::rerun_if_changed;
 use cargo_metadata::{CargoOpt, Metadata, MetadataCommand};
@@ -88,12 +88,12 @@ fn crate_metadata(cargo_manifest: &Path) -> Metadata {
 		cargo_manifest.to_path_buf()
 	};
 
-	let crate_metadata = MetadataCommand::new()
-		.manifest_path(cargo_manifest)
-		.features(CargoOpt::AllFeatures)
+	let mut crate_metadata_command = create_metadata_command(cargo_manifest);
+	crate_metadata_command.features(CargoOpt::AllFeatures);
+
+	let crate_metadata = crate_metadata_command
 		.exec()
 		.expect("`cargo metadata` can not fail on project `Cargo.toml`; qed");
-
 	// If the `Cargo.lock` didn't exist, we need to remove it after
 	// calling `cargo metadata`. This is required to ensure that we don't change
 	// the build directory outside of the `target` folder. Commands like
@@ -593,6 +593,11 @@ impl Profile {
 	}
 }
 
+/// Check environment whether we should build without network
+fn offline_build() -> bool {
+	env::var(OFFLINE).map_or(false, |v| v == "true")
+}
+
 /// Build the project to create the WASM binary.
 fn build_project(
 	project: &Path,
@@ -631,6 +636,10 @@ fn build_project(
 	build_cmd.arg("--profile");
 	build_cmd.arg(profile.name());
 
+	if offline_build() {
+		build_cmd.arg("--offline");
+	}
+
 	println!("{}", colorize_info_message("Information that should be included in a bug report."));
 	println!("{} {:?}", colorize_info_message("Executing build command:"), build_cmd);
 	println!("{} {}", colorize_info_message("Using rustc version:"), cargo_cmd.rustc_version());
@@ -751,6 +760,16 @@ impl<'a> Deref for DeduplicatePackage<'a> {
 	}
 }
 
+fn create_metadata_command(path: impl Into<PathBuf>) -> MetadataCommand {
+	let mut metadata_command = MetadataCommand::new();
+	metadata_command.manifest_path(path);
+
+	if offline_build() {
+		metadata_command.other_options(vec!["--offline".to_owned()]);
+	}
+	metadata_command
+}
+
 /// Generate the `rerun-if-changed` instructions for cargo to make sure that the WASM binary is
 /// rebuilt when needed.
 fn generate_rerun_if_changed_instructions(
@@ -765,8 +784,7 @@ fn generate_rerun_if_changed_instructions(
 		rerun_if_changed(cargo_lock);
 	}
 
-	let metadata = MetadataCommand::new()
-		.manifest_path(project_folder.join("Cargo.toml"))
+	let metadata = create_metadata_command(project_folder.join("Cargo.toml"))
 		.exec()
 		.expect("`cargo metadata` can not fail!");