Repository navigation
Conversation
A private skill or plugin source binds its git credential as an Authorization header on the source's host. The revision's one credential list compiled both the golden template's default policy, which the golden boot needs to fetch the source, and every Session actor's own policy, so a request the sandbox sent to that host with an Authorization header left with the token. A binding now carries a scope: empty for every actor (model and MCP bindings), golden for the golden boot only (artifact bindings). The golden template keeps every binding; the Session's create, repoint and rollback policies are compiled from egress.ForActors, without the golden ones. The host stays reachable from the sandbox, unauthenticated. The scope is part of the revision digest, so an agent with a credentialed source renders a new revision once and its READY sessions are repointed onto it; agents without one keep their digest. Signed-off-by: Timo Derstappen <teemow@gmail.com>
4 tasks
The execute path set revision to the repoint target in two places after its last read; ineffassign reports both once the create path reads the revision through sessionEgressPolicy. Signed-off-by: Timo Derstappen <teemow@gmail.com>
Substrate gives an Actor its template's default egress policy at creation. A Session's policy now differs from that default when the template carries a golden-only binding, and EnsureActorEgressPolicy refused the existing allowlist, so every Session of such an agent failed to create. The create path now passes the template's default as the inherited policy: an existing policy equal to it is replaced with the Session's before the Actor first runs; any other allowlist is still refused. Signed-off-by: Timo Derstappen <teemow@gmail.com>
Member
Author
|
(Written by an agent.) Replaced by #366: the base moved 35 commits (the Vertex AI credential authority, the Session workspace volumes, one carried file per change under fork/carried) and this branch conflicted with it; this line rebase-merges, so the change moved to a fresh branch of the base. |
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.
Closes #286.
Problem
A private skill or plugin source binds its git credential (an App or deploy token) as
authorization: Basicon the source's host. The revision's oneCredentialslist compiled both the golden template's default egress policy, which the golden boot needs to fetch the source, and every Session actor's own policy (create,repointTargetand its rollback). So any request a session's sandbox sent to that host with anAuthorizationheader (a shell tool, an MCP client,gh) left with the token, and read what the token can reach rather than what the person of the turn can.Proposed solution
One carried, upstream-ready commit: a binding names the actors it is for.
egress.CredentialgainsScope(json:"scope,omitempty"): empty for every actor (model and MCP bindings, unchanged),goldenfor the golden boot only.CompileCredentialsscopes every artifact bindinggolden;CanonicalCredentialsvalidates the scope and keeps its same-host-and-header rule.ActorTemplateForRevisionstill compiles the template's default policy from every binding.sessionEgressPolicy, fromegress.ForActors(bindings). The source's host stays allowed from the sandbox, unauthenticated.EnsureActorEgressPolicyas the inherited policy: an existing policy equal to it is replaced with the Session's before the Actor first runs, one equal to the Session's is accepted as before (a retried create), any other allowlist is still refused (fix(substrate): replace a new Actor's inherited template allowlist).refactor(session): drop the execute path's dead revision writes: two assignments after the last read thatineffassignreports once the create path reads the revision through the helper.runtime_revision.credentialstakes the field. The scope is part of the revision digest, so an agent with a credentialed source renders a new revision once (a golden boot) and its READY sessions are repointed by the superseded-revision mechanism, with their policy replaced; other agents keep their digest. NoactorTemplateFormatbump: the golden policy is unchanged.docs/architecture/credential-injection.mddescribes the scope; FORK.md has the row with the upstream exit (the follow-up a review note on feat(skills): private Git skill sources via egress gateway credentials kagent-dev/kagent#3099 names, once that pull request is merged).This lands beside #147, which changes
translator/credentials.goandegress/credentials.goin other hunks; whichever lands second rebases.Acceptance criteria
TestCompileCredentialsScopesArtifactBindingsToTheGoldenBoot(artifactgolden, model and MCP none),TestActorTemplateForRevision(the default policy carries the artifact binding),TestSessionEgressPolicyLeavesOutTheGoldenBootsCredentials(the policy passed toEnsureActorEgressPolicyon create and the onerepointTargetbuilds carry none of it and keep the model and MCP bindings),TestRevisionDigestChangesOnlyWithAnArtifactBinding(a model binding keeps the digest pinned from the base commit; an artifact binding changes it),TestForActors,TestCanonicalCredentials,TestEnsureActorEgressPolicyReplacesTheInheritedDefault.TestGitArtifactCredentialDelivery(every harness) keeps its golden-boot assertion, limited to the fixture's requests recorded before the Agent reported Ready, and gains a turn in which the sandbox's shell tool (driven by the interaction mock) runsgit ls-remoteagainst the source twice: once withoutAuthorization, as git does before a challenge, and once with the placeholder header the golden boot sends. Every request recorded from Ready on carries the Secret value in no header and reaches the fixture (none is denied by the gateway): the bare one arrives bare, the placeholder one with the placeholder, not replaced. The placeholder request is the regression check, since the gateway replaces only a header the request carries: before this change it arrived with the Secret.TestSessionEgressDeniesUnconfiguredDestinationunchanged.