1616use Symfony \Bundle \SecurityBundle \Security ;
1717use Symfony \Component \HttpFoundation \Request ;
1818use Symfony \Component \HttpKernel \Attribute \AsController ;
19+ use Symfony \Component \HttpKernel \Exception \AccessDeniedHttpException ;
1920
2021#[AsController]
2122class CreateCBlogAction extends BaseResourceFileAction
@@ -42,6 +43,12 @@ public function __invoke(
4243 $ resourceLinkList = \is_array ($ resourceLinkListRaw ) ? $ resourceLinkListRaw : [];
4344 }
4445
46+ // The `cid` (and optional `sid`/`gid`) query parameter establishes the
47+ // course context that gated the security expression. Any
48+ // resourceLinkList entry that points to a different context would
49+ // bypass that gate, so we reject the request outright.
50+ $ this ->assertResourceLinkListMatchesQueryContext ($ request , $ resourceLinkList , $ security );
51+
4552 $ blog = (new CBlog ())
4653 ->setTitle ($ title )
4754 ->setBlogSubtitle ($ subtitle )
@@ -89,4 +96,47 @@ private function handleShortcutCreation(
8996 $ shortcutRepository ->addShortCut ($ blog , $ currentUser , $ course , $ session );
9097 }
9198 }
99+
100+ /**
101+ * @param array<int, mixed> $resourceLinkList
102+ */
103+ private function assertResourceLinkListMatchesQueryContext (
104+ Request $ request ,
105+ array $ resourceLinkList ,
106+ Security $ security ,
107+ ): void {
108+ if ($ security ->isGranted ('ROLE_ADMIN ' )) {
109+ return ;
110+ }
111+
112+ if ([] === $ resourceLinkList ) {
113+ return ;
114+ }
115+
116+ $ queryCid = (int ) $ request ->query ->get ('cid ' );
117+ $ querySid = (int ) $ request ->query ->get ('sid ' );
118+ $ queryGid = (int ) $ request ->query ->get ('gid ' );
119+
120+ foreach ($ resourceLinkList as $ entry ) {
121+ if (!\is_array ($ entry )) {
122+ continue ;
123+ }
124+
125+ $ entryCid = (int ) ($ entry ['cid ' ] ?? 0 );
126+ $ entrySid = (int ) ($ entry ['sid ' ] ?? 0 );
127+ $ entryGid = (int ) ($ entry ['gid ' ] ?? 0 );
128+
129+ if ($ entryCid > 0 && $ entryCid !== $ queryCid ) {
130+ throw new AccessDeniedHttpException ('resourceLinkList course does not match the request context. ' );
131+ }
132+
133+ if ($ entrySid > 0 && $ entrySid !== $ querySid ) {
134+ throw new AccessDeniedHttpException ('resourceLinkList session does not match the request context. ' );
135+ }
136+
137+ if ($ entryGid > 0 && $ entryGid !== $ queryGid ) {
138+ throw new AccessDeniedHttpException ('resourceLinkList group does not match the request context. ' );
139+ }
140+ }
141+ }
92142}
0 commit comments