diff --git a/src/apps.js b/src/apps.js index ab0fbcf3d..2df184803 100644 --- a/src/apps.js +++ b/src/apps.js @@ -481,7 +481,8 @@ function validateEnv(env) { return null; } -async function checkStorage(volumeId, prefix) { +async function checkStorage(app, volumeId, prefix) { + assert.strictEqual(typeof app, 'object'); assert.strictEqual(typeof volumeId, 'string'); assert.strictEqual(typeof prefix, 'string'); @@ -495,10 +496,14 @@ async function checkStorage(volumeId, prefix) { if (prefix.endsWith('/')) throw new BoxError(BoxError.BAD_FIELD, `prefix "${prefix}" contains trailing slash`); if (prefix !== '' && path.normalize(prefix) !== prefix) throw new BoxError(BoxError.BAD_FIELD, `prefix "${prefix}" is not a normalized path`); - const storageDir = path.join(volume.hostPath, prefix); - const [error] = await safe(shell.promises.sudo('checkStorage', [ CHECKVOLUME_CMD, storageDir ], {})); - if (error && error.code === 2) throw new BoxError(BoxError.BAD_FIELD, `Target directory ${storageDir} is not empty`); - if (error && error.code === 3) throw new BoxError(BoxError.BAD_FIELD, `Target directory ${storageDir} does not support chown`); + const sourceDir = await getStorageDir(app); + const targetDir = path.join(volume.hostPath, prefix); + const rel = path.relative(sourceDir, targetDir); + if (!rel.startsWith('../') && rel.split('/').length > 1) throw new BoxError(BoxError.BAD_FIELD, 'Only one level subdirectory moves are supported'); + + const [error] = await safe(shell.promises.sudo('checkStorage', [ CHECKVOLUME_CMD, targetDir ], {})); + if (error && error.code === 2) throw new BoxError(BoxError.BAD_FIELD, `Target directory ${targetDir} is not empty`); + if (error && error.code === 3) throw new BoxError(BoxError.BAD_FIELD, `Target directory ${targetDir} does not support chown`); return null; } @@ -1808,7 +1813,7 @@ async function setStorage(app, volumeId, volumePrefix, auditSource) { if (error) throw error; if (volumeId) { - await checkStorage(volumeId, volumePrefix); + await checkStorage(app, volumeId, volumePrefix); } else { volumeId = volumePrefix = null; } diff --git a/src/scripts/mvvolume.sh b/src/scripts/mvvolume.sh index 2081bfc9a..e53e10659 100755 --- a/src/scripts/mvvolume.sh +++ b/src/scripts/mvvolume.sh @@ -27,7 +27,7 @@ if [[ "${BOX_ENV}" == "test" ]]; then fi # copy and remove - this way if the copy fails, the original is intact -# the find logic is so that move to a subdir works (and we also move hidden files) +# the find logic is so that move to a one level subdir works (and we also move hidden files) find "${source_dir}" -maxdepth 1 -mindepth 1 -not -wholename "${target_dir}" -exec cp -ar '{}' "${target_dir}" \; find "${source_dir}" -maxdepth 1 -mindepth 1 -not -wholename "${target_dir}" -exec rm -rf '{}' \; # this will fail if target is a subdir or if source is a mountpoint