diff --git a/.gitlab/pipeline/check.yml b/.gitlab/pipeline/check.yml
index f95bd224fb483ac7ac94c419998d4dab4beb161e..7d98b9cc71c1a592ac17d31e6101b381633a58ad 100644
--- a/.gitlab/pipeline/check.yml
+++ b/.gitlab/pipeline/check.yml
@@ -65,11 +65,7 @@ test-rust-features:
     - .kubernetes-env
     - .test-refs-no-trigger-prs-only
   script:
-    - git clone
-      --depth=1
-      --branch="master"
-      https://github.com/paritytech/pipeline-scripts
-    - bash ./pipeline-scripts/rust-features.sh .
+    - bash .gitlab/rust-features.sh .
 
 job-starter:
   stage: check
diff --git a/.gitlab/rust-features.sh b/.gitlab/rust-features.sh
new file mode 100755
index 0000000000000000000000000000000000000000..c0ac192a6ec69ba16abb3bad2ec49de7e9cebb61
--- /dev/null
+++ b/.gitlab/rust-features.sh
@@ -0,0 +1,87 @@
+#!/usr/bin/env bash
+
+##############################################################################
+#
+# This script checks that crates to not carelessly enable features that
+# should stay disabled. It's important to check that since features
+# are used to gate specific functionality which should only be enabled
+# when the feature is explicitly enabled.
+#
+# Invocation scheme:
+# 	./rust-features.sh <CARGO-ROOT-PATH>
+#
+# Example:
+# 	./rust-features.sh path/to/substrate
+#
+# The steps of this script:
+#   1. Check that all required dependencies are installed.
+#   2. Check that all rules are fullfilled for the whole workspace. If not:
+#   4. Check all crates to find the offending ones.
+#   5. Print all offending crates and exit with code 1.
+#
+##############################################################################
+
+set -eu
+
+# Check that cargo and grep are installed - otherwise abort.
+command -v cargo >/dev/null 2>&1 || { echo >&2 "cargo is required but not installed. Aborting."; exit 1; }
+command -v grep >/dev/null 2>&1 || { echo >&2 "grep is required but not installed. Aborting."; exit 1; }
+
+# Enter the workspace root folder.
+cd "$1"
+echo "Workspace root is $PWD"
+
+function main() {
+	feature_does_not_imply 'default' 'runtime-benchmarks'
+	feature_does_not_imply 'std' 'runtime-benchmarks'
+	feature_does_not_imply 'default' 'try-runtime'
+	feature_does_not_imply 'std' 'try-runtime'
+}
+
+# Accepts two feature names as arguments.
+# Checks that the first feature does not imply the second one.
+function feature_does_not_imply() {
+	ENABLED=$1
+	STAYS_DISABLED=$2
+	echo "📏 Checking that $ENABLED does not imply $STAYS_DISABLED ..."
+
+	# Check if the forbidden feature is enabled anywhere in the workspace.
+	# But only check "normal" dependencies, so no "dev" or "build" dependencies.
+	if cargo tree --no-default-features --locked --workspace -e features,normal --features "$ENABLED" | grep -qF "feature \"$STAYS_DISABLED\""; then
+		echo "❌ $ENABLED implies $STAYS_DISABLED in the workspace"
+	else
+		echo "✅ $ENABLED does not imply $STAYS_DISABLED in the workspace"
+		return
+	fi
+
+	# Find all Cargo.toml files but exclude the root one since we already know that it is broken.
+	CARGOS=`find . -name Cargo.toml -not -path ./Cargo.toml`
+	NUM_CRATES=`echo "$CARGOS" | wc -l`
+	FAILED=0
+	PASSED=0
+	echo "🔍 Checking all $NUM_CRATES crates - this takes some time."
+
+	for CARGO in $CARGOS; do
+		OUTPUT=$(cargo tree --no-default-features --locked --offline -e features,normal --features $ENABLED --manifest-path $CARGO 2>&1 || true)
+
+		if echo "$OUTPUT" | grep -qF "not supported for packages in this workspace"; then
+			# This case just means that the pallet does not support the
+			# requested feature which is fine.
+			PASSED=$((PASSED+1))
+		elif echo "$OUTPUT" | grep -qF "feature \"$STAYS_DISABLED\""; then
+			echo "❌ Violation in $CARGO by dependency:"
+			# Best effort hint for which dependency needs to be fixed.
+			echo "$OUTPUT" | grep -wF "feature \"$STAYS_DISABLED\"" | head -n 1
+			FAILED=$((FAILED+1))
+		else
+			PASSED=$((PASSED+1))
+		fi
+	done
+
+	echo "Checked $NUM_CRATES crates in total of which $FAILED failed and $PASSED passed."
+	echo "Exiting with code 1"
+	exit 1
+}
+
+main "$@"
+