fix: security value problem

This commit is contained in:
马登山
2026-03-09 15:47:26 +08:00
parent 2956932eb6
commit e144f3fdd4
7 changed files with 70 additions and 17 deletions
+1
View File
@@ -0,0 +1 @@
v22
+2
View File
@@ -15,6 +15,8 @@
## Build, Test, and Development Commands
- **Node version requirement**: Before running `pnpm` commands (especially checks/tests), run `nvm use v22` in this repository.
- `pnpm dev` – start the Next.js development server with hot reload.
- `pnpm build` – create a production build.
- `pnpm start` – run the production bundle locally.
+9 -3
View File
@@ -47,8 +47,14 @@ export function AccessKeysNewItem({ visible, onVisibleChange, onSuccess, onNotic
React.useEffect(() => {
if (visible) {
setAccessKey(makeRandomString(20))
setSecretKey(makeRandomString(40))
try {
setAccessKey(makeRandomString(20))
setSecretKey(makeRandomString(40))
} catch {
setAccessKey("")
setSecretKey("")
message.error(t("Failed to generate secure random keys"))
}
setName("")
setDescription("")
setExpiry(null)
@@ -63,7 +69,7 @@ export function AccessKeysNewItem({ visible, onVisibleChange, onSuccess, onNotic
setPolicy("{}")
})
}
}, [visible, api])
}, [visible, api, message, t])
const closeModal = () => {
onVisibleChange(false)
+3 -2
View File
@@ -1,5 +1,6 @@
import { DeleteObjectCommand, DeleteObjectsCommand, ListObjectsV2Command, ListObjectVersionsCommand, S3Client } from "@aws-sdk/client-s3"
import type { ManagedTask, TaskHandler, TaskLifecycleStatus } from "./task-manager"
import { createTaskId } from "./task-id"
export type DeleteStatus = "pending" | "running" | "completed" | "failed" | "canceled"
@@ -203,7 +204,7 @@ export function createDeleteTaskHelpers(s3Client: S3Client, config: DeleteTaskCo
prefix?: string,
): DeleteTask[] =>
items.map((item) => ({
id: `${Date.now()}-${Math.random().toString(36).slice(2, 11)}-${item.key}-${item.versionId ?? "latest"}`,
id: createTaskId(`${item.key}-${item.versionId ?? "latest"}`),
kind: "delete" as const,
key: item.key,
versionId: item.versionId,
@@ -244,7 +245,7 @@ export function createDeleteTaskHelpers(s3Client: S3Client, config: DeleteTaskCo
bucketName: string,
options?: { forceDelete?: boolean },
): FolderDeleteTask => ({
id: `${Date.now()}-${Math.random().toString(36).slice(2, 11)}-${prefix}`,
id: createTaskId(prefix),
kind: "delete-folder" as const,
bucketName,
prefix,
+18 -11
View File
@@ -33,19 +33,26 @@ function convertToBytes(value: string, unit: string, fromK8s = false): number {
}
export function makeRandomString(length = 20): string {
let initstr = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
const arr = initstr.split("")
const alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
if (length <= 0) return ""
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1))
const current = arr[i]
const swapWith = arr[j]
if (current !== undefined && swapWith !== undefined) {
arr[i] = swapWith
arr[j] = current
const cryptoApi = globalThis.crypto
if (!cryptoApi?.getRandomValues) {
throw new Error("Secure random generator is not available")
}
const result: string[] = []
const alphabetLength = alphabet.length
const maxByte = 256 - (256 % alphabetLength)
while (result.length < length) {
const bytes = cryptoApi.getRandomValues(new Uint8Array(length))
for (const byte of bytes) {
if (byte >= maxByte) continue
result.push(alphabet[byte % alphabetLength] ?? "")
if (result.length === length) break
}
}
initstr = arr.join("")
return initstr.slice(0, length)
return result.join("")
}
+35
View File
@@ -0,0 +1,35 @@
const FALLBACK_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyz"
function createSecureSuffix(length = 12): string {
const cryptoApi = globalThis.crypto
if (!cryptoApi?.getRandomValues) {
throw new Error("Secure random generator is not available")
}
const chars: string[] = []
const alphabetLength = FALLBACK_ALPHABET.length
const maxByte = 256 - (256 % alphabetLength)
while (chars.length < length) {
const bytes = cryptoApi.getRandomValues(new Uint8Array(length))
for (const byte of bytes) {
if (byte >= maxByte) continue
chars.push(FALLBACK_ALPHABET[byte % alphabetLength] ?? "")
if (chars.length === length) break
}
}
return chars.join("")
}
export function createTaskId(seed: string): string {
const prefix = Date.now()
const cryptoApi = globalThis.crypto
if (cryptoApi?.randomUUID) {
return `${prefix}-${cryptoApi.randomUUID()}-${seed}`
}
return `${prefix}-${createSecureSuffix()}-${seed}`
}
+2 -1
View File
@@ -7,6 +7,7 @@ import {
} from "@aws-sdk/client-s3"
import type { ManagedTask, TaskHandler, TaskLifecycleStatus } from "./task-manager"
import { formatBytes } from "./functions"
import { createTaskId } from "./task-id"
export type UploadStatus = "pending" | "running" | "completed" | "failed" | "canceled" | "paused"
@@ -105,7 +106,7 @@ export function createUploadTaskHelpers(s3Client: S3Client, config: UploadTaskCo
existKeys.add(`${bucketName}/${item.key}`)
const displayName = item.key.split("/").pop() ?? item.key
return {
id: `${Date.now()}-${Math.random().toString(36).slice(2, 11)}-${item.key}`,
id: createTaskId(item.key),
kind: "upload" as const,
file: item.file,
key: item.key,