nextcloud / nextcloud/server

Reject credential and other unsupported keys in `files_external:option`

Open
#58,821 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

0. Needs triage 32-feedback bug feature: external storage feature: occ good first issue papercut
Dominant language
PHP
Stars
36.9k
Forks
5.2k
Avg merge
2d 3h
Merged PRs (30d)
713

Description

⚠️ This issue respects the following points: ⚠️
Bug description

When configuring SMB external storage via occ, using:

php occ files_external:option <mount_id> password ''

stores a password field as a mount option. It can then be exposed in plaintext via:

php occ files_external:list --output=json

as options.password.

This is problematic for two reasons:

  1. It’s a potential secret-leak footgun (password in plaintext options output).
  2. It does not reliably set the SMB authentication credential where the SMB backend expects it (the correct credential setter is php occ files_external:config <mount_id> password '').

I’m proposing guardrails/warnings (or rejection) when attempting to set option keys like password via files_external:option, and updating docs/examples to steer admins to files_external:config for credential setting.

Steps to reproduce
  1. On a Nextcloud Server instance with the External storage support app enabled, create an SMB external storage mount (any valid SMB host/share/user is fine) and note the returned mount id <mount_id>.
  2. Run the following command to “set the password” via option:

php occ files_external:option <mount_id> password 'example-password'
3. List mounts in JSON:

php occ files_external:list --output=json

  1. Observe that the JSON for that mount includes a plaintext options.password field.
  2. Now set the password via the correct command:
php occ files_external:config <mount_id> password 'example-password'
php occ files_external:list --output=json
  1. Observe that configuration.password is treated as a credential (redacted in output), and options.password should not be used for credentials.
Expected behavior

I expected files_external:option <mount_id> password ... to either:

• be rejected (because password is a credential, not a mount option), or
• at minimum emit a clear warning that credentials must be set via files_external:config, and that storing a password as an option may expose it in output.

I also expected files_external:list --output=json to never include a plaintext password under options.* for any mount.

Nextcloud Server version

32

Operating system

Debian/Ubuntu

PHP engine version

PHP 8.3

Web server

Nginx

Database engine version

MariaDB

Is this bug present after an update or on a fresh install?

Updated from a MINOR version (ex. 32.0.1 to 32.0.2)

Are you using the Nextcloud Server Encryption module?

Encryption is Disabled

What user-backends are you using?
  • Default user-backend (database)
  • LDAP/ Active Directory
  • SSO - SAML
  • Other
Configuration report
{
    "system": {
        "passwordsalt": "***REMOVED SENSITIVE VALUE***",
        "secret": "***REMOVED SENSITIVE VALUE***",
        "trusted_domains": [
            "localhost",
            "wm3v.com",
            "nextcloud",
            "192.168.39.200"
        ],
        "datadirectory": "***REMOVED SENSITIVE VALUE***",
        "overwrite.cli.url": "https:\/\/wm3v.com\/nextcloud",
        "dbtype": "mysql",
        "version": "32.0.4.1",
        "dbname": "***REMOVED SENSITIVE VALUE***",
        "dbhost": "***REMOVED SENSITIVE VALUE***",
        "dbport": "",
        "dbtableprefix": "oc_",
        "dbuser": "***REMOVED SENSITIVE VALUE***",
        "dbpassword": "***REMOVED SENSITIVE VALUE***",
        "installed": true,
        "instanceid": "***REMOVED SENSITIVE VALUE***",
        "ldapIgnoreNamingRules": false,
        "ldapProviderFactory": "\\OCA\\User_LDAP\\LDAPProviderFactory",
        "updatechecker": false,
        "memcache.local": "\\OC\\Memcache\\APCu",
        "integrity.check.disabled": true,
        "filelocking.enabled": true,
        "memcache.locking": "\\OC\\Memcache\\Redis",
        "redis": {
            "host": "***REMOVED SENSITIVE VALUE***",
            "port": "6379",
            "timeout": "0.0",
            "password": "***REMOVED SENSITIVE VALUE***"
        },
        "logout_url": "https:\/\/wm3v.com\/yunohost\/sso\/?action=logout&r=aHR0cHM6Ly93bTN2LmNvbS9uZXh0Y2xvdWQ=",
        "updater.release.channel": "stable",
        "maintenance": false,
        "theme": "",
        "config_is_read_only": false,
        "loglevel": 2,
        "logtimezone": "America\/Denver",
        "default_phone_region": "US",
        "mail_smtpmode": "smtp",
        "mail_sendmailmode": "smtp",
        "mail_from_address": "***REMOVED SENSITIVE VALUE***",
        "mail_domain": "***REMOVED SENSITIVE VALUE***",
        "mail_smtpauthtype": "LOGIN",
        "mail_smtphost": "***REMOVED SENSITIVE VALUE***",
        "mail_smtpport": "25",
        "mail_smtpauth": 1,
        "mail_smtpname": "***REMOVED SENSITIVE VALUE***",
        "mail_smtppassword": "***REMOVED SENSITIVE VALUE***",
        "mail_smtpsecure": "ssl",
        "hashing_default_password": true,
        "mysql.utf8mb4": true,
        "app_install_overwrite": {
            "0": "spreed",
            "1": "sharerenamer",
            "2": "files_reader",
            "3": "radio",
            "4": "occweb",
            "6": "files_frommail",
            "7": "richdocuments",
            "8": "duplicatefinder",
            "9": "ransomware_protection",
            "10": "inventory",
            "11": "hedgenext"
        },
        "localstorage.allowsymlinks": true,
        "simpleSignUpLink.shown": false,
        "mail_smtpstreamoptions": {
            "ssl": {
                "allow_self_signed": true,
                "verify_peer": false,
                "verify_peer_name": false
            }
        },
        "logfile": "\/var\/log\/nextcloud\/nextcloud.log",
        "maintenance_window_start": 1,
        "quota_include_external_storage": false,
        "trusted_proxies": "***REMOVED SENSITIVE VALUE***",
        "trashbin_retention_obligation": "auto, 30",
        "versions_retention_obligation": "auto, 30",
        "forbidden_filename_basenames": [
            "con",
            "prn",
            "aux",
            "nul",
            "com0",
            "com1",
            "com2",
            "com3",
            "com4",
            "com5",
            "com6",
            "com7",
            "com8",
            "com9",
            "com\u00b9",
            "com\u00b2",
            "com\u00b3",
            "lpt0",
            "lpt1",
            "lpt2",
            "lpt3",
            "lpt4",
            "lpt5",
            "lpt6",
            "lpt7",
            "lpt8",
            "lpt9",
            "lpt\u00b9",
            "lpt\u00b2",
            "lpt\u00b3"
        ],
        "forbidden_filename_characters": [
            "<",
            ">",
            ":",
            "\"",
            "|",
            "?",
            "*",
            "\\",
            "\/"
        ],
        "forbidden_filename_extensions": [
            " ",
            ".",
            ".filepart",
            ".part"
        ]
    }
}
List of activated Apps
Enabled:
  - activity: 5.0.0-dev.0
  - admin_audit: 1.22.0
  - audioplayer: 3.7.0
  - camerarawpreviews: 0.8.8
  - circles: 32.0.0
  - cloud_federation_api: 1.16.0
  - comments: 1.22.0
  - contactsinteraction: 1.13.1
  - dav: 1.34.2
  - epubviewer: 1.9.2
  - federatedfilesharing: 1.22.0
  - files: 2.4.0
  - files_3dmodelviewer: 0.0.16
  - files_external: 1.24.0
  - files_fulltextsearch: 32.0.2
  - files_pdfviewer: 5.0.0-dev.0
  - files_sharing: 1.24.1
  - files_trashbin: 1.22.0
  - files_versions: 1.25.0
  - forms: 5.2.3
  - fulltextsearch: 32.0.0
  - impersonate: 3.0.1
  - keeweb: 0.6.22
  - logreader: 5.0.0-dev.0
  - lookup_server_connector: 1.20.0
  - nextcloud_announcements: 4.0.0-dev.0
  - notes: 4.12.4
  - notifications: 5.0.0-dev.0
  - notify_push: 1.3.0
  - oauth2: 1.20.0
  - password_policy: 4.0.0-dev.0
  - passwords: 2026.2.20
  - photos: 5.0.0-dev.1
  - privacy: 4.0.0-dev.0
  - profile: 1.1.0
  - provisioning_api: 1.22.0
  - secrets: 2.1.6
  - serverinfo: 4.0.0-dev.0
  - settings: 1.15.1
  - spreed: 22.0.9
  - support: 4.0.0-dev.0
  - text: 6.0.1
  - theming: 2.7.0
  - thesearchpage: 2.0.5
  - twofactor_backupcodes: 1.21.0
  - user_ldap: 1.23.0
  - user_status: 1.12.0
  - user_usage_report: 3.0.0
  - viewer: 5.0.0-dev.0
  - weather_status: 1.12.0
  - webhook_listeners: 1.3.0
  - workflowengine: 2.14.0
Disabled:
  - app_api: 32.0.0 (installed 5.0.2)
  - assistant: 2.12.0 (installed 2.12.0)
  - bruteforcesettings: 5.0.0-dev.0 (installed 2.9.0)
  - cadviewer: 10.10.7 (installed 10.10.7)
  - context_chat: 5.2.0 (installed 5.2.0)
  - dashboard: 7.12.0 (installed 7.2.0)
  - dicomviewer: 2.3.1 (installed 2.3.1)
  - encryption: 2.20.0
  - federation: 1.22.0 (installed 1.9.0)
  - files_downloadlimit: 5.0.0-dev.0 (installed 2.0.0)
  - files_linkeditor: 1.1.23 (installed 1.1.23)
  - files_photospheres: 1.32.0 (installed 1.32.0)
  - files_reader: 1.5.3 (installed 1.5.3)
  - files_reminders: 1.5.0 (installed 1.2.0)
  - files_rightclick: 1.6.0 (installed 1.6.0)
  - firstrunwizard: 5.0.0-dev.0 (installed 2.8.0)
  - integration_openai: 3.10.0 (installed 3.10.0)
  - inventory: 0.1.3 (installed 0.1.3)
  - keeporsweep: 0.3.0 (installed 0.3.0)
  - occweb: 0.2.3 (installed 0.2.3)
  - ransomware_protection: 1.14.0 (installed 1.14.0)
  - recommendations: 5.0.0-dev.0 (installed 0.7.0)
  - related_resources: 3.0.0-dev.0 (installed 1.4.0)
  - richdocuments: 9.0.2 (installed 9.0.2)
  - richdocumentscode: 25.4.702 (installed 25.4.702)
  - sharebymail: 1.22.0 (installed 1.8.0)
  - sms_relentless: 1.4.4 (installed 1.4.4)
  - survey_client: 4.0.0-dev.0 (installed 1.17.0)
  - suspicious_login: 10.0.0-dev.0
  - systemtags: 1.22.0 (installed 1.19.0)
  - twofactor_nextcloud_notification: 6.0.0-dev.0
  - twofactor_totp: 14.0.0
  - updatenotification: 1.22.0 (installed 1.21.0)
  - wordfind: 1.4.2 (installed 1.4.2)
  - workflow_media_converter: 1.15.1 (installed 1.15.1)
Nextcloud Signing status
Integrity checker has been disabled. Integrity cannot be verified.
Nextcloud Logs
N/A — this report is based on deterministic occ output (files_external:list --output=json) showing options.password after running files_external:option … password …. No specific Nextcloud log entry was required to reproduce.
Additional info

Running on Nextcloud Hub 25 (32.0.4) (YunoHost package 32.0.4~ynh1), PHP-FPM 8.3, MariaDB, nginx, Debian 12. External storage app files_external version 1.24.0. LDAP backend enabled (user_ldap).

Supporting write-up with more context (including YunoHost-specific SMB outage mode):

Related issues found while searching (likely different root causes; listed for context):

https://github.com/nextcloud/server/issues/58027
https://github.com/nextcloud/server/issues/30751
https://github.com/nextcloud/server/issues/29461
https://github.com/nextcloud/server/issues/3299
https://github.com/nextcloud/server/issues/57596
https://github.com/nextcloud/server/issues/36773

Disclosure: I used AI tools (Claude Sonnet 4.6 and OpenClaw / OpenAI Codex gpt‑5.2) to help structure/edit this report; technical claims are based on occ output and observed behavior.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the implementations of the files_external:option, files_external:config, and files_external:list commands in the files_external app, then compare how option and credential values are stored and serialized. Reproduce the commands from the issue and add coverage for unsupported keys such as password; done means credentials are rejected or clearly warned about and are not exposed under options in JSON output.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
backend, cli, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.