Cloudron makes it easy to run web apps like WordPress, Nextcloud, GitLab on your server. Find out more or install now.


Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Bookmarks
  • Search
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo

Cloudron Forum

Offical apps | Community apps | Demo | Docs | Install
  1. Cloudron Forum
  2. Surfer
  3. Surfer: /api/zip serves the whole site anonymously even when "Public folder listing" is off

Surfer: /api/zip serves the whole site anonymously even when "Public folder listing" is off

Scheduled Pinned Locked Moved Surfer
2 Posts 2 Posters 70 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • jagadeesh-s2104J
    jagadeesh-s2104J
    jagadeesh-s2104
    wrote last edited by
    #1

    Hello @nebulon - I'm using Surfer as a simple "link-only" static host. Access is Public, Public folder listing is off, and each set of pages lives under an unguessable folder name, so only people who get the link can read it. That model holds for normal browsing: with listing off, unknown folders return 404. But /api/zip gets around it.

    Environment

    • Cloudron 10.0.5
    • Surfer package 7.2.6 (upstream at c5329dc, 2026-10-06)
    • Settings: access = Public, Public folder listing = off

    Steps to reproduce

    1. Set Surfer access to Public and turn Public folder listing off.
    2. Upload some content into a folder, for example /some-unguessable-name/index.html.
    3. From a logged-out browser or curl:
      curl -o all.zip 'https://surfer.example.com/api/zip?paths=%5B%22%2F%22%5D'
      unzip -l all.zip
      

    Expected: the request is refused (401/404), because folder listing is off, so anonymous visitors shouldn't be able to enumerate or bulk-download content they don't have a URL for.

    Actual: 200 application/zip containing the entire site root, including every folder name, so anyone who can reach the host can discover and download everything.

    Why it happens

    • src/routes/index.js:79: router.get('/api/zip', access.handleProtection, publicSite.zipDownload);. On a Public site, handleProtection lets everyone through, and folderListingEnabled is never consulted.
    • src/routes/public.js zipDownload() accepts any paths inside the site root, and "/" is allowed.
    • Related: the deployment query parameter (sites.rootForQuery()) lets an anonymous caller zip another named site's root (public-<name>) through the same endpoint, from any of the app's domains.

    The only callers I could find are the public listing UI (frontend/utils.js:55, used by Public.vue) and the admin file view (views/FilesView.vue). So when listing is off, the anonymous use case for this endpoint doesn't exist.

    Suggested fix: a "Public zip downloads" on/off setting

    Add a setting next to "Public folder listing", stored the same way as folderListingEnabled:

    Public zip downloads: when enabled, anonymous visitors can download folders as a .zip. When disabled, only signed-in users can (the admin file view keeps working).

    • Default: existing installs inherit their current folderListingEnabled value, so nobody's behavior changes on update. Listing-on sites keep their download button, and listing-off sites stop leaking.
    • Gate: when the switch is off, /api/zip requires auth. A deployment= request always requires auth, because anonymous visitors shouldn't be able to zip other sites.
    • Public UI: hide the folder/multi-select "Download" action when the switch is off. Single-file downloads use ?download and keep working.

    Rough sketch (untested):

    // src/settings.js
    const DEFAULTS = { folderListingEnabled: false, publicZipEnabled: null, /* ... */ };
    // normalize(): null/undefined -> follow folderListingEnabled (backwards compatible)
    publicZipEnabled: values.publicZipEnabled == null
        ? (values.folderListingEnabled === true || values.folderListingEnabled === 'true')
        : (values.publicZipEnabled === true || values.publicZipEnabled === 'true'),
    // storedValue(): add 'publicZipEnabled' to the boolean keys
    
    // src/routes/settings.js
    // get(): publicZipEnabled: !!config.publicZipEnabled,
    // put(): optional, so older clients that don't send it keep working
    if ('publicZipEnabled' in req.body && typeof req.body.publicZipEnabled !== 'boolean') return next(new HttpError(400, 'publicZipEnabled must be a boolean'));
    if ('publicZipEnabled' in req.body) config.publicZipEnabled = req.body.publicZipEnabled;
    
    // src/routes/index.js
    function zipAccess(req, res, next) {
        if (config.publicZipEnabled && !req.query.deployment) return access.handleProtection(req, res, next);
        return auth.requireAuth(req, res, next);   // admin sessions / app passwords still work
    }
    router.get('/api/zip', zipAccess, publicSite.zipDownload);
    
    // frontend/views/SettingsView.vue: one more <Switch v-model="settings.publicZipEnabled">, like folder listing
    // frontend/Public.vue: hide the zip-download action when !settings.publicZipEnabled
    

    If a setting is more than you'd like to add, the minimal version is simply to tie the gate to config.folderListingEnabled instead of a new key.

    1 Reply Last reply
    3
    • girishG
      girishG
      girish
      Staff
      wrote last edited by
      #2

      Instead of making a new setting, I think it's better to simply disable zip downloads when public listing is disabled. I have made this fix. Will release shortly.

      1 Reply Last reply
      1

      Hello! It looks like you're interested in this conversation, but you don't have an account yet.

      Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

      With your input, this post could be even better 💗

      Register Login
      Reply
      • Reply as topic
      Log in to reply
      • Oldest to Newest
      • Newest to Oldest
      • Most Votes


      • Login

      • Don't have an account? Register

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Bookmarks
      • Search