Skip to content

Commit e276628

Browse files
sumnerevansclaude
andcommitted
security: change team member delete from GET to POST
Destructive operations must not be triggered via GET — any page with an <img> or prefetch link pointing at the URL could silently delete members for a logged-in teacher. Replaced the <a> link with a <form method=POST> and switched the handler to read params from the form body. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
1 parent 5065921 commit e276628

3 files changed

Lines changed: 16 additions & 8 deletions

File tree

internal/application.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ func (a *Application) Start() {
190190
}
191191

192192
// Delete Team member
193-
router.HandleFunc("GET /register/teacher/team/delete", a.HandleTeacherDeleteMember)
193+
router.HandleFunc("POST /register/teacher/team/delete", a.HandleTeacherDeleteMember)
194194

195195
// Email confirmation code handling
196196
router.HandleFunc("GET /register/teacher/emaillogin", a.HandleTeacherEmailLogin)

internal/teacherteammembers.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,13 @@ func (a *Application) HandleTeacherDeleteMember(w http.ResponseWriter, r *http.R
248248
return
249249
}
250250

251-
email := r.URL.Query().Get("email")
252-
teamIDStr := r.URL.Query().Get("team_id")
251+
if err := r.ParseForm(); err != nil {
252+
a.Log.Err(err).Msg("failed to parse form")
253+
w.WriteHeader(http.StatusBadRequest)
254+
return
255+
}
256+
email := r.FormValue("email")
257+
teamIDStr := r.FormValue("team_id")
253258
log := a.Log.With().
254259
Str("page_name", "teacher_delete_member").
255260
Str("team_id", teamIDStr).

website/templates/teamedit.html

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,14 @@ <h4 class="card-header">Team Members</h4>
174174
<td>{{ if .PreviouslyParticipated }}Yes{{ else }}No{{ end }}</td>
175175
<td>{{ .ParentEmail }}</td>
176176
<td class="text-center">
177-
<a href="/register/teacher/team/delete?team_id={{ $t.ID }}&email={{ .Email }}"
178-
onclick="return confirm('Are you sure you want to remove {{ .Name }} from {{ $t.Name }}?')"
179-
class="btn btn-danger">
180-
<i class="fa fa-times"></i>
181-
</a>
177+
<form method="POST" action="/register/teacher/team/delete"
178+
onsubmit="return confirm('Are you sure you want to remove {{ .Name }} from {{ $t.Name }}?')">
179+
<input type="hidden" name="team_id" value="{{ $t.ID }}">
180+
<input type="hidden" name="email" value="{{ .Email }}">
181+
<button type="submit" class="btn btn-danger">
182+
<i class="fa fa-times"></i>
183+
</button>
184+
</form>
182185
</td>
183186
</tr>
184187
{{ end }}

0 commit comments

Comments
 (0)