@@ -156,7 +156,13 @@ public function getForms(string $type = 'owned'): DataResponse {
156156 * @throws OCSForbiddenException The user is not allowed to create forms
157157 * @throws OCSBadRequestException Cannot use both fromId and import parameters
158158 * @throws OCSBadRequestException Invalid form data: missing questions
159+ * @throws OCSBadRequestException Invalid form data: unknown properties
159160 * @throws OCSBadRequestException Invalid question data: missing id
161+ * @throws OCSBadRequestException Invalid question data: unknown properties
162+ * @throws OCSBadRequestException Invalid question data: invalid type
163+ * @throws OCSBadRequestException Invalid question data: datetime type no longer supported
164+ * @throws OCSBadRequestException Invalid question data: invalid extraSettings
165+ * @throws OCSBadRequestException Invalid option data: unknown properties
160166 *
161167 * 201: the created form
162168 */
@@ -203,6 +209,19 @@ public function newForm(?int $fromId = null, ?bool $import = false, ?array $form
203209 $ questions = $ formData ['questions ' ];
204210 $ oldConfirmationEmailQuestionId = $ formData ['confirmationEmailQuestionId ' ] ?? null ;
205211 unset($ formData ['questions ' ]);
212+
213+ // Validate form data whitelist
214+ $ allowedFormProperties = [
215+ 'title ' , 'description ' , 'access ' , 'expires ' , 'isAnonymous ' ,
216+ 'submitMultiple ' , 'allowEditSubmissions ' , 'showExpiration ' ,
217+ 'submissionMessage ' , 'maxSubmissions ' , 'confirmationEmailEnabled ' ,
218+ 'confirmationEmailSubject ' , 'confirmationEmailBody ' , 'confirmationEmailQuestionId ' ,
219+ 'allowComments ' ,
220+ ];
221+ $ invalidKeys = array_diff (array_keys ($ formData ), $ allowedFormProperties );
222+ if (!empty ($ invalidKeys )) {
223+ throw new OCSBadRequestException ('Invalid form data: unknown properties: ' . implode (', ' , $ invalidKeys ));
224+ }
206225 } else {
207226 $ oldForm = $ this ->formsService ->getFormIfAllowed ($ fromId , Constants::PERMISSION_EDIT );
208227
@@ -246,6 +265,32 @@ public function newForm(?int $fromId = null, ?bool $import = false, ?array $form
246265 if (!isset ($ oldQuestion ['id ' ])) {
247266 throw new OCSBadRequestException ('Invalid question data: missing id ' );
248267 }
268+
269+ // Validate question property whitelist
270+ $ allowedQuestionProperties = ['id ' , 'order ' , 'type ' , 'isRequired ' , 'text ' , 'name ' , 'description ' , 'extraSettings ' , 'options ' ];
271+ $ invalidQuestionKeys = array_diff (array_keys ($ oldQuestion ), $ allowedQuestionProperties );
272+ if (!empty ($ invalidQuestionKeys )) {
273+ throw new OCSBadRequestException ('Invalid question data: unknown properties: ' . implode (', ' , $ invalidQuestionKeys ));
274+ }
275+
276+ // Validate question type
277+ $ type = $ oldQuestion ['type ' ] ?? null ;
278+ if ($ type === null || array_search ($ type , Constants::ANSWER_TYPES ) === false ) {
279+ throw new OCSBadRequestException ('Invalid question data: invalid type ' );
280+ }
281+
282+ // Block datetime questions
283+ if ($ type === 'datetime ' ) {
284+ throw new OCSBadRequestException ('Invalid question data: datetime type no longer supported ' );
285+ }
286+
287+ // Validate extraSettings
288+ if (!empty ($ oldQuestion ['extraSettings ' ] ?? [])) {
289+ if (!$ this ->formsService ->areExtraSettingsValid ($ oldQuestion ['extraSettings ' ], $ type )) {
290+ throw new OCSBadRequestException ('Invalid question data: invalid extraSettings ' );
291+ }
292+ }
293+
249294 $ questionData = $ oldQuestion ;
250295 $ oldQuestionId = $ oldQuestion ['id ' ];
251296 $ options = $ oldQuestion ['options ' ] ?? [];
@@ -271,6 +316,15 @@ public function newForm(?int $fromId = null, ?bool $import = false, ?array $form
271316 foreach ($ options as $ oldOption ) {
272317 $ optionData = $ import ? $ oldOption : $ oldOption ->read ();
273318
319+ if ($ import ) {
320+ // Validate option property whitelist
321+ $ allowedOptionProperties = ['text ' , 'order ' , 'optionType ' ];
322+ $ invalidOptionKeys = array_diff (array_keys ($ optionData ), $ allowedOptionProperties );
323+ if (!empty ($ invalidOptionKeys )) {
324+ throw new OCSBadRequestException ('Invalid option data: unknown properties: ' . implode (', ' , $ invalidOptionKeys ));
325+ }
326+ }
327+
274328 unset($ optionData ['id ' ]);
275329 $ optionData ['questionId ' ] = $ newQuestion ->getId ();
276330 $ newOption = Option::fromParams ($ optionData );
0 commit comments