A file's edit form shows the person their storage path, account id and all #191

Closed
opened 2026-09-12 12:42:28 +00:00 by tiagoagueda · 1 comment
Owner

Observation

Found while fixing #167, which was about the same line for a different reason.

/documents/files/<pk>/edit/ renders, from Django's ClearableFileInput:

Currently: <a href="/media/documents/1/2026/09/reference.txt">documents/1/2026/09/reference.txt</a>
Change: <input type="file" ...>

The person uploaded a file called reference.txt. What they are shown is
documents/1/2026/09/reference.txt — the path it is stored at, which carries their account
id
and the month they uploaded it, neither of which they asked about and neither of
which is theirs to care about.

Why it is worth fixing beyond tidiness

  • It is the wrong answer to the question. The field is asking which file is this? The
    answer is reference.txt. The rest is Postulo's filing system thinking aloud.
  • It states internal structure in the interface, so the layout on disk becomes something
    people have seen and might rely on. A future change to upload_to then looks like a change
    to them rather than to storage.
  • It is a second place UploadedDocument.title already answers. The form has a Title
    field immediately above showing "Reference". The path adds nothing and contradicts it in
    tone.

What it is not

Not a serious disclosure. The path is the person's own, behind their own login, and
/media/ is already how they download it. This is an interface fault with a small privacy
edge — a screen shared in a call now shows an account id — rather than a leak to anybody
else.

Doing it

Django builds that string from the widget's value, whose __str__ is the stored name. The
narrow fix is a widget that renders the basename, applied wherever a file field is shown;
partials/field.html is where every field already passes through, so that is the natural
place for it to take effect without each form remembering.

Worth checking at the same time: the same widget is used by any other file field — the
Europass import and the plugin upload on the server pages — so the fix should be one widget
rather than one template.

#167 already stopped it running off a phone, by letting the field container wrap
anywhere. That is a fix for the symptom and stands on its own: whatever string ends up there,
it should not scroll the page sideways.

## Observation Found while fixing #167, which was about the same line for a different reason. `/documents/files/<pk>/edit/` renders, from Django's `ClearableFileInput`: Currently: <a href="/media/documents/1/2026/09/reference.txt">documents/1/2026/09/reference.txt</a> Change: <input type="file" ...> The person uploaded a file called `reference.txt`. What they are shown is `documents/1/2026/09/reference.txt` — the path it is stored at, which carries **their account id** and **the month they uploaded it**, neither of which they asked about and neither of which is theirs to care about. ## Why it is worth fixing beyond tidiness - **It is the wrong answer to the question.** The field is asking *which file is this?* The answer is `reference.txt`. The rest is Postulo's filing system thinking aloud. - **It states internal structure in the interface**, so the layout on disk becomes something people have seen and might rely on. A future change to `upload_to` then looks like a change to them rather than to storage. - **It is a second place `UploadedDocument.title` already answers.** The form has a *Title* field immediately above showing "Reference". The path adds nothing and contradicts it in tone. ## What it is not Not a serious disclosure. The path is the person's own, behind their own login, and `/media/` is already how they download it. This is an interface fault with a small privacy edge — a screen shared in a call now shows an account id — rather than a leak to anybody else. ## Doing it Django builds that string from the widget's value, whose `__str__` is the stored name. The narrow fix is a widget that renders the **basename**, applied wherever a file field is shown; `partials/field.html` is where every field already passes through, so that is the natural place for it to take effect without each form remembering. Worth checking at the same time: the same widget is used by any other file field — the Europass import and the plugin upload on the server pages — so the fix should be one widget rather than one template. **#167 already stopped it running off a phone**, by letting the field container wrap anywhere. That is a fix for the symptom and stands on its own: whatever string ends up there, it should not scroll the page sideways.
Author
Owner

Reproduced, and narrower than this issue claimed

Rendered the page against a fresh upload, with a space in the filename to see the
sanitising as well:

Currently: <a href="/media/documents/1/2026/09/my_cv.pdf">documents/1/2026/09/my_cv.pdf</a><br>
Change: <input type="file" name="file" class="field-input" id="id_file">

So it is exactly as described: the person uploaded my cv.pdf and is shown
documents/1/2026/09/my_cv.pdf — their account id, the month, and a name Django rewrote.

Correcting this issue: it is one form, not several

The body says to check "the Europass import and the plugin upload" and to fix one widget
rather than one template. Having looked, only one form exposes a bound model file field:

documents/forms.py:220   fields = ("title", "kind", "file", "notes", "replaces")

Everything else that takes a file does it differently and never renders Currently::

  • accounts/forms.py uses a plain forms.FileField for the profile picture — unbound, so
    Django has no stored value to print.
  • Company.logo is set programmatically and is on no form.
  • The Europass import and the plugin upload take a file and store nothing on a model field
    the same form then re-renders.

Currently: only appears for a ModelForm field bound to an instance that already has a
file
, and UploadedDocumentForm on the edit page is the only one of those. That makes the
fix smaller than written — though a widget rather than a template is still the better shape,
because the next ModelForm file field should not have to remember.

Still worth doing, and still only cosmetic-with-an-edge

Nothing here is exposed to anybody else: the path is the person's own, behind their own
login, and /media/ is already how they fetch it. The fault is that the field answers
which file is this? with Postulo's filing system instead of the filename, on a page whose
Title field two rows above already says "Reference".

d4b8bf3d6 (#167) stopped it scrolling the page sideways by letting the container wrap
anywhere. That stands on its own whatever string ends up there.

## Reproduced, and narrower than this issue claimed Rendered the page against a fresh upload, with a space in the filename to see the sanitising as well: Currently: <a href="/media/documents/1/2026/09/my_cv.pdf">documents/1/2026/09/my_cv.pdf</a><br> Change: <input type="file" name="file" class="field-input" id="id_file"> So it is exactly as described: the person uploaded `my cv.pdf` and is shown `documents/1/2026/09/my_cv.pdf` — their account id, the month, and a name Django rewrote. ### Correcting this issue: it is one form, not several The body says to check "the Europass import and the plugin upload" and to fix one widget rather than one template. Having looked, **only one form exposes a bound model file field**: documents/forms.py:220 fields = ("title", "kind", "file", "notes", "replaces") Everything else that takes a file does it differently and never renders `Currently:`: - `accounts/forms.py` uses a plain `forms.FileField` for the profile picture — unbound, so Django has no stored value to print. - `Company.logo` is set programmatically and is on no form. - The Europass import and the plugin upload take a file and store nothing on a model field the same form then re-renders. `Currently:` only appears for a **ModelForm field bound to an instance that already has a file**, and `UploadedDocumentForm` on the edit page is the only one of those. That makes the fix smaller than written — though a widget rather than a template is still the better shape, because the next ModelForm file field should not have to remember. ### Still worth doing, and still only cosmetic-with-an-edge Nothing here is exposed to anybody else: the path is the person's own, behind their own login, and `/media/` is already how they fetch it. The fault is that the field answers *which file is this?* with Postulo's filing system instead of the filename, on a page whose *Title* field two rows above already says "Reference". `d4b8bf3d6` (#167) stopped it scrolling the page sideways by letting the container wrap anywhere. That stands on its own whatever string ends up there.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Postulo/postulo#191
No description provided.