|
1 | 1 | import { Sandbox } from '@e2b/code-interpreter' |
2 | 2 | import { NextRequest } from 'next/server' |
| 3 | +import path from 'path' |
3 | 4 |
|
4 | 5 | export const maxDuration = 60 |
5 | 6 | export const runtime = 'nodejs' |
@@ -42,21 +43,27 @@ export async function GET( |
42 | 43 | // Connect to existing sandbox |
43 | 44 | const sbx = await Sandbox.connect(sbxId) |
44 | 45 |
|
45 | | - // Read file content from sandbox |
46 | | - // Remove leading slash if present and prepend /home/user/ |
47 | | - const fullPath = filePath.startsWith('/') |
48 | | - ? `/home/user${filePath}` |
49 | | - : `/home/user/${filePath}` |
| 46 | + // Sanitize path to prevent path traversal attacks |
| 47 | + const userDir = '/home/user' |
| 48 | + const normalizedPath = path.normalize(path.join(userDir, filePath)) |
50 | 49 |
|
51 | | - const result = await sbx.commands.run(`cat "${fullPath}"`) |
| 50 | + // Verify the normalized path is still within the allowed directory |
| 51 | + if (!normalizedPath.startsWith(userDir + '/') && normalizedPath !== userDir) { |
| 52 | + return new Response( |
| 53 | + JSON.stringify({ error: 'Access denied: Invalid path' }), |
| 54 | + { status: 403, headers: { 'Content-Type': 'application/json' } } |
| 55 | + ) |
| 56 | + } |
| 57 | + |
| 58 | + const result = await sbx.commands.run(`cat "${normalizedPath}"`) |
52 | 59 |
|
53 | 60 | if (result.exitCode !== 0) { |
54 | 61 | console.error('Error reading file:', result.stderr) |
55 | 62 | return new Response( |
56 | 63 | JSON.stringify({ |
57 | 64 | error: 'Failed to read file', |
58 | 65 | details: result.stderr, |
59 | | - path: fullPath |
| 66 | + path: normalizedPath |
60 | 67 | }), |
61 | 68 | { status: 404, headers: { 'Content-Type': 'application/json' } } |
62 | 69 | ) |
@@ -117,12 +124,21 @@ export async function POST( |
117 | 124 | // Connect to existing sandbox |
118 | 125 | const sbx = await Sandbox.connect(sbxId) |
119 | 126 |
|
120 | | - // Write file content to sandbox |
121 | | - const fullPath = filePath.startsWith('/') |
122 | | - ? filePath.substring(1) |
123 | | - : filePath |
| 127 | + // Sanitize path to prevent path traversal attacks |
| 128 | + const userDir = '/home/user' |
| 129 | + const normalizedPath = path.normalize(path.join(userDir, filePath)) |
| 130 | + |
| 131 | + // Verify the normalized path is still within the allowed directory |
| 132 | + if (!normalizedPath.startsWith(userDir + '/') && normalizedPath !== userDir) { |
| 133 | + return new Response( |
| 134 | + JSON.stringify({ error: 'Access denied: Invalid path' }), |
| 135 | + { status: 403, headers: { 'Content-Type': 'application/json' } } |
| 136 | + ) |
| 137 | + } |
124 | 138 |
|
125 | | - await sbx.files.write(fullPath, content) |
| 139 | + // E2B files.write expects path relative to /home/user |
| 140 | + const relativePath = normalizedPath.substring(userDir.length + 1) |
| 141 | + await sbx.files.write(relativePath, content) |
126 | 142 |
|
127 | 143 | return new Response( |
128 | 144 | JSON.stringify({ |
|
0 commit comments