Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
142795a
test(reliability): reject invalid runtime image config
seonghobae Aug 11, 2026
be171aa
fix(reliability): validate runtime image config
seonghobae Aug 11, 2026
3995d33
test(reliability): reject malformed image config containers
seonghobae Aug 11, 2026
707221a
fix(reliability): validate runtime image config shape
seonghobae Aug 11, 2026
f18fd40
test(reliability): reject unknown image config keys
seonghobae Aug 11, 2026
9e1611b
test(reliability): redact image config key reflection failures
seonghobae Aug 11, 2026
560cbd5
fix(reliability): reject unknown image config keys
seonghobae Aug 11, 2026
8e58659
test(reliability): define build options runtime boundary RED
seonghobae Aug 11, 2026
f2c480b
test(reliability): cover build options reflection boundary
seonghobae Aug 11, 2026
c4ba62d
fix(reliability): validate build extension options
seonghobae Aug 11, 2026
013958b
fix(ci): remove unreachable build-options branch
seonghobae Aug 11, 2026
fbc0405
test(reliability): cover revoked extension config proxies
seonghobae Aug 11, 2026
f6830e4
fix(reliability): redact revoked extension config proxies
seonghobae Aug 11, 2026
c2d6219
merge(main): synchronize runtime image configuration lane
seonghobae Aug 16, 2026
85aac6e
merge: synchronize image configuration hardening with protected main
seonghobae Aug 18, 2026
6e28769
chore(sync): integrate protected security baseline
seonghobae Aug 25, 2026
0f94374
Merge remote-tracking branch 'origin/main' into codex/pr216-restack
seonghobae Sep 4, 2026
4f25110
test(ci): cover event-specific Python matrix
seonghobae Sep 4, 2026
83eca56
test(ci): bind Python matrix to event
seonghobae Sep 4, 2026
9576358
revert(ci): restore Office contract owner
seonghobae Sep 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions src/extensions/buildExtensionsRuntimeBoundary.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { describe, expect, it } from 'vitest';
import { buildExtensions, type BuildExtensionsOptions } from './kit.js';

const INVALID_BUILD_EXTENSIONS_CONFIGURATION =
'Build extensions configuration is invalid.';

function expectInvalidBuildExtensionsOptions(options: unknown): void {
expect(() =>
buildExtensions(options as BuildExtensionsOptions),
).toThrowError(new RangeError(INVALID_BUILD_EXTENSIONS_CONFIGURATION));
}

describe('buildExtensions runtime configuration boundary', () => {
it.each([null, [], 'invalid', 0, false])(
'rejects malformed top-level option container %p through one stable error',
(options) => {
expectInvalidBuildExtensionsOptions(options);
},
);

it('redacts revoked top-level proxy shape failures', () => {
const { proxy: options, revoke } = Proxy.revocable({}, {});
revoke();

expectInvalidBuildExtensionsOptions(options);
});

it('redacts revoked image proxy shape failures', () => {
const { proxy: image, revoke } = Proxy.revocable({}, {});
revoke();

expect(() => buildExtensions({ image })).toThrowError(
new RangeError('Image configuration is invalid.'),
);
});

it('rejects accessor-backed options without evaluating the accessor', () => {
let reads = 0;
const options = {} as BuildExtensionsOptions;
Object.defineProperty(options, 'image', {
enumerable: true,
get() {
reads += 1;
return { maxSizeBytes: 1_024 };
},
});

expectInvalidBuildExtensionsOptions(options);
expect(reads).toBe(0);
});

it('rejects non-enumerable top-level option properties', () => {
const options = {} as BuildExtensionsOptions;
Object.defineProperty(options, 'disableHistory', {
enumerable: false,
value: true,
});

expectInvalidBuildExtensionsOptions(options);
});

it('rejects unknown and symbol option keys instead of silently ignoring them', () => {
expectInvalidBuildExtensionsOptions({ maxSzieBytes: 1_024 });

const symbolKey = Symbol('private-build-options');
const options: Record<PropertyKey, unknown> = {};
options[symbolKey] = true;
expectInvalidBuildExtensionsOptions(options);
});

it('redacts hostile own-key reflection failures', () => {
const options = new Proxy(
{},
{
ownKeys() {
throw new Error('private build-options own-key detail');
},
},
);

expectInvalidBuildExtensionsOptions(options);
});

it('redacts hostile property-descriptor reflection failures', () => {
const options = new Proxy(
{},
{
ownKeys() {
return ['image'];
},
getOwnPropertyDescriptor() {
throw new Error('private build-options descriptor detail');
},
},
);

expectInvalidBuildExtensionsOptions(options);
});

it('rejects a reported option key without an own descriptor', () => {
const options = new Proxy(
{},
{
ownKeys() {
return ['image'];
},
getOwnPropertyDescriptor() {
return undefined;
},
},
);

expectInvalidBuildExtensionsOptions(options);
});
});
127 changes: 127 additions & 0 deletions src/extensions/imageConfigRuntime.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { describe, expect, it } from 'vitest';
import { buildExtensions } from './kit.js';

describe('runtime image configuration', () => {
it.each([
['maxSizeBytes', Number.NaN],
['maxSizeBytes', -1],
['maxSizeBytes', 1.5],
['maxDimension', Number.POSITIVE_INFINITY],
['maxDimension', -1],
['maxDimension', 1.5],
] as const)('rejects invalid %s values before extension setup', (key, value) => {
expect(() =>
buildExtensions({
image: { [key]: value } as never,
}),
).toThrowError(new RangeError(`Image ${key} configuration is invalid.`));
});

it.each([Number.NaN, Number.NEGATIVE_INFINITY, -0.1, 1.1])(
'rejects invalid quality %s before extension setup',
(quality) => {
expect(() =>
buildExtensions({ image: { quality } }),
).toThrowError(new RangeError('Image quality configuration is invalid.'));
},
);

it.each([null, [], 'invalid', 0, false])(
'rejects malformed image configuration containers without coercion',
(image) => {
expect(() => buildExtensions({ image: image as never })).toThrowError(
new RangeError('Image configuration is invalid.'),
);
},
);

it('rejects accessor-backed image configuration without evaluating the accessor', () => {
let reads = 0;
const image = {};
Object.defineProperty(image, 'maxSizeBytes', {
enumerable: true,
get() {
reads += 1;
return 1024;
},
});

expect(() => buildExtensions({ image })).toThrowError(
new RangeError('Image configuration is invalid.'),
);
expect(reads).toBe(0);
});

it('rejects non-enumerable image configuration data properties', () => {
const image = {};
Object.defineProperty(image, 'quality', {
enumerable: false,
value: 0.8,
});

expect(() => buildExtensions({ image })).toThrowError(
new RangeError('Image configuration is invalid.'),
);
});

it('rejects unknown runtime configuration keys instead of silently weakening policy', () => {
const image = {
maxSizeBytes: 1024,
maxSzieBytes: 16,
} as never;

expect(() => buildExtensions({ image })).toThrowError(
new RangeError('Image configuration is invalid.'),
);
});

it('rejects own symbol configuration keys without reflecting their identity', () => {
const privatePolicyKey = Symbol('private-policy-key');
const image: Record<PropertyKey, unknown> = { maxSizeBytes: 1024 };
image[privatePolicyKey] = 16;

expect(() => buildExtensions({ image: image as never })).toThrowError(
new RangeError('Image configuration is invalid.'),
);
});

it('redacts own-key reflection failures at the image configuration boundary', () => {
const image = new Proxy(
{},
{
ownKeys() {
throw new Error('private own-key reflection detail');
},
},
);

expect(() => buildExtensions({ image })).toThrowError(
new RangeError('Image configuration is invalid.'),
);
});

it('redacts reflection failures at the image configuration boundary', () => {
const image = new Proxy(
{},
{
getOwnPropertyDescriptor() {
throw new Error('private reflection detail');
},
},
);

expect(() => buildExtensions({ image })).toThrowError(
new RangeError('Image configuration is invalid.'),
);
});

it('preserves valid disabled and boundary configuration', () => {
const image = buildExtensions({
image: { maxSizeBytes: 0, maxDimension: 0, quality: 1 },
}).find((extension) => extension.name === 'image');

expect(image?.options.maxSizeBytes).toBe(0);
expect(image?.options.maxDimension).toBe(0);
expect(image?.options.quality).toBe(1);
});
});
Loading
Loading