restricted networking for all sandboxing methods, new seatbelt profiles, updated docs, fixes to sandbox build, debugging through sandbox (#891)

This commit is contained in:
Olcan
2025-06-10 08:58:37 -07:00
committed by GitHub
parent 895c1f132f
commit e38d2078cc
16 changed files with 511 additions and 47 deletions

View File

@@ -111,7 +111,7 @@ function buildImage(imageName, dockerfile) {
execSync(
`${buildCommand} ${process.env.BUILD_SANDBOX_FLAGS || ''} -f "${dockerfile}" -t "${imageName}" .`,
{ stdio: buildStdout },
{ stdio: buildStdout, shell: '/bin/bash' },
);
console.log(`built ${imageName}`);
}

74
scripts/example-proxy.js Executable file
View File

@@ -0,0 +1,74 @@
#!/usr/bin/env node
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
// Example proxy server that listens on 0.0.0.0:8877 and only allows HTTPS connections to example.com.
// Set `GEMINI_SANDBOX_PROXY_COMMAND=scripts/example-proxy.js` to run proxy alongside sandbox
// Test via `curl https://example.com` inside sandbox (in shell mode or via shell tool)
import http from 'http';
import net from 'net';
import { URL } from 'url';
import console from 'console';
const PROXY_PORT = 8877;
const ALLOWED_DOMAINS = ['example.com', 'googleapis.com'];
const ALLOWED_PORT = '443';
const server = http.createServer((req, res) => {
// Deny all requests other than CONNECT for HTTPS
console.log(
`[PROXY] Denying non-CONNECT request for: ${req.method} ${req.url}`,
);
res.writeHead(405, { 'Content-Type': 'text/plain' });
res.end('Method Not Allowed');
});
server.on('connect', (req, clientSocket, head) => {
// req.url will be in the format "hostname:port" for a CONNECT request.
const { port, hostname } = new URL(`http://${req.url}`);
console.log(`[PROXY] Intercepted CONNECT request for: ${hostname}:${port}`);
if (
ALLOWED_DOMAINS.some(
(domain) => hostname == domain || hostname.endsWith(`.${domain}`),
) &&
port === ALLOWED_PORT
) {
console.log(`[PROXY] Allowing connection to ${hostname}:${port}`);
// Establish a TCP connection to the original destination.
const serverSocket = net.connect(port, hostname, () => {
clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n');
// Create a tunnel by piping data between the client and the destination server.
serverSocket.write(head);
serverSocket.pipe(clientSocket);
clientSocket.pipe(serverSocket);
});
serverSocket.on('error', (err) => {
console.error(`[PROXY] Error connecting to destination: ${err.message}`);
clientSocket.end(`HTTP/1.1 502 Bad Gateway\r\n\r\n`);
});
} else {
console.log(`[PROXY] Denying connection to ${hostname}:${port}`);
clientSocket.end('HTTP/1.1 403 Forbidden\r\n\r\n');
}
clientSocket.on('error', (err) => {
// This can happen if the client hangs up.
console.error(`[PROXY] Client socket error: ${err.message}`);
});
});
server.listen(PROXY_PORT, '0.0.0.0', () => {
console.log(`[PROXY] Proxy listening on 0.0.0.0:${PROXY_PORT}`);
console.log(
`[PROXY] Allowing HTTPS connections to domains: ${ALLOWED_DOMAINS.join(', ')}`,
);
});

View File

@@ -33,11 +33,12 @@ execSync('node ./scripts/check-build-status.js', {
// inside sandbox SANDBOX should be set and sandbox_command.js should fail
const nodeArgs = [];
try {
execSync('node scripts/sandbox_command.js -q', {
stdio: 'inherit',
const sandboxCommand = execSync('node scripts/sandbox_command.js', {
cwd: root,
});
if (process.env.DEBUG) {
})
.toString()
.trim();
if (process.env.DEBUG && !sandboxCommand) {
if (process.env.SANDBOX) {
const port = process.env.DEBUG_PORT || '9229';
nodeArgs.push(`--inspect-brk=0.0.0.0:${port}`);