Security

Interview Questions: Validation, Capabilities, and XSS Prevention

Q1: How do you prevent SQL Injection in Moodle?

Never use variables directly in SQL strings. Always use the placeholders (? or named parameters) provided by the DML API ($DB).

// BAD
$DB->get_record_sql("SELECT * FROM {user} WHERE id = $id");

// GOOD
$DB->get_record_sql("SELECT * FROM {user} WHERE id = ?", [$id]);

Q2: Explain the difference between `required_param` and `optional_param`.

These functions are used to retrieve data from $_GET or $_POST safely.

  • required_param($name, $type): Stops execution with an error if the parameter is missing. Use this for critical data (e.g., course ID).
  • optional_param($name, $default, $type): Returns a default value if the parameter is missing.

Both require a PARAM_* constant (e.g., PARAM_INT, PARAM_TEXT) to sanitize the input immediately.

Q3: How do you check for permissions in a plugin?

Use the Capabilities API. First, define the context, then check the capability.

$context = context_course::instance($courseid);

// Throws an exception if user doesn't have permission (stops execution)
require_capability('mod/myplugin:view', $context);

// Returns boolean (good for conditional logic)
if (has_capability('mod/myplugin:edit', $context)) {
    // Show edit button
}

Q4: What is 'sesskey' and why is it important?

A sesskey (Session Key) is a token used to prevent Cross-Site Request Forgery (CSRF). It is generated for each user session. Any script that performs an action (POST request) must check require_sesskey() to ensure the request originated from the user and not a malicious site.

Q5: How do you prevent Cross-Site Scripting (XSS)?

Moodle provides output cleaning functions. Always use s() for plain text attributes and format_string() or format_text() for content. When outputting HTML, use $OUTPUT renderers or Mustache templates which auto-escape variables by default.

Q6: What is 'PARAM_CLEANHTML'?

It is a parameter type used with optional_param or required_param. It uses HTML Purifier to remove malicious scripts (like <script> tags) while preserving safe HTML formatting. Use it for rich text editor content.

Q7: What is 'require_login()'?

It ensures that a user is logged in before accessing a page. If not, it redirects them to the login page. It also sets up the global $USER object. It should be called at the top of almost every script.

Q8: How do you securely handle file downloads?

Do not link directly to files in moodledata. Use pluginfile.php. In your plugin's lib.php, implement the _pluginfile() callback function to check permissions (e.g., has_capability) before serving the file content.

Q9: What is 'is_siteadmin()'?

A function that checks if the current user is a site administrator. Admins have all capabilities by default. Use this check sparingly; prefer capability checks (has_capability) to allow for role delegation.

Q10: What is 'PARAM_INT'?

A parameter type that casts the input to an integer. It is crucial for IDs. If the input is not an integer, it strips non-numeric characters or returns 0, preventing SQL injection via ID fields.

Q11: How do you secure a cron task?

Cron tasks run in the background, often as the admin user or without a specific user. Ensure your task logic does not rely on $USER or $PAGE context unless explicitly set. Use cron_setup_user() if you need to impersonate a user securely.

Q12: What is 'ignore_missing' in capability checks?

When defining capabilities in access.php, you can set archetypes. If you check a capability that doesn't exist, Moodle might throw an error. has_capability handles this gracefully, but require_capability is strict.

Q13: What is 'MOODLE_INTERNAL'?

A constant defined in the main Moodle entry points. Most include files check defined('MOODLE_INTERNAL') || die(); to prevent direct access to library files via the browser, which could expose paths or errors.

Q14: How do you sanitize a URL?

Use clean_param($url, PARAM_URL) or new moodle_url($url). This ensures the URL is valid and prevents javascript: protocol injection attacks.

Q15: What is 'PARAM_TEXT'?

A parameter type that strips all HTML tags. It is useful for plain text inputs like names or titles where no formatting is allowed.

Q16: How do you prevent 'Privilege Escalation'?

Always check capabilities in the correct context. Do not check CONTEXT_SYSTEM if the action is only for a specific course. Ensure that form submissions (POST) re-verify permissions, not just the page load (GET).

Q17: What is 'https_required()'?

A function (or $CFG->wwwroot setting) that ensures the site is accessed via HTTPS. Moodle now strongly recommends or enforces HTTPS to protect session cookies and data in transit.

Q18: How do you handle passwords?

Never store passwords in plain text. Moodle uses password_hash() (bcrypt) to hash passwords. Use hash_internal_user_password() to generate hashes and validate_internal_user_password() to check them.

Q19: What is 'security_key' in external services?

When using Web Services, a token is generated for the external app. This token acts as the password. It must be kept secret and can be restricted by IP address or expiration date.

Q20: What is 'riskbitmask'?

In access.php, capabilities have a riskbitmask (e.g., RISK_XSS, RISK_CONFIG). This warns admins that assigning this capability might allow the user to perform dangerous actions (like inserting XSS or changing site config).

Q21: How do you prevent 'Session Fixation'?

Moodle automatically regenerates the session ID upon login (session_regenerate_id). This prevents an attacker from tricking a user into using a known session ID.

Q22: What is 'login_https'?

An older setting to use HTTPS only for the login page. Modern practice is to use HTTPS for the entire site (Always-On SSL) to protect the session cookie at all times.

Q23: How do you validate a file upload type?

In the form definition, use the accepted_types option for the filemanager element (e.g., ['.pdf', '.docx']). Moodle validates the extension and MIME type.

Q24: What is 'user_not_fully_set_up()'?

A check to see if the user has completed their profile (e.g., agreed to site policy). Moodle restricts access until these steps are completed.

Q25: How do you prevent 'Brute Force' attacks?

Moodle has a built-in account lockout mechanism. If a user fails login multiple times (configurable threshold), their account is temporarily locked.

Q26: What is 'PARAM_NOTAGS'?

Similar to PARAM_TEXT, it strips HTML tags. It is strictly for data that should not contain any markup.

Q27: How do you secure a Web Service API?

Ensure the service function checks capabilities (validate_context). Do not rely solely on the token. The token authenticates the user, but the code must authorize the action.

Q28: What is 'clean_text()'?

A legacy function, now largely replaced by format_text(). It was used to clean dangerous HTML. format_text() does this automatically if the format requires it.

Q29: How do you handle 'Guest' access securely?

Guest access allows unauthenticated users to view content. Ensure your plugin checks isguestuser() if you need to restrict features (like posting to a forum) that guests should not do.

Q30: What is 'config_plugins' table?

It stores plugin configuration. While not a security feature per se, sensitive data (like API keys) stored here should be handled carefully. Moodle does not encrypt these values by default.