Skip to content

Commit 2e5b086

Browse files
authored
Use 128-bit random base64url identifiers for images & files, not uuid (#9079)
1 parent 0f7760f commit 2e5b086

File tree

5 files changed

+23
-45
lines changed

5 files changed

+23
-45
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@keystone-6/core': major
3+
---
4+
5+
Changes `file` and `image` to use random 128-bit `base64url` identifiers by default, not `uuid`

packages/core/src/lib/assets/createFilesContext.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
1-
import crypto from 'crypto'
1+
import { randomBytes } from 'node:crypto'
22

33
import type { KeystoneConfig, FilesContext } from '../../types'
44
import { localFileAssetsAPI } from './local'
55
import { s3FileAssetsAPI } from './s3'
66
import type { FileAdapter } from './types'
77

8-
const defaultTransformName = (path: string) => {
9-
// Appends a UUID to the filename so that people can't brute-force guess stored filenames
10-
//
11-
// This regex lazily matches for any characters that aren't a new line
8+
// appends a 128-bit random identifier to the filename to prevent guessing
9+
function defaultTransformName (path: string) {
10+
// this regex lazily matches for any characters that aren't a new line
1211
// it then optionally matches the last instance of a "." symbol
1312
// followed by any alphanumerical character before the end of the string
1413
const [, name, ext] = path.match(/^([^:\n].*?)(\.[A-Za-z0-9]{0,10})?$/) as RegExpMatchArray
1514

16-
const id = crypto.randomBytes(12).toString('base64url').slice(0, 12)
17-
15+
const id = randomBytes(16).toString('base64url')
1816
const urlSafeName = name.replace(/[^A-Za-z0-9]/g, '-')
1917
if (ext) return `${urlSafeName}-${id}${ext}`
2018
return `${urlSafeName}-${id}`
@@ -46,11 +44,11 @@ export function createFilesContext (config: KeystoneConfig): FilesContext {
4644
},
4745
getDataFromStream: async (stream, originalFilename) => {
4846
const storageConfig = config.storage![storageString]
49-
const { transformName = defaultTransformName } = storageConfig as typeof storageConfig & {
47+
const { transformName = defaultTransformName } = storageConfig as (typeof storageConfig) & {
5048
type: 'file'
5149
}
52-
const filename = await transformName(originalFilename)
5350

51+
const filename = await transformName(originalFilename)
5452
const { filesize } = await adapter.upload(stream, filename)
5553
return { filename, filesize }
5654
},

packages/core/src/lib/assets/createImagesContext.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
import { v4 as uuid } from 'uuid'
1+
import { randomBytes } from 'node:crypto'
22
import imageSize from 'image-size'
3+
34
import type { KeystoneConfig, ImagesContext } from '../../types'
45
import type { ImageAdapter } from './types'
56
import { localImageAssetsAPI } from './local'
67
import { s3ImageAssetsAPI } from './s3'
78
import { streamToBuffer } from './utils'
89

10+
function defaultTransformName (path: string) {
11+
return randomBytes(16).toString('base64url')
12+
}
13+
914
async function getImageMetadataFromBuffer (buffer: Buffer) {
1015
const fileType = await (await import('file-type')).fileTypeFromBuffer(buffer)
1116
if (!fileType) {
@@ -50,13 +55,12 @@ export function createImagesContext (config: KeystoneConfig): ImagesContext {
5055
},
5156
getDataFromStream: async (stream, originalFilename) => {
5257
const storageConfig = config.storage![storageString]
53-
const { transformName = () => uuid() } = storageConfig
58+
const { transformName = defaultTransformName } = storageConfig
5459

5560
const buffer = await streamToBuffer(stream)
5661
const { extension, ...rest } = await getImageMetadataFromBuffer(buffer)
5762

5863
const id = await transformName(originalFilename, extension)
59-
6064
await adapter.upload(buffer, id, extension)
6165
return { id, extension, ...rest }
6266
},

pnpm-lock.yaml

Lines changed: 3 additions & 32 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/api-tests/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"@types/mime": "^2.0.3",
3636
"@types/superagent": "^4.1.15",
3737
"@types/supertest": "^2.0.11",
38-
"@types/uuid": "^8.3.1",
38+
"@types/uuid": "^9.0.0",
3939
"express": "^4.17.1"
4040
}
4141
}

0 commit comments

Comments
 (0)