Until now, MDL Shield reviewed code after the fact: a release on the
Marketplace, or a branch you pointed us at. Pull request reviews move the
review to the moment the code is actually decided. Install the MDL Shield
GitHub App on a repository and every pull request gets a security review
before it merges, with the results posted straight to the PR and to your
dashboard.
The reviewer is the same one behind every MDL Shield review: an AI Moodle
security specialist that reads your change the way a human reviewer would,
understanding what the code does and how it fits into Moodle, not just
pattern-matching lines. It is not a linter and it does not replace
moodle-plugin-ci.
Pull request reviews are in free preview, and we'd love your help
putting them through their paces. Open the
Pull Requests tab in your dashboard and hit
Request access.
On the pull request
Three things land on the PR:
A check called MDL Shield review that passes or fails according to
the severity you choose to block on.
One summary comment that always shows the current state: every
finding, its severity, and its status.
An inline comment on the exact line for each finding, with the
description up front and the depth (context, risk assessment, suggested
fix) folded away until you want it.
mdlshieldBotcommented 2 hours ago • edited
MDL Shield security review
1 open finding (1 high) as of 9f3ab12.
SeverityFindingStatus
🟠 HIGHSort column from the request is concatenated into the report queryopen
🔵 LOWThe returnurl parameter reaches redirect() without a local-URL checkaccepted risk
▶Commands
Open the dashboard for full details and history.
All checks have failed
1 failing check
MDL Shield review Failing after 4m — Review complete — 1 open finding (1 high)
No conflicts with base branch
Merging can be performed automatically.
Merge pull requestYou can also merge this with the command line. View command line instructions.
The summary comment carries the current state; the check carries the verdict
Sort column from the request is concatenated into the report query
The sort request parameter is read as PARAM_RAW and interpolated straight into the ORDER BY clause, so whatever a user puts in it becomes part of the SQL that $DB->get_records_sql() executes.
Every enrolled user can open this report, so any student can steer the query.
▶Context
▶Risk assessment
▼Suggested fix
Accept only the columns the report can sort by and fall back to the default; read the parameter as PARAM_ALPHA.
Triage: reply !mdlshield dismiss, !mdlshield accept, or !mdlshield confirm.
AReply...
Resolve conversation
Each finding is an inline comment on the exact line, with the depth folded away
Findings in pre-existing code that your change interacts with are reported
too. On public repositories those never appear on the PR, only in your
dashboard, so a review can't hand a bystander a map of unfixed code.
Findings follow the code
Every push is reviewed, and findings are never re-reported push after push:
a finding stays open until a commit actually fixes it, and when one does, the
review resolves it and names the commit. If a later commit turns a latent risk
into a real one, the finding escalates, with the evidence.
classes/report/table.phpOutdated
55+ WHERE courseid = :courseid
56+ ORDER BY $sort";
mdlshieldBot2 hours ago • edited
🟠 [HIGH] · SQL injection
Sort column from the request is concatenated into the report query
▶Context
▶Risk assessment
▶Suggested fix
✅ Addressed in commit 7d1c0e2.
Triage: reply !mdlshield dismiss, !mdlshield accept, or !mdlshield confirm.
AReply...
Resolve conversation
alexc added 1 commit just now
AWhitelist the sortable columnsVerified7d1c0e2
mdlshieldBot reviewed just now
View reviewed changes
mdlshieldBotleft a comment
Reviewed 9f3ab12..7d1c0e2 (incremental) — no new findings; 1 resolved.
Resolved by this pass:
• 🟠 HIGH Sort column from the request is concatenated into the report query (classes/report/table.php:56) — addressed in 7d1c0e2
▶Review details
All checks have passed
1 successful check
MDL Shield review Successful after 2m — Review complete — no open findings
No conflicts with base branch
Merging can be performed automatically.
Merge pull requestYou can also merge this with the command line. View command line instructions.
Push the fix: the next review resolves the finding and credits the commit
Triage from the PR
Every finding's inline thread takes commands from the repository owner and
the users you trust. Reply on the finding to triage it, with a reason if you
have one:
!mdlshield accept Only course managers can reach the export page
dismiss, accept, confirm and resolve are the verbs. The bot
acknowledges with a thumbs up, appends the decision to the finding (who, and
why), and the check recomputes. !mdlshield review on the PR forces a
re-review, and so does the Re-run button on the check.
Settings in the repository, or on the site
A .mdlshield/config.yml on your default branch controls which pull requests
are reviewed and how: branch, label, author and path filters, the severity
that fails the check, what the check does when a review errors, who may issue
commands, and the Moodle version to review against.
fail_on:severity:high# the check fails on high and criticalon-error:open# an errored review never blocks a mergemoodle:versions: ["5.0"]
trusted_users: ["alexc"]
include:branches: ["main", "MOODLE_*_STABLE"]
exclude:paths: ["lang/**", "vendor/**"]
authors: ["dependabot[bot]"]
The same settings exist on the site, as account defaults and per-repository
settings, so you don't need a file at all. When there is one, it wins, key by
key. You can also give the reviewer private context about your plugin (what
it is for, who can reach it, known trust boundaries) that guides every review
and is never committed to your repository.
Your dashboard
The new Pull Requests tab lists every PR across your repositories with
its open findings and check state at a glance.
Pull requestFindingsCheckUpdated
Upgrade step for the new stats table
acme/moodle-report_example#43 by priya-m
—
just now
Add sortable course activity report
acme/moodle-report_example#42 by alexc · 2 reviews
—
3m ago
Bulk export of course notes as CSV
acme/moodle-report_example#41 by priya-m · 1 review
12
1d ago
Settings page for default block visibility
acme/moodle-block_example#17 by alexc · 1 review
1
2d ago
Fix capability check on the block config form
acme/moodle-block_example#16 by alexc · 3 reviews
—
4d ago
Experiment with cached report queries
acme/moodle-report_example#38 by alexc
—
9d ago
The Pull Requests tab: every PR across your repositories, open findings and check state at a glance
Every pull request gets a page in your dashboard with the full history of
review passes, every finding in full depth, and triage buttons that twin the
commands. This is the only place a finding's proof of concept ever appears:
it is never posted to GitHub. You can also authorise other people to view and
triage without giving them settings or billing.
Add sortable course activity report
Open
acme/moodle-report_example#42 · opened by alexc · 2 days ago
Check passedReviewed head 7d1c0e2 · 3m ago2nd review on this pull request
Findings (1)
Low Risk accepted
The returnurl parameter reaches redirect() without a local-URL check
View finding ›
classes/report/export.php:31
@@ -28,2 +28,5 @@ public function download(int $courseid): void
2828 public function download(int $courseid): void {
▸ Files reviewed (2)Moodle 5.0 · configuration from repository configuration file + account defaults · run 3f8c1a2b9e4d
3m ago
Reviewed 4e1d7aa..9f3ab12
Full review when the pull request opened · 6 files · 2 new findings
2d ago
Every pull request gets a page in your dashboard: findings in full depth, and the review history
Pull request reviews are in free preview, and we'd love your help
putting them through their paces. Open the
Pull Requests tab in your dashboard and hit
Request access.