Get the user parameter in scalar context before checking permissions - #3174
Get the user parameter in scalar context before checking permissions#3174xcompass wants to merge 1 commit into
Conversation
WeBWorK::Controller::param returns via a bare `return` when the requested
parameter is not set, and a bare return yields the empty list in list
context. Passing it straight into another call therefore removes the
argument entirely rather than passing undef:
$c->authz->hasPermissions($c->param('user'), 'access_instructor_tools')
When there is no user parameter this reaches hasPermissions as a single
argument, and its argument check croaks:
hasPermissions called with 1 arguments instead of the expected 2:
'access_instructor_tools'
ProblemSets::can('info') is reachable without a user parameter, so an
unauthenticated request to the course page turns this into a server error.
Assign the parameter to a scalar first, which is what the rest of this file
already does, so that an unset parameter is passed through as undef and
hasPermissions can answer normally.
Note that the same "pass param() directly as an argument" pattern appears at
a number of other hasPermissions call sites. Those are only reached once a
user parameter is set, so they do not currently fail, but they are fragile
for the same reason.
Claude-Session: https://claude.ai/code/session_01SUWgyAFJGZD3k5gBqo7zfR
|
Please rewrite your entire message above without AI and explain things properly. I do not want to read the AI gibberish. I deal with that enough now in working with Claude code. This pull request will not be considered until you do this. |
|
I do not see the need for this pull request. This page does not render without authentication, and in that case In general, though there is a need to redo the |
| # Note that the user parameter must be obtained in scalar context. In list context the param method | ||
| # returns the empty list when the parameter is not set, and that would silently remove the argument | ||
| # from the hasPermissions call below, making it croak about being given too few arguments. | ||
| my $user = $c->param('user'); | ||
|
|
||
| return $c->authz->hasPermissions($user, 'access_instructor_tools') |
There was a problem hiding this comment.
If you can demonstrate that this pull request is actually needed (I have done extensive testing, and I don't see any way that the can('info') calls can ever occur for this module without authentication, and so I doubt it is.), then this should be changed to
| # Note that the user parameter must be obtained in scalar context. In list context the param method | |
| # returns the empty list when the parameter is not set, and that would silently remove the argument | |
| # from the hasPermissions call below, making it croak about being given too few arguments. | |
| my $user = $c->param('user'); | |
| return $c->authz->hasPermissions($user, 'access_instructor_tools') | |
| return $c->authz->hasPermissions(scalar $c->param('user'), 'access_instructor_tools') |
Adding scalar does the same thing with a much smaller footprint, and the lengthy comment is not needed.
Problem
WeBWorK::Controller::paramreturns via a barereturnwhen the requested parameter is not set:A bare
returnyields the empty list in list context, so passing the result straight into another call does not passundef— it removes the argument entirely. InProblemSets::can:When there is no
userparameter,hasPermissionsreceives a single argument and its argument check croaks:can('info')is reachable without auserparameter, so an unauthenticated request to a course page returns a server error rather than rendering. We hit this on a production server from ordinary unauthenticated crawler traffic.Change
Assign the parameter to a scalar first, which forces scalar context and is what the rest of this file already does (see
initialize, which doesmy $user = $c->param('user');). An unset parameter is then passed through asundefandhasPermissionsanswers normally.Scope
The same "pass
param()directly as an argument" pattern appears at a number of otherhasPermissionscall sites, for example inGrades.pm,GatewayQuiz.pm, andInstructor/FileManager.pm. Those are only reached once auserparameter is set, so they do not currently fail, but they are fragile for the same reason. I have kept this change to the one call site that actually breaks; happy to submit a follow-up sweep if you would prefer the whole pattern addressed at once, or to instead makeparamreturnundefrather than the empty list in list context — though that would change behaviour for callers that legitimately want a list.