Simple security layer for GitLab Runner using a pre-build hook to restrict which users and projects are allowed to run CI jobs.
The runner will fetch a remote allowlist configuration and validate:
GITLAB_USER_IDCI_PROJECT_ID
If the user or project is not listed, the job will fail immediately before the build starts.
- GitLab Runner executes
pre-build.shbefore running the CI job. - The script downloads a remote configuration (
allowed-list.conf). - The configuration defines:
- allowed GitLab user IDs
- allowed project IDs
- The script checks:
GITLAB_USER_IDCI_PROJECT_ID
- If either is not allowed → the job exits with error.
.
├── allowed-list.conf
└── pre-build.sh
Contains the allowlist configuration.
Example:
ALLOWED_USER_IDS=(
7
8
64
)
ALLOWED_PROJECT_IDS=(
632
718
830
)You can store this file anywhere (GitHub Gist, internal repo, etc) and load it remotely.
GitLab Runner hook that:
- Downloads the configuration
- Loads the allowlist
- Validates the pipeline context
Key logic:
CONFIG_URL="https://.../allowed-list.conf"
curl ... "${CONFIG_URL}" -o "${TMP_FILE}"
source "${TMP_FILE}"Validation examples:
if [[ ! " ${ALLOWED_USER_IDS[@]} " =~ " ${GITLAB_USER_ID} " ]]; then
echo "ERROR: User is not authorized"
exit 1
fiExample location:
/opt/gitlab-runner/hooks/pre-build.sh
Make it executable:
chmod +x pre-build.shEdit config.toml:
[[runners]]
name = "secured-runner"
url = "https://gitlab.com"
token = "YOUR_TOKEN"
executor = "shell"
pre_build_script = "/opt/gitlab-runner/hooks/pre-build.sh"Restart runner:
gitlab-runner restartThis approach allows you to:
- Restrict who can trigger jobs
- Restrict which projects can run on the runner
- Manage access centrally via remote config
- Avoid modifying runner config on every update
- Shared internal runners
- Protecting production deployment runners
- Preventing unauthorized pipelines from consuming resources
- Centralized CI access control
| Variable | Description |
|---|---|
GITLAB_USER_ID |
ID of the user who triggered the pipeline |
GITLAB_USER_LOGIN |
GitLab username |
CI_PROJECT_ID |
ID of the GitLab project |
- Cache allowlist locally
- Add branch restrictions
- Add group-based authorization
- Add audit logging
- Add rate limiting / throttling