instructure/canvas-lms · error · Attachment::OverQuotaError
Zip contents exceed course quota limit
Error message
Zip contents exceed course quota limit
What it means
charge_quota in lib/unzip_attachment.rb:299 raises Attachment::OverQuotaError when an individual extracted entry's size exceeds the remaining quota tracked during extraction. Because zip central directories can lie about entry sizes, Canvas decrements @quota_remaining per entry to defend against zip-bomb denial-of-service attacks.
Solutions
- Treat the upload as suspicious and verify the zip source; use a zip-bomb scanner for untrusted uploads
- Free up quota in the target context and re-upload a smaller, verified archive
- Delete partially extracted files from the failed attempt before retrying
- Do not loosen this check — it is the anti-zip-bomb defense
Example fix
// before # zip declares 100KB entries but inflates to 5GB each UnzipAttachment.process(course, 'sneaky.zip') // after # pre-scan: reject zips with suspicious compression ratios or nested zips before processing
Defensive patterns
Strategy: try-catch
Validate before calling
raise SuspiciousZip if zip_compression_ratio(zip_path) > MAX_SAFE_RATIO
Try / catch
begin
UnzipAttachment.process(context, zip)
rescue Attachment::OverQuotaError => e
logger.warn("possible zip bomb: #{e.message}")
mark_upload_flagged(upload)
end Prevention
- Never disable charge_quota — it blocks zip bombs
- Pre-scan untrusted zips for nested archives and extreme ratios
- Remove partially extracted artifacts after failure
When it happens
Trigger: Extraction encounters an entry whose actual inflated size exceeds @quota_remaining (quota was set by validate_against); a maliciously crafted or corrupted zip whose declared sizes are smaller than the real content.
Common situations: Malicious zip bombs uploaded by users; zips with inaccurate central directory metadata; legitimately large files uploaded when the course was just under quota per nominal size.
Related errors
- Zip file would exceed quota limit
- can't build pseudonym_credentials except on just-generated…
- Cannot generate a symmetric, non-encrypted JWT
- Zip File cannot have more than #
- A new_id, '# ', referenced an existing # and the # with #…
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/a0cf7da6b3ae5478.
Report an issue: GitHub.
Appendix: source
Thrown at lib/unzip_attachment.rb:299
# check whether the nominal size of the zip's contents would exceed
# quota, and reject the zip immediately if so
quota_hash = Attachment.get_quota(context)
if quota_hash[:quota] > 0
if (quota_hash[:quota_used] + total_size) > quota_hash[:quota]
raise Attachment::OverQuotaError, "Zip file would exceed quota limit"
end
@quota_remaining = quota_hash[:quota] - quota_hash[:quota_used]
end
end
# since the central directory can lie, track quota during extraction as well
# to prevent zip bomb denial-of-service attacks
def charge_quota(size)
return if @quota_remaining.nil?
if size > @quota_remaining
raise Attachment::OverQuotaError, "Zip contents exceed course quota limit"
end
@quota_remaining -= size
end
def paths_with_positions(base)
positions_hash = {}
paths.sort.each_with_index { |p, idx| positions_hash[p] = idx + base }
positions_hash
end
def percent_complete(current_index)
(current_index + 1).to_f / file_count.to_f
end
private
def process!View on GitHub (pinned to 1c9f0bb801)