Importing a CV: the website and ORCID are stored without the checks the profile forms apply #610
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#610
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found on 2026-09-29 in a read-only review of postulo at
95348908d, reading the importer's writer and trying it against the test settings.Checked again on 2026-10-01 against
mainat0a5cad587: still present. The code is now atplugins/europass/reader.py:342-344and:643-644(the website taken as written) andplugins/europass/common.py:80-95(_orcid_from, the checksum check);resume/importing.py,core/web_links.pyandresume/candidate.pyhave not moved.importing.applywrites a record's personal details without running any form or validator. The website goes throughweb_links.save_only_link, which assigns the value and callssave()with nofull_clean, and the ORCID throughPersonIdentifier.objects.create. The candidate-file importer, by contrast, sends the same values throughWebLinkFormandPersonIdentifierForm. The Europass reader takes the website from the first website address in the file without checking it. The importer contract in the wiki lets a third-party importer put any string inperson.resume/importing.py:141-145(website),:177-180(ORCID);core/web_links.py:210-241(save_only_link);plugins/europass/reader.py:466-468and:767-768(website taken as written); compareresume/candidate.py:954and:992.importing.apply(user, Record(person={"website": "javascript:alert(1)", "orcid": "not-an-orcid"}))stored aWebLinkwith that URL and aPersonIdentifierwith that value, and reported both as filled.full_clean()on the stored link then fails with "Enter a valid URL." The value appears in the CV's contact details. The profile's link form will not accept a row the person never typed, so they have to find and delete it themselves. The Europass reader already checks an ORCID's checksum (reader.py:189-204); a third-party importer's ORCID gets no check.importing.apply, validate each personal value as its page does before writing it: the URL field's validator (orWebLinkForm) for the website,identifiers.clean(identifiers.ORCID, …)(orPersonIdentifierForm) for the ORCID. A value that fails goes intoReport.skippedas a sentence instead of being stored. The telephone number is written the same way (save_only_number,:159); give it the same treatment once #304 settles what a valid number is.Related to #304 and #305, which change what the telephone and web link forms check; this path skips the forms, whatever they check.
Done when
tests/test_importers.pyapplies a record whose website is not an http(s) URL and whose ORCID fails its checksum, and finds neither stored and both named inreport.skipped.href#32