Skip to content

Commit d91771f

Browse files
committed
fix(core): validate protobuf SHA-256 hash lengths
1 parent e2d2e63 commit d91771f

2 files changed

Lines changed: 21 additions & 0 deletions

File tree

packages/core/src/configuration/ufc-protobuf.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,17 @@ describe('UFC protobuf decoder', () => {
366366
).toMatchObject({ value: false, reason: 'ERROR', errorCode: 'PARSE_ERROR' })
367367
})
368368

369+
it.each([11, 12] as const)('reports an invalid SHA-256 hash length for condition kind %s', (conditionKind) => {
370+
expect(
371+
evaluateBoolean({ conditionKind, shaHashes: ['00'] }, { targetingKey: 'user', country: 'US' })
372+
).toMatchObject({
373+
value: false,
374+
reason: 'ERROR',
375+
errorCode: 'PARSE_ERROR',
376+
errorMessage: 'SHA-256 hashes must contain 32 bytes',
377+
})
378+
})
379+
369380
it('lazily compiles each regex once per configuration', () => {
370381
const configuration = decodeRules({ conditionKind: 7 })
371382
const regexes = configuration.regexes

packages/core/src/evaluation/evaluateProtobufConfiguration.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { UFC_REASON, UFC_VARIATION_TYPE } from './ufc-enums'
3131
const SUPPORTED_FEATURE_LEVEL = 0
3232
const compiledRegexCache = new WeakMap<FlagsConfiguration, Map<number, RegExp | null>>()
3333
const validatedSortedArrays = new WeakSet<object>()
34+
const validatedSha256Arrays = new WeakSet<object>()
3435

3536
export function evaluateProtobufConfiguration<T extends FlagValueType>(
3637
configuration: FlagsConfiguration,
@@ -443,10 +444,19 @@ function isJsonValue(value: unknown): value is FlagValue {
443444
}
444445

445446
function containsBytes(values: Uint8Array[], value: Uint8Array): boolean {
447+
validateSha256Hashes(values)
446448
ensureSorted(values, compareBytes, 'SHA-256 hashes')
447449
return containsSorted(values, (candidate) => compareBytes(candidate, value))
448450
}
449451

452+
function validateSha256Hashes(values: Uint8Array[]): void {
453+
if (validatedSha256Arrays.has(values)) return
454+
if (values.some((hash) => hash.length !== 32)) {
455+
throw new FlagConfigurationError('SHA-256 hashes must contain 32 bytes')
456+
}
457+
validatedSha256Arrays.add(values)
458+
}
459+
450460
function compareStrings(left: string, right: string): number {
451461
return left === right ? 0 : left < right ? -1 : 1
452462
}

0 commit comments

Comments
 (0)