(relativeKey: string)
| 263 | * Throws PathTraversalError if the key is malicious (PSR M22186). |
| 264 | */ |
| 265 | export async function validateTeamMemKey(relativeKey: string): Promise<string> { |
| 266 | sanitizePathKey(relativeKey) |
| 267 | const teamDir = getTeamMemPath() |
| 268 | const fullPath = join(teamDir, relativeKey) |
| 269 | // First pass: normalize .. segments and check string-level containment. |
| 270 | const resolvedPath = resolve(fullPath) |
| 271 | if (!resolvedPath.startsWith(teamDir)) { |
| 272 | throw new PathTraversalError( |
| 273 | `Key escapes team memory directory: "${relativeKey}"`, |
| 274 | ) |
| 275 | } |
| 276 | // Second pass: resolve symlinks and verify real containment. |
| 277 | const realPath = await realpathDeepestExisting(resolvedPath) |
| 278 | if (!(await isRealPathWithinTeamDir(realPath))) { |
| 279 | throw new PathTraversalError( |
| 280 | `Key escapes team memory directory via symlink: "${relativeKey}"`, |
| 281 | ) |
| 282 | } |
| 283 | return resolvedPath |
| 284 | } |
| 285 | |
| 286 | /** |
| 287 | * Check if a file path is within the team memory directory |
no test coverage detected