Version 5.1.0

October 9, 2026

Added

  • Jobs and their specifications are now in Craft's GraphQL API: hireJobs, hireJob, hireJobCount and hireSpecGroups, behind one schema permission (Hire → Query for jobs and their specifications). Jobs carry the published salary, address, spec terms, apply link and the JobPosting JSON; spec terms carry their open-job counts. Lite and Pro.
  • Jobs fields can be queried through GraphQL, held to the same rule about which jobs come back.
  • GraphQL shows what the careers page shows — open jobs, plus closed ones when the site lists them. A salary that isn't published is null. Applications and applicants are deliberately not in the API, under any permission.

Version 5.0.1

October 3, 2026

Security

  • Fixed an SQL injection vulnerability in the public jobs feed. The orderBy parameter of /actions/hire/feed/jobs (and craft.hire.listing()) was passed to the query unchecked; sorting is now limited to the built-in sort names and existing custom field handles, and anything else falls back to the default sort.
  • Fixed a vulnerability where the applicant status page matched hireToken values containing query syntax such as *, exposing other applicants' status pages. Portal tokens are now validated and matched exactly.
  • CVs are only stored in a volume someone chose. With none chosen, Hire used the site's first volume — usually its public images — so a fresh install put applicants' CVs at public URLs. Forms now can't take a CV until a volume is chosen, the setting has no preselected volume, and the settings screen warns when the chosen volume has public URLs.
  • HTML, SVG, XML, JavaScript and PHP uploads are always refused, even if a site adds them to the accepted file types.
  • Fixed a vulnerability where the duplicate-application check matched email addresses containing query syntax: a submitted *@example.com matched every applicant at that domain, which in "block" mode let a visitor discover who had applied. Emails are now matched exactly.
  • Files uploaded with a refused application (a validation error, a blocked duplicate or a before-submit refusal) are now deleted instead of left orphaned in the CV volume.
  • Hard-deleting an application now deletes the files uploaded to its other file questions, not only the CV.
  • Uploaded filenames lose any inner extension (cv.php.pdf is stored as cv-php.pdf).
  • CVs already stored on a public volume by 5.0.0 stay where they are. If the settings screen warns that your CV volume has public URLs, move them to a private volume.

Added

  • Applications::EVENT_BEFORE_SUBMIT / EVENT_AFTER_SUBMIT (SubmitApplicationEvent) and EVENT_BEFORE_STAGE_CHANGE / EVENT_AFTER_STAGE_CHANGE (StageChangeEvent). The "before" events can refuse; a refusal without a reason still shows the visitor a message.
  • PHPStan (level 4) and ECS configuration.

Fixed

  • A ticked filter box in the built-in listing rendered blank.
  • Listing rows no longer show “Location” twice when a specification group is also called Location.
  • The default applicant and team emails sent their placeholders literally ("Hi {firstName},"). Craft renders system messages as Twig, so they now use {{ firstName }}. Messages you've already customised keep your wording — check them for single-brace placeholders.

  • A failure to compose an email logged an empty template name: “$key” reads a variable called $key”, because PHP allows the closing quote's bytes in an identifier.