8000 🟡 Security: Align file upload size limits across nginx and application · Issue #84 · jra3/mulm · GitHub
[go: up one dir, main page]

Skip to content

🟡 Security: Align file upload size limits across nginx and application #84

Closed

Description

@jra3

Problem

File upload size limits are inconsistent across different layers:

  • nginx.conf: 50MB (client_max_body_size)
  • default.conf uploads location: 100MB (client_max_body_size)
  • Application (multer): 10MB (fileSize limit)

Locations:

  • nginx/nginx.conf:25 - client_max_body_size 50M
  • nginx/conf.d/default.conf:95 - client_max_body_size 100M (uploads)
  • src/routes/api/upload.ts:27 - fileSize: 10 * 1024 * 1024 (10MB)

Issues

  1. Confusion - Unclear what the actual limit is
  2. Wasted bandwidth - nginx might accept 100MB file, then app rejects at 10MB
  3. Poor user experience - Error happens after upload completes
  4. Security - Inconsistent enforcement

Solution

Align all limits to 10MB (current application limit is reasonable):

1. Fix nginx.conf

# nginx/nginx.conf:25
client_max_body_size 10M;  # Changed from 50M

2. Fix default.conf

# nginx/conf.d/default.conf - Upload endpoints
location ~ ^/(submission|tank|upload) {
    limit_req zone=uploads burst=10 nodelay;
    client_max_body_size 10M;  # Changed from 100M
    # ... rest of config
}

3. Document in Code

// src/routes/api/upload.ts
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB - must match nginx limits

const upload = multer({
  storage: multer.memoryStorage(),
  limits: {
    fileSize: MAX_FILE_SIZE, // 10MB - enforced at nginx + app layers
    files: 5
  },
  // ...
});

4. Add Configuration Constant

// src/config.ts or constants.ts
export const UPLOAD_LIMITS = {
  MAX_FILE_SIZE_MB: 10,
  MAX_FILE_SIZE_BYTES: 10 * 1024 * 1024,
  MAX_FILES_PER_REQUEST: 5,
  TOTAL_MAX_SIZE_MB: 50 // 5 files * 10MB
};

Implementation Steps

  1. Update nginx.conf to 10M
  2. Update default.conf uploads location to 10M
  3. Add UPLOAD_LIMITS constant
  4. Update multer config to use constant
  5. Update image processing to use constant
  6. Add validation check on startup
  7. Document limits in API documentation
  8. Test with file exactly at limit
  9. Deploy nginx config to production

Deployment

# Copy updated nginx configs to production
scp nginx/nginx.conf BAP:/tmp/
scp nginx/conf.d/default.conf BAP:/tmp/

# Apply changes
ssh BAP "sudo cp /tmp/nginx.conf /opt/basny/nginx/ && \
         sudo cp /tmp/default.conf /opt/basny/nginx/conf.d/ && \
         sudo docker exec basny-nginx nginx -t && \
         sudo docker exec basny-nginx nginx -s reload"

Testing

# Test file at limit (should succeed)
dd if=/dev/zero of=test-10mb.jpg bs=1M count=10
curl -X POST -F "images=@test-10mb.jpg" https://bap.basny.org/api/upload/image

# Test file over limit (should fail immediately)
dd if=/dev/zero of=test-11mb.jpg bs=1M count=11
curl -X POST -F "images=@test-11mb.jpg" https://bap.basny.org/api/upload/image
# Should see nginx 413 error, not application error

Alternative: Increase to 20MB?

If users need larger files, consider:

  • 20MB allows higher resolution images
  • Sharp will still optimize/resize
  • Increase all three limits to 20MB

Discuss with product owner.

Related

Priority: Medium - Affects user experience and clarity
Effort: Low - 30 minutes

Activity

  1. added
    bugSomething isn't working
    securitySecurity improvements and vulnerability fixes
    infrastructureInfrastructure, deployment, and DevOps
    priority:mediumMedium priority - important but not urgent
    on Oct 6, 2025
  2. jra3 commented on Oct 7, 2025

    @jra3
    OwnerAuthor

    Consolidated into master issue #115. See #115 for comprehensive tracking of all image upload enhancements.

  3. jra3 commented on Nov 4, 2025

    @jra3
    OwnerAuthor

    ✅ Resolved: Nginx Upload Size Limit Alignment

    Changes made:

    1. Updated nginx upload limit (nginx/conf.d/default.conf:95)

      • Changed from 100M to 52M
      • Rationale: App allows 5 files × 10MB = 50MB total, plus 2MB overhead for request metadata
    2. Updated documentation (nginx/README.md:63)

      • Documented the alignment between nginx and app limits
      • Added explanation: "5 files × 10MB + overhead"

    Current limits:

    • ✅ App: 10MB per file, max 5 files = 50MB total
    • ✅ Nginx upload routes: 52MB
    • ✅ Nginx global: 50M

    All limits are now properly aligned. Users will get clearer error messages when exceeding limits at the nginx level rather than waiting for the app to reject files.

    To apply in production:

    scp nginx/conf.d/default.conf BAP:/tmp/
    ssh BAP "sudo cp /tmp/default.conf /opt/basny/nginx/conf.d/ && sudo docker exec basny-nginx nginx -t && sudo docker exec basny-nginx nginx -s reload"
  4. added a commit that references this issue on Nov 4, 2025
    d89b150
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinginfrastructureInfrastructure, deployment, and DevOpspriority:mediumMedium priority - important but not urgentsecuritySecurity improvements and vulnerability fixes

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0