Skip to content

Commit

Permalink
fix: sanitize asset filenames
Browse files Browse the repository at this point in the history
  • Loading branch information
dominikg committed Aug 18, 2022
1 parent 21515f1 commit b0e2516
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 1 deletion.
19 changes: 18 additions & 1 deletion packages/vite/src/node/plugins/asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ export function assetFileNamesToFileName(
return hash

case '[name]':
return name
return sanitizeFileName(name)
}
throw new Error(
`invalid placeholder ${placeholder} in assetFileNames "${assetFileNames}"`
Expand All @@ -335,6 +335,23 @@ export function assetFileNamesToFileName(
return fileName
}

// taken from https://github.com/rollup/rollup/blob/a8647dac0fe46c86183be8596ef7de25bc5b4e4b/src/utils/sanitizeFileName.ts
// https://datatracker.ietf.org/doc/html/rfc2396
// eslint-disable-next-line no-control-regex
const INVALID_CHAR_REGEX = /[\x00-\x1F\x7F<>*#"{}|^[\]`;?:&=+$,]/g
const DRIVE_LETTER_REGEX = /^[a-z]:/i
function sanitizeFileName(name: string): string {
const match = DRIVE_LETTER_REGEX.exec(name)
const driveLetter = match ? match[0] : ''

// A `:` is only allowed as part of a windows drive letter (ex: C:\foo)
// Otherwise, avoid them because they can refer to NTFS alternate data streams.
return (
driveLetter +
name.substr(driveLetter.length).replace(INVALID_CHAR_REGEX, '_')
)
}

export const publicAssetUrlCache = new WeakMap<
ResolvedConfig,
// hash -> url
Expand Down
3 changes: 3 additions & 0 deletions playground/assets-sanitize/+circle.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions playground/assets-sanitize/__tests__/assets-sanitize.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { expect, test } from 'vitest'
import { getBg, isBuild, listAssets, page } from '~utils'

if (!isBuild) {
test('importing asset with special char in filename works', async () => {
expect(await getBg('.circle-bg')).toContain('+circle.svg')
expect(await page.textContent('.circle-bg')).toMatch('+circle.svg')
})
} else {
const expected_asset_name_RE = /_circle\.[\w]+\.svg/
test('importing asset with special char in filename works', async () => {
expect(await getBg('.circle-bg')).toMatch(expected_asset_name_RE)
expect(await page.textContent('.circle-bg')).toMatch(expected_asset_name_RE)
})
test('asset with special char in filename gets sanitized', async () => {
const svgs = listAssets().filter((a) => a.endsWith('.svg'))
expect(svgs[0]).toMatch(expected_asset_name_RE)
expect(svgs.length).toBe(1)
})
}
6 changes: 6 additions & 0 deletions playground/assets-sanitize/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<script type="module" src="./index.js"></script>
<h1>test element below should show a circle and it's url</h1>
<div
class="circle-bg"
style="background-repeat: no-repeat; padding-left: 2rem"
></div>
4 changes: 4 additions & 0 deletions playground/assets-sanitize/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import svg from './+circle.svg'
const el = document.body.querySelector('.circle-bg')
el.style.backgroundImage = `url(${svg})`
el.textContent = svg
11 changes: 11 additions & 0 deletions playground/assets-sanitize/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "test-assets-sanitize",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"debug": "node --inspect-brk ../../packages/vite/bin/vite",
"preview": "vite preview"
}
}
11 changes: 11 additions & 0 deletions playground/assets-sanitize/vite.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const { defineConfig } = require('vite')

module.exports = defineConfig({
build: {
//speed up build
minify: false,
target: 'esnext',
assetsInlineLimit: 0,
manifest: true
}
})

0 comments on commit b0e2516

Please sign in to comment.