In Jenkins, how does a shared library configured globally differ in trust from one configured on a folder, and what does that mean for who may merge to the library repository?
answer
- trust follows where it is registered
- one scope skips the sandbox entirely
- script approval never fires for it
- merge rights equal controller rights
- folder scope for team-owned code
basics
~20 sGlobally configured Jenkins shared libraries are trusted: their Groovy runs outside the script sandbox with full access to Jenkins internals. Folder-scoped libraries are untrusted and run sandboxed. So merge rights on a trusted library repository are effectively administrator rights on the controller.
solid answer
~50 sJenkins decides trust by where the library is registered, not by what the code does. A library configured under the global system configuration is trusted: its code is exempt from the Groovy sandbox and from script approval, so it can call Jenkins internal APIs, reach the credentials store, and run arbitrary Java. A library configured on a folder is untrusted, and its code runs in the same sandbox as an ordinary Jenkinsfile, so restricted calls are blocked until an administrator approves them. The consequence is the part interviewers want: anyone who can merge to a trusted global library repository can run arbitrary code on the controller in every build that loads it, which means reading every credential Jenkins holds. That repository therefore needs production-grade protection — mandatory review, restricted merge rights, protected branches — and code that many teams should edit belongs in a folder library instead. Recent Jenkins versions also offer an explicitly untrusted global library section for exactly that middle case.
go deeper
Know that shared libraries can be set up for the whole controller or just for a folder, and that the global ones are treated as trusted code an administrator vouches for.
Explain the sandbox: ordinary pipeline Groovy is intercepted and needs approval for restricted calls, while trusted global library code is exempt and can call Jenkins internals directly.
State the consequence out loud — merge access to a trusted library is controller-admin access — and describe the controls you put on that repository, including pinning the default version.
Own the placement policy: which libraries are trusted, who may merge, what goes into folder libraries instead, and how you keep the trusted surface small enough to review seriously.
## Trust is a property of where the library is registered The Pipeline: Shared Groovy Libraries plugin defines library scopes, and each scope carries a fixed trust level: - **Global Pipeline Libraries**, registered by an administrator in the Jenkins system configuration, are **trusted**. - **Folder-level libraries**, registered on a folder by someone with permission to configure that folder, are **untrusted**. Nothing in the library's own code changes this. The same file is unsandboxed in one place and sandboxed in the other. ## What trusted actually means Ordinary Jenkinsfile Groovy runs in the **Groovy sandbox**: an interceptor checks every method call against an allowlist and blocks anything not approved, at which point an administrator must approve the specific signature in the script-approval screen. That is the mechanism that stops a pipeline author from calling into Jenkins itself. Trusted library code skips all of it. It can: - call Jenkins internal APIs and plugin classes directly, including model objects that expose configuration; - reach the credentials store programmatically rather than through `withCredentials`; - run arbitrary Java and Groovy, spawn processes on the controller, read files on the controller's filesystem. That is exactly the power a platform team wants when writing infrastructure-grade steps — and exactly why the repository holding it is a crown-jewel asset. ## The security statement worth memorising **Merge access to a trusted global shared library is equivalent to administrator access to the Jenkins controller.** A single commit adding a few lines to a widely-loaded `vars` file can enumerate and exfiltrate every credential the controller stores, on the next build of any job. No approval prompt fires, because trusted code is not subject to approval. It gets sharper when the library is also loaded implicitly: the code runs in every build on the controller with no Jenkinsfile opting in. ## What follows operationally Treat the trusted library repository as production: - protected default branch, no direct pushes; - mandatory review by the platform team, with reviewers who are themselves trusted at that level; - pin the default version to a tag rather than a branch, so a merge is not a deploy; - audit changes — the library's history is a security log; - keep it small. Every extra line of trusted code is unsandboxed attack surface. And conversely: if a team wants to iterate on their own pipeline helpers, giving them merge rights on the trusted library is the wrong answer. Put their code in a **folder library** scoped to their folder. It runs sandboxed, restricted calls surface as approval requests instead of silent power, and the blast radius is their folder rather than the controller. ## The middle ground in recent versions Recent releases of the shared-libraries plugin split the global configuration into trusted and untrusted sections, so an administrator can register a controller-wide library whose code still runs in the sandbox. That is useful when a library must be available everywhere but its authors should not be implicitly administrators. Check the controller's configuration page before promising this in a design — the option's presence depends on the plugin version installed. ## Related traps - **`resources/` and `src/` are not safer than `vars/`.** All library code in a trusted library is trusted. - **Sandboxed does not mean safe.** An untrusted folder library still runs in builds with access to whatever credentials those jobs bind; the sandbox protects the controller, not the job's own secrets. - **Version pinning is a security control here, not just a stability one.** A trusted library whose default version is a branch means a merge becomes controller-wide code execution with no review gate between commit and run. ## How to answer in an interview Lead with the rule — trust follows scope, global is trusted and unsandboxed, folder is sandboxed — then state the consequence for merge rights, then say what you do about it: protect the repository like production, keep trusted code small, and push team-owned helpers down to folder libraries.
- Does moving logic from vars/ into src/ change what a trusted library is allowed to do?No. Trust is a property of the library's scope, not of the directory. Everything in a trusted global library — vars, src and the resources it ships — runs outside the sandbox. Splitting code between directories is a design decision about testability and API surface, never a security boundary.
- A folder library hits a rejected signature during a build. What has happened and what are the options?Sandboxed code called a method that is not on the allowlist, so the build failed and an approval request was recorded for an administrator. Options: approve the specific signature if it is genuinely safe, rewrite the code to use an approved pipeline step instead, or move that narrow piece into a trusted library owned by the platform team.
- What still goes wrong if a trusted library is pinned to a tag rather than a branch?Pinning removes automatic propagation, not the underlying power. Whoever can create or move tags, or whoever an administrator asks to bump the default version, still controls unsandboxed code. Pinning buys a review point and a rollback path; it does not replace protecting the repository and restricting who may merge.
saying these in an interview costs you the question
- Thinks trust depends on the code, not the library scope
- Believes script approval protects trusted library code
- Says folder libraries are just global ones with a smaller audience
- Grants library merge rights broadly to speed teams up
- Assumes src classes are sandboxed while vars are not