Repository navigation
Add Workspace options to restrict the checkout and agent credentials - #1831
Open
knechtionscoding wants to merge 1 commit into
Open
knechtionscoding wants to merge 1 commit into
knechtionscoding wants to merge 1 commit into
Conversation
knechtionscoding
had a problem deploying
to
ok-to-test
October 19, 2026 09:25 — with
GitHub Actions
Error
There was a problem hiding this comment.
All reported issues were addressed across 14 files
Reply with feedback, questions, or to request a fix.
View guided diff | Re-trigger cubic
knechtionscoding
force-pushed
the
feature/workspace-restricted-checkout
branch
from
October 19, 2026 09:43
201e546 to
05fb5c6
Compare
knechtionscoding
had a problem deploying
to
ok-to-test
October 19, 2026 09:43 — with
GitHub Actions
Error
knechtionscoding
force-pushed
the
feature/workspace-restricted-checkout
branch
from
October 19, 2026 09:58
05fb5c6 to
33e94b7
Compare
knechtionscoding
had a problem deploying
to
ok-to-test
October 19, 2026 09:58 — with
GitHub Actions
Error
knechtionscoding
had a problem deploying
to
ok-to-test
October 19, 2026 11:05 — with
GitHub Actions
Error
There was a problem hiding this comment.
All reported issues were addressed across 17 files
Reply with feedback, questions, or to request a fix.
View guided diff | Re-trigger cubic
knechtionscoding
force-pushed
the
feature/workspace-restricted-checkout
branch
from
October 19, 2026 11:13
f2c48f6 to
17b7f5a
Compare
knechtionscoding
had a problem deploying
to
ok-to-test
October 19, 2026 11:13 — with
GitHub Actions
Error
knechtionscoding
had a problem deploying
to
ok-to-test
October 19, 2026 11:35 — with
GitHub Actions
Error
There was a problem hiding this comment.
All reported issues were addressed across 10 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
View guided diff | Re-trigger cubic
knechtionscoding
requested a deployment
to
ok-to-test
October 19, 2026 11:48 — with
GitHub Actions
Waiting
A Workspace with a secretRef always gives the agent container the GitHub token, through GITHUB_TOKEN/GH_TOKEN, the mounted token file and the credential helper written into .git/config, and always checks out the whole repository with its .git directory. An agent that should only read part of a private repository can therefore fetch the rest. Add three optional Workspace fields: - spec.clone.paths: check out only the listed repository paths. The clone uses --filter=blob:none --no-checkout and a non-cone sparse checkout with root-anchored patterns, so root files are not included unless listed. Works for branch, tag and commit SHA refs. Up to 64 paths of 256 characters, validated by CEL and again when the Job is built. - spec.clone.removeGitDir: delete .git at the end of git-clone. CEL rejects it together with spec.remotes, and a Task with spec.branch or a Session with spec.initialBranch fails at Job build, since both need .git. - spec.agentCredentials (Token, the default, or None): with None the token reaches only git-clone and branch-setup. The agent container gets no token env vars, GH_CONFIG_DIR, token mount or KELOS_GITHUB_TOKEN_FILE, and the credential helper is not persisted into .git/config. Session restarts no longer re-persist it either. branch-setup passes the helper inline to the checkout commands, since a partial clone fetches blobs there. Sessions with a volumeClaimTemplate reject clone.paths and clone.removeGitDir: their workspace keeps the checkout it was created with, so a restriction added later could not take effect. Sessions without persistent storage clone again on every Pod start. The fields survive a v1alpha1 round trip through a preservation annotation, so an update through v1alpha1 cannot silently drop agentCredentials None or the clone restrictions. WorkerPools do not implement these fields. A WorkerPool whose Workspace sets them is rejected before any token is minted or pool resource is touched, with an UnsupportedWorkspace Warning event, and Tasks sent to it fail instead of being assigned to existing worker pods. While the pool's Workspace is missing, its Tasks wait rather than run on workers built from it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
knechtionscoding
force-pushed
the
feature/workspace-restricted-checkout
branch
from
October 19, 2026 11:56
ac5656f to
4d79889
Compare
knechtionscoding
requested a deployment
to
ok-to-test
October 19, 2026 11:56 — with
GitHub Actions
Waiting
This was referenced Oct 19, 2026
Contributor
Author
|
@gjkim42 bump here |
This branch is waiting to be deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What type of PR is this?
/kind api
What this PR does / why we need it:
A Workspace with a
secretRefalways hands the agent container the GitHub token (GITHUB_TOKEN/GH_TOKEN, the mounted token file, and the credential helper written into.git/config), and always checks out the whole repository with its.gitdirectory. There is no way to give an agent part of a private repository without also giving it the means to fetch the rest, and even a depth-1 clone keeps every path reachable through.git.This adds three optional, backward-compatible fields to
Workspace(v1alpha2 only):spec.clone.paths: check out only the listed repository paths (directories or files). git-clone uses a partial clone (--filter=blob:none --no-checkout) and a non-cone sparse checkout with root-anchored patterns, so root files such asCLAUDE.mdare not checked out unless listed (cone mode always includes them). Works for branch, tag and full-SHA refs, keeping the existing depth and branch behavior. Entries are validated by CEL (relative, no empty/./..segments, no trailing space before or after an optional trailing slash, no*?[\or control characters, 1-64 entries of at most 256 characters) and again when the Job is built.spec.clone.removeGitDir: delete/workspace/repo/.gitas the last step of git-clone. Features that need.gitare rejected rather than silently broken: CEL rejects it together withspec.remotes, and a Task withspec.branchor a Session withspec.initialBranchfails at Job build with a message naming the conflict (JobBuildFailed/StatefulSetBuildFailed).spec.agentCredentials(Token, the default, orNone): withNonethe token reaches only git-clone and branch-setup. The agent container gets noGITHUB_TOKEN,GH_TOKEN,GH_ENTERPRISE_TOKEN,GH_CONFIG_DIR,KELOS_GITHUB_TOKEN_FILEor token volume mount, and the credential helper is not persisted into.git/config. Session restarts on a persistent volume no longer re-persist it either. branch-setup passes the helper inline to its checkout commands, because a partial clone fetches blobs there.Sessions with a
volumeClaimTemplaterejectclone.pathsandclone.removeGitDir(the Session fails withStatefulSetBuildFailedand a message naming the conflict). Their workspace keeps the checkout it was created with, so a restriction added later could not take effect, and any record of it on that volume could be rewritten by the agent. Sessions without persistent storage clone again on every Pod start, so they always match the current Workspace.agentCredentials: Noneworks with both.Together they let a Workspace produce a checkout the agent can read but cannot widen.
The new fields are carried through a v1alpha1 round trip in a
kelos.dev/v1alpha2-workspace-checkoutannotation, the same way AgentConfig and TaskSpawner preserve their v1alpha2-only fields, so an update through v1alpha1 cannot silently turnagentCredentials: Noneback intoToken. The path limits keep that annotation under about 96 KiB in the worst case.Which issue(s) this PR is related to:
N/A
Special notes for your reviewer:
Workspace.spec.clone(withbranches). The two structs merge without overlap; whichever PR lands second needs a small rebase ofWorkspaceClone.UnsupportedWorkspaceWarning event. The reconcile returns without an error so nothing retries with backoff; the Workspace watch re-enqueues the pool when it changes. Existing worker pods are left in place, but Tasks sent to the pool fail instead of being assigned to them, since they were built with the full checkout and token, and while the pool's Workspace is missing its Tasks wait instead of running on those pods. This is documented in the reference.Nonethe agent container never mounts that Secret, so refreshes do not reach it.remote.origin.promisorandremote.origin.partialclonefilterexplicitly before the filtered fetch, asgit clone --filterwould, and runs the sparse checkout beforecheckout --detachso only the listed blobs are fetched. Both checkouts that fetch blobs lazily run with the credential helper.agentCredentialsis named after what it controls in the agent container. It does not limit network access, andpodOverridesentries that reference the token Secret are applied as written; the reference says so.Testing:
.gitremoval only when set; credential helper persisted only forTokenwithoutremoveGitDir), agent env and mounts for omitted/Token/Noneon github.com and GHE, validation of paths and ofremoveGitDirwith a branch or remotes, Session restart handling, WorkerPool rejection and the WorkerPool task-assignment guard.TestSessionPodRestrictedCheckoutNeedsEphemeralStoragecovers the persistent-Session rejection.TestBranchSetupFetchesBlobsWithoutSavedCredentialsserves the repository throughgit http-backendbehind basic auth and checks that branch-setup can check out a branch whose blobs the partial clone has not downloaded, with no helper saved in.git/config.TestWorkspaceCloneScriptProducesRestrictedCheckoutruns the rendered git-clone command with real git against a local repository for branch and SHA refs and checks the files on disk, that.gitis gone, and that no credential helper is left in.git/configunderNone.removeGitDirwith a branch fails with the conflict message, and a restricted Workspace updated through v1alpha1 keeps its restrictions (this spec fails without the conversion change).setupCommand(which runs in the agent container) that only the listed paths exist,.gitis gone and no token is present.make update,make verify,make test,make test-integration,make buildpass locally. e2e was not run locally.Does this PR introduce a user-facing change?