docusealco/docuseal · error · Submitters::NormalizeValues::InvalidDefaultValue
File type '.#{detected_extensions.first}' is not allowed.
Error message
File type '.#{detected_extensions.first}' is not allowed. What it means
Submitters::NormalizeValues#find_or_create_blob_from_base64 (lib/submitters/normalize_values.rb:251) raises InvalidDefaultValue when any extension Marcel maps for the decoded payload's MIME type is in Submitters::DANGEROUS_EXTENSIONS. The content is sniffed from the decoded bytes (Marcel::MimeType.for), so this is a content-based blocklist: base64-encoded executables/scripts/installers are rejected even when the field name suggests an image. The message names the first detected extension.
Source
Thrown at lib/submitters/normalize_values.rb:251
end
def find_or_create_blob_from_html(_account, value, _field)
raise InvalidDefaultValue, "HTML content is not allowed: #{value.first(200)}..."
end
def find_or_create_blob_from_base64(account, data, type, mime_type: nil)
checksum = Digest::MD5.base64digest(data)
blob = find_blob_by_checksum(checksum, account)
return blob if blob
mime_type ||= Marcel::MimeType.for(data)
detected_extensions = Marcel::TYPE_EXTS[mime_type].to_a.map(&:downcase)
if detected_extensions.any? { |e| Submitters::DANGEROUS_EXTENSIONS.include?(e) }
raise InvalidDefaultValue, "File type '.#{detected_extensions.first}' is not allowed."
end
extension = detected_extensions.first
extension = 'png' if extension.blank? && type.in?(%w[signature initials stamp image])
filename = extension.present? ? "#{type}.#{extension}" : type
ActiveStorage::Blob.create_and_upload!(io: StringIO.new(data), filename:)
end
def find_or_create_blob_from_text(account, text, type)
data, width, height = Submitters::GenerateFontImage.call(text, font: type)
checksum = Digest::MD5.base64digest(data)
blob = find_blob_by_checksum(checksum, account)
blob || ActiveStorage::Blob.create_and_upload!(View on GitHub (pinned to 004a22c1c8)
Solutions
- Upload only document/image formats (pdf, png, jpeg, docx...) as base64 attachment values.
- If you believe the file is safe and misdetected, re-encode it in a canonical format (e.g. zip it or convert to pdf) so the sniffed type is concrete and allowed.
- Rescue Submitters::NormalizeValues::InvalidDefaultValue and return the message verbatim in a 422 so the caller sees which type was detected.
Example fix
# before
attachment_value = Base64.strict_encode64(File.read('tool.exe'))
# after (ship the binary out-of-band; attach a document instead)
attachment_value = Base64.strict_encode64(File.read('guide.pdf')) Defensive patterns
Strategy: validation
Validate before calling
# Sniff the decoded bytes locally and reject dangerous types before upload
EXTS = Marcel::TYPE_EXTS[Marcel::MimeType.for(decoded_bytes)].to_a.map(&:downcase)
raise ArgumentError, 'dangerous content type' if EXTS.any? { |e| Submitters::DANGEROUS_EXTENSIONS.include?(e) } Try / catch
begin
Submitters::NormalizeValues.normalize_attachment_value(base64_value, field, account, attachments, purpose: :api)
rescue Submitters::NormalizeValues::InvalidDefaultValue => e
render json: { error: e.message }, status: :unprocessable_entity
end Prevention
- Only embed document/image formats as base64 defaults.
- Remember this check sniffs CONTENT (Marcel), not the filename — renaming does not help.
- Re-package unusual binaries as zip/pdf if they must be delivered alongside the submission.
When it happens
Trigger: A base64 default_value for an attachment field whose decoded bytes identify as exe/bat/sh/jar/dll/apk etc.; a polyglot file whose sniffed type maps to a dangerous extension; re-encoding an existing dangerous file to base64 to smuggle it past the filename check.
Common situations: Users base64-embedding installers or scripts as 'attachments' via the API; testers probing whether content sniffing exists (it does); MIME mis-detection of unusual binary formats landing on a blocklisted extension.
Related errors
- File type '.#{extension}' is not allowed.
- File type '.#{extension}' is not allowed.
- Invalid value, url, base64 or text < 60 chars is expected: #
- Invalid #{type} value
- HTML content is not allowed: #{value.first(200)}...
AI-assisted analysis of docusealco/docuseal@004a22c1c8 (2026-08-21).
Data as JSON: /api/errors/ea9c4bcbb4dd948a.
Report an issue: GitHub.