docusealco/docuseal · error · Submitters::NormalizeValues::InvalidDefaultValue
File type '.#{extension}' is not allowed.
Error message
File type '.#{extension}' is not allowed. What it means
Submitters::NormalizeValues#find_or_create_blob_from_url (lib/submitters/normalize_values.rb:282) raises InvalidDefaultValue when the extension of the URL's last path segment (File.extname, downcased) is in Submitters::DANGEROUS_EXTENSIONS. The check runs before any download: it is purely filename-based on the remote URL, so 'https://host/payload.exe' is rejected immediately while extension-less URLs proceed to DownloadUtils with SSRF validation.
Source
Thrown at lib/submitters/normalize_values.rb:282
checksum = Digest::MD5.base64digest(data)
blob = find_blob_by_checksum(checksum, account)
blob || ActiveStorage::Blob.create_and_upload!(
io: StringIO.new(data),
filename: "#{type}.png",
content_type: 'image/png',
metadata: { analyzed: true, identified: true, width:, height: }
)
end
def find_or_create_blob_from_url(account, url)
filename = Addressable::URI.parse(url).path.split('/').last.to_s
extension = File.extname(filename).delete_prefix('.').downcase
if Submitters::DANGEROUS_EXTENSIONS.include?(extension)
raise InvalidDefaultValue, "File type '.#{extension}' is not allowed."
end
cache_key = [account.id, url].join(':')
checksum = CHECKSUM_CACHE_STORE.fetch(cache_key)
blob = find_blob_by_checksum(checksum, account) if checksum
return blob if blob
data = DownloadUtils.call(url, validate: true).body
checksum = Digest::MD5.base64digest(data)
CHECKSUM_CACHE_STORE.write(cache_key, checksum)
blob = find_blob_by_checksum(checksum, account)
blob || ActiveStorage::Blob.create_and_upload!(io: StringIO.new(data), filename:)View on GitHub (pinned to 004a22c1c8)
Solutions
- Point the URL at a safe, allowed document/image resource (pdf, png, jpg, docx...).
- If the asset is legitimately named with a dangerous extension, re-host it under a safe filename or bundle it into a zip/pdf and link that.
- Rescue Submitters::NormalizeValues::InvalidDefaultValue and surface the message as a 422 so callers see the rejected extension.
Example fix
# before
{ 'default_value' => 'https://cdn.example.com/downloads/setup.exe' }
# after
{ 'default_value' => 'https://cdn.example.com/downloads/instructions.pdf' } Defensive patterns
Strategy: validation
Validate before calling
# Check the URL's last path segment against the same blocklist
ext = File.extname(URI.parse(url).path.split('/').last.to_s).delete_prefix('.').downcase
raise ArgumentError, "File type '.#{ext}' is not allowed." if Submitters::DANGEROUS_EXTENSIONS.include?(ext) Try / catch
begin
Submitters::NormalizeValues.normalize_attachment_value(url, field, account, attachments, purpose: :api)
rescue Submitters::NormalizeValues::InvalidDefaultValue => e
render json: { error: e.message }, status: :unprocessable_entity
end Prevention
- Link to safe document/image assets only; keep dangerous binaries off asset URLs.
- The check reads the URL path, not Content-Type — re-host under a safe filename when needed.
- Signed-URL filenames inherit the original extension; generate them from safe originals.
When it happens
Trigger: An API default_value URL ending in .exe/.sh/.jar/.dll/.apk etc.; URLs with query strings after the dangerous extension (extname still resolves to the last segment); test/probing calls pointing at executable downloads.
Common situations: Integrations pre-filling attachments from asset servers that host both documents and binaries; URL signed-asset filenames retaining the original dangerous extension; users pasting direct download links to installers.
Related errors
- File type '.#{detected_extensions.first}' is not allowed.
- File type '.#{extension}' is not allowed.
- Error loading: #{uri}. Only HTTPS is allowed.
- Error loading: #{uri}. Can't download from localhost.
- Invalid #{type} value
AI-assisted analysis of docusealco/docuseal@004a22c1c8 (2026-08-21).
Data as JSON: /api/errors/c8b917ef70539cef.
Report an issue: GitHub.