Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/sbx-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ What `createSandbox()` shares, in order:
**Scrubbing nested credential stores.** Several whitelisted dirs legitimately
hold tool settings but also stash a secret in a well-known child — e.g.
`.config/gh`, `.config/gcloud`, `.cargo/credentials`, `.claude/.credentials.json`,
`.copilot/config.json`, `.gemini/oauth_creds.json`. Because the parent is mounted
`.gemini/oauth_creds.json`. Because the parent is mounted
wholesale and sbx cannot overlay or mask a nested path, the manager instead
**moves those credential paths aside on the host before `sbx create` and restores
them after the sandbox is torn down** (`scrubHomeCredentials` /
Expand Down
2 changes: 1 addition & 1 deletion src/config/mount-policy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ describe('mount-policy', () => {

expect(paths).toContain('.config/gh');
expect(paths).toContain('.cargo/credentials');
expect(paths).toContain('.copilot/config.json');
expect(paths).toContain('.claude/.credentials.json');
// Never-mounted parents are excluded.
expect(paths).not.toContain('.ssh/id_rsa');
expect(paths).not.toContain('.aws/credentials');
Expand Down
1 change: 0 additions & 1 deletion src/config/sandbox-mount-policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
{ "path": ".cargo/credentials", "type": "file", "reason": "crates.io registry token" },
{ "path": ".cargo/credentials.toml", "type": "file", "reason": "crates.io registry token (newer cargo)" },
{ "path": ".claude/.credentials.json", "type": "file", "reason": "Claude Code OAuth tokens" },
{ "path": ".copilot/config.json", "type": "file", "reason": "Copilot CLI persisted auth token" },
{ "path": ".gemini/oauth_creds.json", "type": "file", "reason": "Gemini CLI OAuth tokens" },
{ "path": ".gemini/google_accounts.json", "type": "file", "reason": "Gemini CLI account identity" },
{ "path": ".gemini/access_tokens.json", "type": "file", "reason": "Gemini CLI cached access tokens" },
Expand Down
6 changes: 2 additions & 4 deletions src/sbx-manager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,12 @@ describe('sbx-manager', () => {
const parents = [
`${homePath}/.cargo`,
`${homePath}/.claude`,
`${homePath}/.copilot`,
`${homePath}/.gemini`,
];
const secrets = [
`${homePath}/.cargo/credentials`,
`${homePath}/.cargo/credentials.toml`,
`${homePath}/.claude/.credentials.json`,
`${homePath}/.copilot/config.json`,
`${homePath}/.gemini/oauth_creds.json`,
`${homePath}/.gemini/google_accounts.json`,
];
Expand Down Expand Up @@ -244,10 +242,10 @@ describe('sbx-manager', () => {

it('restores scrubbed credentials after the sandbox is removed', async () => {
const homePath = process.env.HOME || '/home/runner';
const secret = `${homePath}/.copilot/config.json`;
const secret = `${homePath}/.claude/.credentials.json`;
mockedExistsSync.mockImplementation(
(p: fs.PathLike) =>
String(p) === `${homePath}/.copilot` ||
String(p) === `${homePath}/.claude` ||
String(p) === secret ||
String(p).includes('.awf-sbx-cred-backup'),
);
Expand Down
2 changes: 1 addition & 1 deletion src/sbx-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ export async function createSandbox(config: SbxConfig): Promise<string> {
// individual file, so child-by-child expansion would drop loose files the
// agent needs (e.g. ~/.copilot/mcp-config.json). Several of these dirs also
// nest a credential store — e.g. .config/gh, .cargo/credentials,
// .claude/.credentials.json, .copilot/config.json, .gemini/oauth_creds.json.
// .claude/.credentials.json, .gemini/oauth_creds.json.
// Those specific paths are moved aside on the host BEFORE `sbx create` (see
// scrubHomeCredentials below) and restored after teardown, so the benign tool
// state stays available while the secrets never enter the microVM.
Expand Down
1 change: 0 additions & 1 deletion src/services/agent-volumes/credential-hiding.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ describe('buildCredentialHidingOverlays', () => {
expect(overlays).toContain('/dev/null:/home/runner/.config/gh/hosts.yml:ro');
expect(overlays).toContain('/dev/null:/host/home/runner/.config/gh/hosts.yml:ro');
// Newly centralized entries (previously only protected by sbx).
expect(overlays).toContain('/dev/null:/home/runner/.copilot/config.json:ro');
expect(overlays).toContain('/dev/null:/home/runner/.claude/.credentials.json:ro');
expect(overlays).toContain('/dev/null:/home/runner/.gemini/oauth_creds.json:ro');
});
Expand Down
Loading