fix(security): require fresh file parameter input (#11455)
This commit is contained in:
@@ -82,6 +82,27 @@ describe('ACP recipe param requests', () => {
|
||||
scope.finish();
|
||||
});
|
||||
|
||||
it('does not offer deeplink values for file parameters', async () => {
|
||||
setRecipeParameters({ document: '/tmp/private.txt', topic: 'release notes' });
|
||||
const scope = requests.beginConfiguredRecipeParameterScope()!;
|
||||
const request = recipeParamRequest('session-1', scope.id);
|
||||
request.parameters.unshift({
|
||||
key: 'document',
|
||||
description: 'Document',
|
||||
input_type: 'file',
|
||||
requirement: 'required',
|
||||
});
|
||||
|
||||
const response = requests.requestAcpRecipeParams(request);
|
||||
const [pendingRequest] = requests.getAcpRecipeParamRequestsSnapshot();
|
||||
|
||||
expect(pendingRequest.initialValues).toEqual({ topic: 'release notes' });
|
||||
|
||||
requests.cancelAcpRecipeParamRequest(pendingRequest.id);
|
||||
await expect(response).resolves.toEqual({ action: 'cancel' });
|
||||
scope.finish();
|
||||
});
|
||||
|
||||
it('allows same-session retries until a terminal response consumes the values', async () => {
|
||||
setRecipeParameters({ topic: 'release notes' });
|
||||
const scope = requests.beginConfiguredRecipeParameterScope()!;
|
||||
|
||||
@@ -81,8 +81,7 @@ export function beginConfiguredRecipeParameterScope(): ConfiguredRecipeParameter
|
||||
}
|
||||
|
||||
const configured = window.appConfig?.get('recipeParameters') as
|
||||
| Record<string, string>
|
||||
| undefined;
|
||||
Record<string, string> | undefined;
|
||||
if (!configured || Object.keys(configured).length === 0) {
|
||||
configuredParameterState = { status: 'consumed' };
|
||||
return undefined;
|
||||
@@ -122,8 +121,15 @@ function configuredParameterValues(request: RequestRecipeParams_unstable): {
|
||||
if (configuredParameterState.sessionId !== request.sessionId) {
|
||||
return { values: {}, usesConfiguredParameters: false };
|
||||
}
|
||||
const fileParameterKeys = new Set(
|
||||
request.parameters
|
||||
.filter((parameter) => parameter.input_type === 'file')
|
||||
.map((parameter) => parameter.key)
|
||||
);
|
||||
return {
|
||||
values: { ...configuredParameterState.values },
|
||||
values: Object.fromEntries(
|
||||
Object.entries(configuredParameterState.values).filter(([key]) => !fileParameterKeys.has(key))
|
||||
),
|
||||
usesConfiguredParameters: true,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -101,6 +101,10 @@ const ParameterInputModal: React.FC<ParameterInputModalProps> = ({
|
||||
useEffect(() => {
|
||||
const values = createParameterValueMap();
|
||||
parameters.forEach((param) => {
|
||||
if (param.input_type === 'file') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (param.requirement === 'optional' && param.default != null) {
|
||||
if (isValidParameterValue(param, param.default)) {
|
||||
values[param.key] = param.default;
|
||||
|
||||
@@ -507,6 +507,44 @@ describe('ParameterInputModal', () => {
|
||||
expect((screen.getByLabelText(/boolean parameter/i) as HTMLSelectElement).value).toBe('true');
|
||||
});
|
||||
|
||||
it('does not initialize file parameters from prefills or defaults', async () => {
|
||||
const user = userEvent.setup();
|
||||
const onSubmit = vi.fn();
|
||||
renderWithIntl(
|
||||
<ParameterInputModal
|
||||
{...defaultProps}
|
||||
onSubmit={onSubmit}
|
||||
parameters={[
|
||||
{
|
||||
key: 'document',
|
||||
description: 'Document',
|
||||
input_type: 'file',
|
||||
requirement: 'required',
|
||||
default: '/tmp/default.txt',
|
||||
},
|
||||
{
|
||||
key: 'topic',
|
||||
description: 'Topic',
|
||||
input_type: 'string',
|
||||
requirement: 'required',
|
||||
},
|
||||
]}
|
||||
initialValues={{ document: '/tmp/private.txt', topic: 'release notes' }}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(screen.getByLabelText(/^Document/)).toHaveValue('');
|
||||
expect(screen.getByLabelText(/^Topic/)).toHaveValue('release notes');
|
||||
|
||||
await user.type(screen.getByLabelText(/^Document/), '/tmp/selected.txt');
|
||||
await user.click(screen.getByText('Start Recipe'));
|
||||
|
||||
expect(onSubmit).toHaveBeenCalledWith({
|
||||
document: '/tmp/selected.txt',
|
||||
topic: 'release notes',
|
||||
});
|
||||
});
|
||||
|
||||
it('keeps a valid default when an invalid prefill is supplied', () => {
|
||||
renderWithIntl(
|
||||
<ParameterInputModal
|
||||
|
||||
Reference in New Issue
Block a user