Allow disabling after_script on the runner

What does this MR do?

This MR introduces a new configuration option after_script_disabled for GitLab Runner. When enabled, the runner skips executing the after_script section entirely, regardless of any job definition.

Why was this MR needed?

Currently, after_script always executes, even if a job exits early (e.g., in pre_build_script). This creates potential security issues:

  • A user could access sensitive data from the runner during after_script.
  • A user could delete files or modify runner state via after_script.
  • It prevents full control over what commands actually run on the runner.

By introducing this flag, runner administrators can fully control which steps are executed, ensuring that all logic is handled explicitly in pre_build_script. This improves security and predictability for critical runners.

This feature acts as an additional security layer, alongside existing protections like allowed_images and allowed_services, to ensure that jobs cannot execute arbitrary or unsafe commands on critical runners.

What's the best way to test this MR?

Configure a runner with after_script_disabled = true
[[runners]]
  name = "secure-runner"
  executor = "docker"
  pre_build_script = "echo RUN_PREBUILD_SECURITY_SCRIPT; exit 0"
  after_script_disabled = true
Define a job with a non-empty after_script
stages:
  - test

.after_script:
  stage: test
  image: alpine:3
  tags: [local]
  needs: []
  script:
    - echo SCRIPT

after_script:ok:
  extends: [.after_script]
after_script:warn:
  extends: [.after_script]
  after_script:
    - echo AFTER_SCRIPT

Run the job and verify: the job executes all normal stages (script, cache, etc.), the after_script stage is never executed.

https://gitlab.com/madest92/gitlab-runner/-/pipelines/2068770431

See log

image

Refs User defined after_script is executed after fai... (#3116)

Edited by Timo Furrer

Merge request reports

Loading