fix(desktop): address security scan findings
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import type { HermesConfigRecord } from '@/types/hermes'
|
||||
|
||||
import { getNested, setNested } from './helpers'
|
||||
|
||||
describe('settings helpers', () => {
|
||||
it('reads and writes nested config paths', () => {
|
||||
const config: HermesConfigRecord = { display: { theme: 'mono' } }
|
||||
const next = setNested(config, 'display.theme', 'slate')
|
||||
|
||||
expect(getNested(next, 'display.theme')).toBe('slate')
|
||||
expect(getNested(config, 'display.theme')).toBe('mono')
|
||||
})
|
||||
|
||||
it('rejects prototype-polluting config paths', () => {
|
||||
const config: HermesConfigRecord = {}
|
||||
|
||||
expect(() => setNested(config, '__proto__.polluted', true)).toThrow('Unsafe config path')
|
||||
expect(() => setNested(config, 'constructor.prototype.polluted', true)).toThrow('Unsafe config path')
|
||||
expect(({} as Record<string, unknown>).polluted).toBeUndefined()
|
||||
})
|
||||
})
|
||||
@@ -23,10 +23,22 @@ export const providerGroup = (key: string) => PROVIDER_GROUPS.find(g => key.star
|
||||
|
||||
export const providerPriority = (name: string) => PROVIDER_GROUPS.find(g => g.name === name)?.priority ?? 99
|
||||
|
||||
const POLLUTING_PATH_PARTS = new Set(['__proto__', 'constructor', 'prototype'])
|
||||
|
||||
function configPathParts(path: string): string[] {
|
||||
const parts = path.split('.')
|
||||
|
||||
if (parts.some(part => !part || POLLUTING_PATH_PARTS.has(part))) {
|
||||
throw new Error(`Unsafe config path: ${path}`)
|
||||
}
|
||||
|
||||
return parts
|
||||
}
|
||||
|
||||
export function getNested(obj: HermesConfigRecord, path: string): unknown {
|
||||
let cur: unknown = obj
|
||||
|
||||
for (const part of path.split('.')) {
|
||||
for (const part of configPathParts(path)) {
|
||||
if (cur == null || typeof cur !== 'object') {
|
||||
return undefined
|
||||
}
|
||||
@@ -39,7 +51,7 @@ export function getNested(obj: HermesConfigRecord, path: string): unknown {
|
||||
|
||||
export function setNested(obj: HermesConfigRecord, path: string, value: unknown): HermesConfigRecord {
|
||||
const clone = structuredClone(obj)
|
||||
const parts = path.split('.')
|
||||
const parts = configPathParts(path)
|
||||
let cur: Record<string, unknown> = clone
|
||||
|
||||
for (let i = 0; i < parts.length - 1; i += 1) {
|
||||
|
||||
Reference in New Issue
Block a user