CJE study materials
CJE study resources

Folder-Scoped Contractors and a Leaked Deploy Token

CJE · Put your knowledge to work in context.

All case studies

Folder-Scoped Contractors and a Leaked Deploy Token

A Jenkins controller authenticates 140 developers through LDAP and uses matrix-based security with anonymous read disabled. Five teams share folders named after their products. All developers are members of cn=developers; administrators are in cn=jenkins-admins. A GitLab runner deploys with a shared Jenkins user named svc-deploy, which is in the administrators group and uses a static API token. A contractor team needs read-only access to the client-a folder only and must not see job names in other folders. During an incident, a deployment job printed an API token into its console log; the token belongs to svc-deploy. Security wants the shared admin account removed and the exposure contained before a change freeze in 10 days.

1. Design authorization so contractors see only client-a and cannot discover job names in other folders. Which strategy and patterns do you use, and how do you verify it?

Read the worked answer

Use the Role-based Authorization Strategy plugin, or a folder-scoped project-based matrix if you already standardize on folders. Grant all authenticated users Overall/Read so they can log in, but do not grant global Job/Read. Create an item role for contractors with pattern ^client-a(/.*)?$ and permissions Job/Read and Run/Read (add View/Read for a dedicated view if needed). Assign that role to the LDAP group contractors, not to individuals. Keep developers' item roles scoped to their product folders so they cannot see other teams' job names. Test with a real contractor account: log in, confirm the dashboard lists only client-a, and request another folder's job URL directly; it must return 403. Also confirm they cannot access manage or script. This is safer than granting Overall/Read plus Job/Read globally and hiding views, because views are not an authorization boundary.

2. Replace svc-deploy with least privilege. What permissions and token controls should the replacement have, and why?

Read the worked answer

svc-deploy is effectively admin because of LDAP group membership; permissions come from the group, so removing it from cn=jenkins-admins is the first step. Create a dedicated service identity, for example svc-gitlab-deploy, and give it only the permissions needed to trigger the deployment job: Overall/Read, Job/Read, and Job/Build on the deploy folder via an item role pattern. It does not need Overall/Administer, Agent/Configure, Credentials, or Job/Configure. Store the GitLab token as a Jenkins credential and bind it in the Pipeline with withCredentials, so the user does not need credential access. API tokens inherit the user's permissions and cannot be scoped down independently, so least privilege at the user and role level is the control. Rotate the new token on a schedule and prefer short-lived or OIDC-based credentials if GitLab supports them.

3. Contain the leaked token and prevent recurrence. What do you revoke, what do you preserve, and what controls do you add?

Read the worked answer

Revoke the leaked token immediately, then rotate the GitLab token it protects and update the runner. Search build logs and job configs for the token string; remember that Jenkins masks credentials used through withCredentials, but a token printed from a plain variable or a config file is not masked. Remove the token from job configuration, and quarantine the affected build logs rather than deleting them if they are audit evidence. Enable the Audit Trail plugin to record job configuration changes and logins, restrict Script Console and admin access, and add a Pipeline review rule that rejects echo of credential variables. Re-test with a canary job that prints a dummy secret to confirm masking. Finally, review whether the runner can use a project access token with only write_repository and deploy permissions instead of a personal token.