403 status code when attaching files on custom web form

We have a custom web form with an file attachment field. The upload fails with an PermissionError (frappe.exceptions.PermissionError) and http status 403 (“Forbidden”) when a user is not logged in (see stack trace below).

This is a custom job application form so it cannot require user authentication. Enabling the web form’s “anonymous” checkbox in the Settings tab doesn’t solve this.

Traceback (most recent call last):
  File "apps/frappe/frappe/app.py", line 110, in application
    response = frappe.api.handle(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "apps/frappe/frappe/api/__init__.py", line 49, in handle
    data = endpoint(**arguments)
           ^^^^^^^^^^^^^^^^^^^^^
  File "apps/frappe/frappe/api/v1.py", line 36, in handle_rpc_call
    return frappe.handler.handle()
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "apps/frappe/frappe/handler.py", line 49, in handle
    data = execute_cmd(cmd)
           ^^^^^^^^^^^^^^^^
  File "apps/frappe/frappe/handler.py", line 85, in execute_cmd
    return frappe.call(method, **frappe.form_dict)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "apps/frappe/frappe/__init__.py", line 1684, in call
    return fn(*args, **newargs)
           ^^^^^^^^^^^^^^^^^^^^
  File "apps/frappe/frappe/utils/typing_validations.py", line 31, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "apps/frappe/frappe/handler.py", line 173, in upload_file
    raise frappe.PermissionError
frappe.exceptions.PermissionError

If I happen to be logged into the system then the attachment works fine, returning a 200 status code.

{
    "message": {
        "name": "d2af2bb957",
        "owner": "<redacted>",
        "creation": "2024-05-20 12:46:39.094560",
        "modified": "2024-05-20 12:46:39.094560",
        "modified_by": "<redacted>",
        "docstatus": 0,
        "idx": 0,
        "file_name": "resume.docx",
        "is_private": 1,
        "is_home_folder": 0,
        "is_attachments_folder": 0,
        "file_size": 828873,
        "file_url": "/private/files/resume.docx",
        "folder": "Home",
        "is_folder": 0,
        "content_hash": "04d9cde4ef97c4ab5878b70fffa9708b",
        "uploaded_to_dropbox": 0,
        "uploaded_to_google_drive": 0,
        "doctype": "File"
    }
}

Frontend application logs:

186.132.223.59 - - [20/May/2024:15:27:14 +0000] "POST /api/method/upload_file HTTP/1.1" 403 427 "https://<redacted>/job-application/new?job_title=HR-OPN-2024-0012" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"

Can someone point us in the right direction of what might be going on here?

I finally solved this. By default ERPNext doesn’t allow anonymous/guest attachment uploads but t can be enabled by toggling “Allow Guests to Upload Files” in System Settings.

I guess it comes with risks since you open up the door to untrusted users uploading stuff to ERPNext but at least the feature is there.