{"version":3,"file":"readOutputFiles.cjs","names":["path","fs","encodeFileForTestCaseResult","sandboxUserName","isContainedPath"],"sources":["../../src/helpers/readOutputFiles.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { TestCaseResult } from '../types/testCaseResult.js';\n\nimport { encodeFileForTestCaseResult } from './printTestCaseResult.js';\nimport { isContainedPath } from './safeFs.js';\nimport { sandboxUserName } from './sandboxUser.js';\n\nexport async function readOutputFiles(\n  cwd: string,\n  outputFilePaths: readonly string[]\n): Promise<NonNullable<TestCaseResult['outputFiles']>> {\n  const outputFiles: NonNullable<TestCaseResult['outputFiles']> = [];\n  for (const filePath of outputFilePaths) {\n    try {\n      const resolvedPath = path.join(cwd, filePath);\n      if (!(await isSafeSubmissionOutputPath(cwd, resolvedPath))) continue;\n      const buffer = await fs.promises.readFile(resolvedPath);\n      outputFiles.push(encodeFileForTestCaseResult(filePath, buffer));\n    } catch {\n      // file not found\n    }\n  }\n  return outputFiles;\n}\n\n/**\n * Whether the harness may read the given submission-created path. When submissions run as the\n * sandbox user while the harness is trusted, a submission could plant a symlink (or a symlinked\n * parent directory) escaping its working directory — e.g. to the 0700 problem directory — and the\n * privileged read would exfiltrate protected bytes, so only paths that resolve inside the working\n * directory are allowed. Without user separation the submission can read those targets itself, so\n * the check is skipped to keep authoring behavior unchanged.\n */\nexport async function isSafeSubmissionOutputPath(cwd: string, filePath: string): Promise<boolean> {\n  if (!sandboxUserName) return true;\n  try {\n    const realFilePath = await fs.promises.realpath(filePath);\n    const realCwd = await fs.promises.realpath(cwd);\n    return isContainedPath(realCwd, realFilePath);\n  } catch {\n    return false;\n  }\n}\n"],"mappings":"wPASA,eAAsB,EACpB,EACA,EACqD,CACrD,IAAM,EAA0D,CAAC,EACjE,IAAK,IAAM,KAAY,EACrB,GAAI,CACF,IAAM,EAAeA,EAAAA,QAAK,KAAK,EAAK,CAAQ,EAC5C,GAAI,CAAE,MAAM,EAA2B,EAAK,CAAY,EAAI,SAC5D,IAAM,EAAS,MAAMC,EAAAA,QAAG,SAAS,SAAS,CAAY,EACtD,EAAY,KAAKC,EAAAA,4BAA4B,EAAU,CAAM,CAAC,CAChE,MAAQ,CAER,CAEF,OAAO,CACT,CAUA,eAAsB,EAA2B,EAAa,EAAoC,CAChG,GAAI,CAACC,EAAAA,gBAAiB,MAAO,GAC7B,GAAI,CACF,IAAM,EAAe,MAAMF,EAAAA,QAAG,SAAS,SAAS,CAAQ,EAClD,EAAU,MAAMA,EAAAA,QAAG,SAAS,SAAS,CAAG,EAC9C,OAAOG,EAAAA,gBAAgB,EAAS,CAAY,CAC9C,MAAQ,CACN,MAAO,EACT,CACF"}