Check G14 · execution surface family · severity HIGH · automatic · one of the 22 GitLab checks
The question this check asks: does this gitlab.com project carry build-time code that your editor or build tool will run before you have read it — a Rust build script, a checked-in build-tool binary, a CMake configure step, a test-collection hook? It is C14, the GitHub check, run unchanged on a project hosted at gitlab.com.
Where a project is hosted has no bearing on what its build does once the files are on your disk. Opening a Rust project in an editor runs its build.rs: rust-analyzer's own documentation states that proc macros and build scripts are executed by default. Gradle and Maven wrappers are checked-in JAR files that ./gradlew and ./mvnw execute on every build — binaries you did not compile, in a place nobody reads, and two weaponised ones were found in the MinecraftOnline project. CMake's execute_process() runs at configure time, and the CMake Tools extension can configure on open. And pytest executes conftest.py during collection, before a single test runs. Each of these is ordinary engineering; each is also a place where code runs without a decision from you — and a project cloned from gitlab.com is opened by the same editor with the same defaults.
G14 is C14 on a gitlab.com project: the same code, run on a snapshot RepoGates builds from gitlab.com's public API. The file list is one call — the recursive repository tree at per_page=10000, no clone; inkscape/inkscape's 7,182 entries arrive in 0.36 s. A full page is reported as truncated rather than read as complete, and a project with more than one page — twelve of the 100 most-starred, gitlab-org/gitlab among them at 136,997 entries — is a partial scan: the tree checks ran on the first page only, the verdict is cached briefly and retried, and it is never a clean PASS. On that list the check fires on five paths. Three at severity HIGH for 10 points: build.rs (“rust-analyzer runs build scripts on open”), gradle/wrapper/gradle-wrapper.jar (“checked-in JAR executed by ./gradlew”) and .mvn/wrapper/maven-wrapper.jar (the same for ./mvnw). Two at MEDIUM for 5 points: CMakeLists.txt (“execute_process at configure time”) and conftest.py (“executed at pytest collection”). A project that trips one HIGH scores 90, one MEDIUM 95; the badge stays green, the verdict is REVIEW, and the default personal policy warns. Nothing here blocks on its own. The execution-surface evidence note in the scoring table:
“28.8% of top-100 repos carry devcontainers — informative, not damning”
That note is GitHub's Phase 0 measurement. On 19 September 2026 the same code ran, anonymously, over the 100 most-starred gitlab.com projects: a wrapper JAR on 13, a CMakeLists.txt on 9, a build.rs on 2; fdroid/fdroidclient carries a Gradle wrapper, inkscape/inkscape CMake (REVIEW 79). Outside the hundred, gitlab-org/security-products/analyzers/semgrep — a four-segment subgroup path, 34 stars, measured the day before — carries a wrapper JAR inside its QA fixtures and scored REVIEW 82. The run as a whole came back 14 PASS / 84 REVIEW / 2 BLOCK, and the control — GitHub's 100 most-starred repositories, same engine, same day — 0 PASS / 96 REVIEW / 4 BLOCK. The REVIEW rate is the roster's, not GitLab's: on the largest, oldest, busiest projects the 22 flag execution surface that is ordinary there, and GitLab's top 100 is the milder of the two.
Where the verdict reaches you today: the API (GET /v1/gl/score/{path}), the MCP server (check_repo with platform="gl"), and the Claude Code plugin's preflight (a hook on Claude Code's Bash tool: it reads the command line, never a process), which turns a warning into an ask before a git clone https://gitlab.com/… line runs. The extension's board on gitlab.com pages is a later release.
Every Rust crate with a build script, every Gradle and Maven project (the wrapper is the recommended way to ship one), every CMake project, every Python project with shared test fixtures. That is most of four ecosystems, which is why the weights are 10 and 5 and the action is a warning; on gitlab.com's top 100 the wrapper JAR was the most common of the five, and every one of the 13 is, as far as a file list can tell, the wrapper Gradle published. The finding is a reminder of what will run when you open the folder; the settings below decide whether it does.
It sees names, not contents: a build.rs that generates bindings and one that downloads a payload are the same line here, and a genuine Gradle wrapper and a replaced one have the same path. Verifying the wrapper's checksum needs the bytes; a deep scan reads them. Other build systems — Makefiles, npm scripts, Bazel — are not on the list; setup.py has its own check. A .gitlab-ci.yml is build configuration too, and it is deliberately not a finding: pipelines run on push and on merge request, on GitLab's runners, never on clone or open. And the finding is on the verdict before the project reaches your machine; the build runs when you open or build it.
And RepoGates as a whole is a browser download gate and an answer an agent can ask for: it does not see git clone, package managers or curl — outside Claude Code with the RepoGates plugin, whose hook refuses a clone or install that names a blocked repository on the command line, before it runs.
RepoGates runs the same 22 checks on a gitlab.com project that it runs on a GitHub repository, from gitlab.com's public API, under the key gl/{namespace…}/{project}. What that API withholds from an anonymous caller — fork status, a user namespace's account age, and OpenSSF Scorecard, which does not cover gitlab.com — is listed as not checked, never assumed. A self-managed GitLab is another hostname and is not assessed. The repository's code is not read on this tier: a PASS means the provenance and the declared execution surface are clean.
Without installing anything: look at the project root on gitlab.com for build.rs, CMakeLists.txt and conftest.py, and under gradle/wrapper/ and .mvn/wrapper/ for a JAR. With curl against gitlab.com's API — one call for the whole tree, the project path URL-encoded so / becomes %2F:
curl -s 'https://gitlab.com/api/v4/projects/NAMESPACE%2FPROJECT/repository/tree?recursive=true&per_page=10000' | jq -r '.[].path' | grep -E '^(build\.rs|CMakeLists\.txt|conftest\.py)$|wrapper\.jar$'
Then turn the automatic execution off in your user settings — rust-analyzer.cargo.buildScripts.enable: false, rust-analyzer.procMacro.enable: false, cmake.configureOnOpen: false — and, for a wrapper JAR, compare its checksum with Gradle's published list before the first ./gradlew:
shasum -a 256 gradle/wrapper/gradle-wrapper.jar # compare with services.gradle.org/versions/all
Every Rust crate has a build.rs — does every one warn? Every one with a build.rs at the root, yes: 10 points and a warning, never a block, and gitlab.com changes nothing about it — the file runs on your machine, not on GitLab's. rust-analyzer's own documentation says build scripts and proc macros run by default, so opening the folder in an editor is running the file. Two user settings — rust-analyzer.cargo.buildScripts.enable and rust-analyzer.procMacro.enable set to false — make the warning moot for your machine. Two of the hundred most-starred gitlab.com projects carry one.
What is wrong with a Gradle wrapper? Nothing, when it is the wrapper Gradle published. It is a binary JAR committed to source that ./gradlew executes on every build, so a replaced one runs whatever it likes on every developer's machine — two weaponised wrappers were found in the MinecraftOnline project. Thirteen of the hundred most-starred gitlab.com projects carry a wrapper JAR, and a smaller one, gitlab-org/security-products/analyzers/semgrep, keeps it inside its QA fixtures, where nobody would think to look. Verify the JAR's checksum against Gradle's published list before the first ./gradlew.
Does RepoGates stop git clone of a gitlab.com project? In the browser, no: an extension cannot see a process outside it, and RepoGates does not see git clone, package managers or curl — outside Claude Code with the RepoGates plugin, whose hook refuses a clone or install that names a blocked repository on the command line, before it runs. These findings warn rather than block, so a clone of a project that carries one becomes an ask there, not a refusal. A browser gate for gitlab.com's own download links is a later release; the build runs when you open or build the project.
C14 Build scripts and wrapper JARs — the GitHub original · G15 Committed binaries — the wrapper JAR is one; so is anything else you cannot rebuild · G13 Editor and workspace config — the editor running things on trust · G16 Install scripts — code that runs at install rather than at build.
Add RepoGates to Chrome Pricing
Numbers on this page: the 100 most-starred gitlab.com projects and the 100 most-starred GitHub repositories, both measured 19 September 2026 through the same code as the verdict API; rust-analyzer documentation and the Gradle wrapper attack report as cited in the repository vetting standard; weights and actions from the product's scoring and policy tables.