mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2026-08-18 17:04:50 -05:00
Force download for SVG
Prevent XSS when the file is opened directly
This commit is contained in:
@@ -953,6 +953,37 @@ describe('Test config', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('SVG', function () {
|
||||||
|
let svgUrl: string
|
||||||
|
|
||||||
|
it('Should update instance favicon with an SVG', async function () {
|
||||||
|
await server.config.updateInstanceLogo({ type: 'favicon', fixture: 'peertube.svg' })
|
||||||
|
|
||||||
|
const htmlConfig = await server.config.getConfig()
|
||||||
|
|
||||||
|
const favicons = htmlConfig.instance.logo.filter(l => l.type === 'favicon')
|
||||||
|
expect(favicons).to.have.lengthOf(1)
|
||||||
|
expect(favicons[0].isFallback).to.be.false
|
||||||
|
|
||||||
|
svgUrl = favicons[0].fileUrl
|
||||||
|
expect(svgUrl).to.match(/\.svg$/)
|
||||||
|
|
||||||
|
await testFileExistsOnFSOrNot(server, 'uploads/images', basename(svgUrl), true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should serve the SVG with a Content-Disposition attachment header', async function () {
|
||||||
|
const res = await makeRawRequest({ url: svgUrl, expectedStatus: HttpStatusCode.OK_200 })
|
||||||
|
|
||||||
|
expect(res.headers['content-disposition']).to.equal('attachment')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should remove the SVG favicon', async function () {
|
||||||
|
await server.config.deleteInstanceLogo({ type: 'favicon' })
|
||||||
|
|
||||||
|
await testFileExistsOnFSOrNot(server, 'uploads/images', basename(svgUrl), false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('Default logo', function () {
|
describe('Default logo', function () {
|
||||||
before(async function () {
|
before(async function () {
|
||||||
await server.config.updateInstanceImage({ type: ActorImageType.AVATAR, fixture: 'avatar.png' })
|
await server.config.updateInstanceImage({ type: ActorImageType.AVATAR, fixture: 'avatar.png' })
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { processImage, processSVG } from '@peertube/peertube-server/core/helpers
|
|||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { ensureDir, remove } from 'fs-extra/esm'
|
import { ensureDir, remove } from 'fs-extra/esm'
|
||||||
import { readFile, writeFile } from 'fs/promises'
|
import { readFile, writeFile } from 'fs/promises'
|
||||||
|
import { tmpdir } from 'os'
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
import sharp from 'sharp'
|
import sharp from 'sharp'
|
||||||
|
|
||||||
@@ -123,7 +124,7 @@ describe('Image helpers', function () {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('SVG sanitization', function () {
|
describe('SVG sanitization', function () {
|
||||||
const svgDir = join(root(), 'test-svg')
|
const svgDir = join(tmpdir(), 'test-svg')
|
||||||
const svgSrc = join(svgDir, 'input.svg')
|
const svgSrc = join(svgDir, 'input.svg')
|
||||||
const svgDest = join(svgDir, 'output.svg')
|
const svgDest = join(svgDir, 'output.svg')
|
||||||
|
|
||||||
|
|||||||
@@ -103,7 +103,15 @@ staticRouter.use(
|
|||||||
|
|
||||||
staticRouter.use(
|
staticRouter.use(
|
||||||
STATIC_PATHS.UPLOAD_IMAGES,
|
STATIC_PATHS.UPLOAD_IMAGES,
|
||||||
express.static(DIRECTORIES.UPLOAD_IMAGES, { fallthrough: false }),
|
express.static(DIRECTORIES.UPLOAD_IMAGES, {
|
||||||
|
fallthrough: false,
|
||||||
|
setHeaders: (res, filePath) => {
|
||||||
|
// Force a download instead of inline rendering to prevent XSS if the svg is opened directly
|
||||||
|
if (filePath.endsWith('.svg')) {
|
||||||
|
res.setHeader('Content-Disposition', 'attachment')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
handleStaticError
|
handleStaticError
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user