Skip to content
This repository has been archived by the owner on Feb 12, 2024. It is now read-only.

Commit

Permalink
fix: do not write to prefix outside of output directory (#3417)
Browse files Browse the repository at this point in the history
Adds a check to prevent overwriting files not under the output
directory, which you can override with a `--force` option.
  • Loading branch information
achingbrain authored Nov 23, 2020
1 parent 1529da9 commit 75dd865
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 1 deletion.
11 changes: 10 additions & 1 deletion packages/ipfs-cli/src/commands/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,29 @@ module.exports = {
type: 'string',
default: process.cwd()
},
force: {
alias: 'f',
type: 'boolean',
default: false
},
timeout: {
type: 'string',
coerce: parseDuration
}
},

async handler ({ ctx: { ipfs, print }, ipfsPath, output, timeout }) {
async handler ({ ctx: { ipfs, print }, ipfsPath, output, force, timeout }) {
print(`Saving file(s) ${ipfsPath}`)

for await (const file of ipfs.get(ipfsPath, {
timeout
})) {
const fullFilePath = path.join(output, file.path)

if (fullFilePath.substring(0, output.length) !== output && !force) {
throw new Error(`File prefix invalid, would write to files outside of ${output}, pass --force to override`)
}

if (file.content) {
await fs.promises.mkdir(path.join(output, path.dirname(file.path)), { recursive: true })
await pipe(
Expand Down
34 changes: 34 additions & 0 deletions packages/ipfs-cli/test/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,38 @@ describe('get', () => {

await clean(outPath)
})

it('should not get file with path traversal characters that result in leaving the output directory', async () => {
ipfs.get.withArgs(cid.toString(), defaultOptions).returns([{
path: '../foo.txt',
content: function * () {
yield buf
}
}])

const outPath = path.join(process.cwd(), 'derp')

await expect(cli(`get ${cid} --output ${outPath}`, { ipfs })).to.eventually.be.rejectedWith(/File prefix invalid/)
})

it('should get file with path traversal characters that result in leaving the output directory when forced', async () => {
ipfs.get.withArgs(cid.toString(), defaultOptions).returns([{
path: '../foo.txt',
content: function * () {
yield buf
}
}])

const dir = path.join(process.cwd(), 'derp')
const outPath = path.join(process.cwd(), 'derp', 'herp')
await clean(dir)

const out = await cli(`get ${cid} --output ${outPath} --force`, { ipfs })
expect(out)
.to.equal(`Saving file(s) ${cid}\n`)

expect(fs.readFileSync(path.join(dir, 'foo.txt'))).to.deep.equal(buf)

await clean(dir)
})
})

0 comments on commit 75dd865

Please sign in to comment.