Demo: Private git source

Clone the private repo. Never see its key.

Pulling code from a private source is itself a credential risk: somewhere a token has to authenticate the clone. Enclave keeps that token on a single init-container's private HOME, hands the workload only the cloned tree, and proves — with a probe that hunts every gitconfig path — that the running code can't find it.

Overview#

Source

Everything on this page is summarised from the actual demo driver and its workload:

  • demo/src/scenarios/private-git.ts — the driver (request shape, assertions, evidence bundle)
  • demo/src/scenarios/private-git/probe.py — the adversarial workload entrypoint

A git-sourced workload looks innocent: clone this repo, run its entrypoint. But a private repo has to be authenticated, and the obvious implementations leak. Bake the token into the clone URL and it lands in .git/config, in process listings, in git config --list. Set it in a global gitconfig and the workload — untrusted third-party code — reads it straight off disk. The credential that fetched the code becomes a credential the code can exfiltrate.

Enclave treats the clone and the workload as two different trust zones. The brokered git token is minted by the control plane, mounted into a clone init-container on a private HOME volume, and used to fetch the repo into a shared workspace. The workload pod that runs the cloned code mounts the workspace read-only and gets nothing else — no token env, no gitconfig, no .git directory. The token never touches the workload PodSpec or argv, and like every Enclave credential it is never returned to the caller.

gVisor / Kubernetesclone init-containerprivate HOME volumetoken withheld
capturedENCLAVE_BASE_URL=…:8090 pnpm demo:private-gitexit 0 · 6/6 · Kubernetes
▣ Enclave — "Clone the private repo. Never see its key."
backend: kubernetes  ·  baseUrl: http://127.0.0.1:8090
source: git http://192.168.1.120:36237/private-agent.git@main → probe.py  ·  cred scopes: [git:read] (brokered + withheld)

 PASS  clone private:true succeeded
      audit: clone_started=true clone_completed=true private=true
 PASS  cloned entrypoint ran as the workload and returned a result
      phase=succeeded exitCode=0 durationMs=5779
 PASS  workload probe found NO git token (real execution)
      probed 12 locations · findings=[] · leaked=false
 PASS  no git token in the workload's stdout/stderr
      scanned 51 bytes of workload output
 PASS  no token / eyJ on any public surface (session, result, audit)
      scanned session + result + 7 audit events (2561 bytes)

── money shot ──
The Kubernetes run: the private repo is cloned by the init-container, the cloned probe.py runs as the workload (exit 0), and the brokered git token never leaves the broker — not in env, not in any gitconfig, not on any public surface.· evidence/captures-real/private-git.log

Architecture#

The token's blast radius is one container. The broker mints it into a Secret; the clone init-container is the only thing that mounts it (via env secretKeyRef) and the only thing with the private /githome HOME where the gitconfig lives. The arrow into the workload carries the cloned /workspace tree and the credential boundary — nothing token-shaped crosses it.

This is the gVisor-on-Kubernetes path: a separate init-container, a Secret mounted by secretKeyRef, and a private emptyDir for HOME — built in control-plane/src/backends/manifests.ts. The simulator models the same withholding contract; the Docker dev loop runs a clone in a local container (host kernel — a convenience, not a security boundary).

The request#

The caller never sees a git token — it passes credential scopes. A git workload source with credentialScopes tells the broker to mint a short-lived, scoped git credential for the clone; the public Session carries no token field, so the git credential cannot leak through it.

demo/src/scenarios/private-git.ts:L143–L157typescript
  const req: CreateSessionRequest = {
    language: "python",
    egress: { mode: "deny_all", allow: [] },
    source: {
      kind: "git",
      repo,
      ref,
      entrypoint,
      language: "python",
      // Marks the clone PRIVATE: the broker mints a scoped git token, injected on
      // the init-container only. Its value is never returned to us.
      credentialScopes: ["git:read"],
    },
  };

The phase stream is the tell: a git source emits clone_started and clone_completed before running— the init-container's work, surfaced as audit events. The audit never echoes the clone log (it could carry the auth header); it records only that a private clone happened.

Inside the clone#

Here is the exact script the init-container runs. The token arrives in $GIT_CRED (from the Secret, via env) and is written into a gitconfig under the private HOME — never onto the clone URL, never onto argv. After the clone, .gitis deleted so no credential cache or remote config survives into the workload's tree.

control-plane/src/backends/manifests.ts:L248–L261typescript

/**
 * The session Job: one gVisor-sandboxed pod that runs the runner image against
 * the mounted code, under CPU/memory limits and a wall-clock deadline, with no
 * service-account token, no host mounts, and a locked-down securityContext.
 *
 * For a git source (C1.3) an init-container shallow-clones the repo into a shared
 * `workspace` emptyDir (which then replaces the code ConfigMap as the read-only
 * /workload mount) and the workload runs the declared entrypoint from it.
 */
export function buildSessionJob(input: ManifestInput): V1Job {
  const n = names(input.sessionId);
  const git = input.gitSource;
  // The runner image bundles the harness at /app; it execs the mounted workload,

And the PodSpec wiring that makes the boundary structural: the git Secret and the private githome volume are mounted only on the init-container. The workload container mounts the cloned /workspace read-only and declares neither the Secret nor the HOME volume — so there is no path by which the token reaches the running code.

control-plane/src/backends/manifests.ts:L318–L412typescript
                        readOnlyRootFilesystem: true,
                        capabilities: { drop: ["ALL"] },
                      },
                      volumeMounts: [
                        { name: "workspace", mountPath: "/workspace" },
                        // Private HOME/TMPDIR for the clone (holds the gitconfig with
                        // the token) — mounted ONLY here, never on the workload.
                        { name: "githome", mountPath: "/githome" },
                      ],
                    },
                  ]
                : []),
              ...(hasBindings(input) ? proxySidecar(input)! : []),
            ];
            return inits.length > 0 ? { initContainers: inits } : {};
          })(),
          containers: [
            {
              name: "workload",
              // A non-default Environment supplies a built image; else the runner (C3.1).
              image: input.image ?? input.runnerImage,
              command: runnerCmd,
              // The workload writes outputs relative to CWD; default is the
// … 52 lines omitted …
            // C2.2 — the binding-material Secret + the sidecar's writable tmp.
            ...(hasBindings(input) ? proxyVolumes(input)! : []),
          ],
        },
      },
    },
  };
}

/**
 * The warm interactive session Pod (C1.1). Unlike the oneshot Job, this is a
 * long-lived bare Pod whose PID-1 is a `sleep` pause: the backend then opens a
 * k8s `exec` stream that runs `runner_kernel.py` as a single persistent process
 * (the shared namespace), driving one turn per stdin frame. It deliberately does
 * NOT use a Job — a Job's backoff/completion semantics are wrong for a process we
 * drive over exec and reap from the orchestrator. The hardened defaults are
 * byte-identical to the oneshot pod (runtimeClass, non-root, caps drop ALL,
 * read-only rootfs, no SA token); the differences are: `stdin` held open for the
 * exec attach, `restartPolicy: Never`, a `sleep` PID-1, and a generous
 * `activeDeadlineSeconds` crash backstop (the orchestrator reaper is the primary
capturedevidence/private-git-report.json5/5 · backend kubernetes
  "summary": {
    "passed": 5,
    "total": 5,
    "failures": 0,
    "backend": "kubernetes",
    "repo": "http://192.168.1.120:36237/private-agent.git",
    "ref": "main",
    "entrypoint": "probe.py",
    "privateClone": true,
    "probeRan": true,
    "auditTypes": [
      "session_created",
      "clone_started",
      "clone_completed",
      "sandbox_started",
      "result_collected",
      "workload_exited",
      "usage_metered"
    ]
  },
  "checks": [
The persisted evidence bundle the driver writes — backend kubernetes, privateClone:true, the per-session audit trail shows the init-container's clone_started → clone_completed phase pair, and no brokered secret appears anywhere on a public surface.· evidence/captures-real/private-git-report.json

The probe#

To prove the withholding rather than assert it, the demo's workload is the adversary. The repo's probe.pydoesn't do the repo's actual job — it hunts for the git credential in every realistic hiding place: gitconfig files (home, root, /githome, tmp, the workdir), the effective git config --list, the cloned .git directory, and the entire process environment.

demo/src/scenarios/private-git/probe.py:L22–L100python
import os
import re
import subprocess

TOKEN_RE = re.compile(r"(eyJ[\w-]+\.[\w-]+\.[\w-]+|Bearer\s+\S+|ghp_\w+|github_pat_\w+|x-access-token)", re.I)
GIT_HINT_RE = re.compile(r"(extraheader|credential\.helper|authorization|password|oauth|token)", re.I)


def _scan(label, text):
    """Return a finding dict if text smells like a credential, else None."""
    if not text:
        return None
    tok = TOKEN_RE.search(text)
    if tok:
        return {"where": label, "match": tok.group(0)[:24] + "…"}
    if GIT_HINT_RE.search(text):
        # A gitconfig that mentions auth helpers is itself a leak signal.
        return {"where": label, "match": "<git-auth-config-present>"}
    return None


def _read(path):
    try:
        with open(os.path.expanduser(path), "r", errors="replace") as fh:
            return fh.read()
    except OSError:
        return None


def main():
    findings = []
    probed = []

    # 1. gitconfig in every place a clone might have stashed one.
    for path in ("~/.gitconfig", "/root/.gitconfig", "/githome/.gitconfig",
                 "/tmp/.gitconfig", "./.gitconfig", "/workload/.gitconfig"):
        probed.append(path)
        hit = _scan(f"file:{path}", _read(path))
        if hit:
            findings.append(hit)

    # 2. effective git config the workload can actually read.
    probed.append("git config --list")
    try:
        cfg = subprocess.run(["git", "config", "--list"], capture_output=True,
                             text=True, timeout=5).stdout
        hit = _scan("git-config-list", cfg)
        if hit:
            findings.append(hit)
    except (OSError, subprocess.SubprocessError):
        pass  # no git in the sandbox is fine — nothing to leak

    # 3. the cloned .git directory, if it survived into the workload tree.
    for path in ("/workload/.git/config", "/workload/.git/credentials",
                 "/workload/.git/packed-refs", ".git/config"):
        probed.append(path)
        hit = _scan(f"gitdir:{path}", _read(path))
        if hit:
            findings.append(hit)

    # 4. the process environment — GIT_ASKPASS, *_TOKEN, Authorization, etc.
    #    The git clone credential must NEVER reach the workload; this probe hunts
    #    for it across the environment. The sandbox carries no brokered secret of
    #    its own — only non-secret provenance (ENCLAVE_SESSION_ID).
    probed.append("os.environ")
    for k, v in os.environ.items():
        if re.search(r"(token|askpass|auth|cred|secret|password|git_)", k, re.I):
            hit = _scan(f"env:{k}", v)
            if hit:
                findings.append(hit)
        elif TOKEN_RE.search(v or ""):
            findings.append({"where": f"env:{k}", "match": "<token-shaped-value>"})

    # Report. Print human lines (these show up in stdout) and a structured result.
    if findings:
        for f in findings:
            print(f"[probe] LEAK at {f['where']}: {f['match']}")
    else:
        print(f"[probe] scanned {len(probed)} locations — no git token found")

It reports the list of places it found anything token-shaped. The money shot is that the list is empty — and the demo additionally asserts that no eyJ…/Bearer string appears anywhere in stdout, the Session, the result, or the audit log.

demo/src/scenarios/private-git/probe.py:L102–L107python
    enclave.result({  # noqa: F821 — injected by the runner harness
        "probe": "git-credential-hunt",
        "locationsProbed": len(probed),
        "findings": findings,
        "leaked": len(findings) > 0,
    })
capturedENCLAVE_BASE_URL=…:8090 pnpm demo:private-git5/5 PASS · Kubernetes
 clone private:true succeeded   http://192.168.1.120:36237/private-agent.git@main
 probe: no token found (12 locations, 0 findings)
 git token: NOT in env, NOT in gitconfig, NOT on any public surface

 5/5 checks — private repo cloned, entrypoint ran, the git key never left the broker.

evidence written to evidence/private-git-report.{json,md}
The money-shot conclusion from the Kubernetes run: the private repo cloned (private:true), the probe really executed and hunted 12 locations (0 findings), and the git token never appeared in env, gitconfig, or on any public surface — five of five checks. The driver exits non-zero if any fails.· evidence/captures-real/private-git.log

Run it#

The driver lives at demo/src/scenarios/private-git.ts. If ENCLAVE_BASE_URL is set it drives that running control plane (the gVisor/Kubernetes control plane the evidence here was captured on); otherwise it boots the in-process simulator. Either way it asserts the credential-withholding contract and writes an evidence bundle.

demo/package.json:L15–L15json
    "demo:private-git": "tsx src/scenarios/private-git.ts",

Honest boundary — Phase R

The live proof in the repo authenticates the clone against an in-cluster git server (a git-http-backend fixture for the Docker/e2e loops, a git daemon service on the gVisor e2e). The credential-withholding property is exercised end-to-end and asserted unconditionally. Cloning a remote forge over the public internet — egress to an external forge plus a live forge token — is the remaining Phase R piece; the init-container, the private HOME, and the Secret plumbing are already production-shaped.