Skip to content

feat: add scope control for password complexity rules#415

Open
rohasmsk wants to merge 1 commit into
owncloud:masterfrom
rohasmsk:splitting-password-policy-users-and-links
Open

feat: add scope control for password complexity rules#415
rohasmsk wants to merge 1 commit into
owncloud:masterfrom
rohasmsk:splitting-password-policy-users-and-links

Conversation

@rohasmsk

Copy link
Copy Markdown

Summary

  • Add two checkboxes to the "Minimum password requirements" section in
    admin security settings: Apply to user account passwords and
    Apply to public link passwords (both enabled by default —
    no change in behavior for existing installations)
  • Complexity rules (min length, lowercase, uppercase, numbers, special
    chars) are now skipped for the unchecked scope; password history,
    expiration and force-change-on-first-login rules are unaffected and
    continue to apply to user accounts only
image

Motivation

Workaround for #359
This change provides a workaround for #359.

Installations using OpenID Connect (or other external identity
providers) can now disable complexity checks for user account passwords,
since those users authenticate via their IdP which enforces its own
password policies. Applying ownCloud's complexity rules on top is
redundant and causes friction. At the same time, complexity rules for
public link passwords remain fully functional.

Allow admins to selectively apply complexity rules to user account passwords, public link
passwords, or both via two new checkboxes in the security settings.
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


Maksim Martynov seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@dj4oC dj4oC left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adds two admin checkboxes ("Apply to user account passwords" / "Apply to public link passwords") intended to let admins scope complexity-rule enforcement independently for user accounts vs. public links.

Findings

Security

  • Dead/non-functional setting — "Apply to public link passwords" does nothing (A05:2021 Security Misconfiguration; related CWE-1164 Irrelevant Code controlling a security decision). spv_apply_to_links_checked is added to SettingsController::DEFAULTS and rendered in templates/admin.php, but Engine::verifyPassword() never reads it. Only the $type === 'user' branch is gated by spv_apply_to_users_checked; the $type === 'public' path is completely unchanged and always runs the full complexity check. Unchecking the "public link" box has zero effect — it fails "safe" (rules stay enforced) rather than open, but it's a broken control: the admin UI claims a capability the enforcement code doesn't implement, which is misleading and should be fixed (and tested) before merge.
  • Scope is broader than the stated intent (A05:2021 Security Misconfiguration; CWE-521 Weak Password Requirements as a consequence). The PR's motivation is to skip complexity checks for OIDC/IdP-authenticated users, but spv_apply_to_users_checked is a single global toggle for every local user password change — including the built-in admin, service/technical accounts, and any user not actually behind the IdP. Unchecking it to accommodate SSO users silently weakens password-strength enforcement for accounts that still rely on ownCloud-managed passwords, with no warning in the UI. Recommend either scoping enforcement by auth backend/IdP-managed status, or at minimum adding an explicit warning in the settings UI/docs that this applies to all local accounts.
  • CSRF: no new endpoint was added (reuses the existing updatePolicy() action, which is still protected by the existing requesttoken), and no @NoCSRFRequired annotation was introduced — no regression here.
  • XSS: the new template output only branches on truthiness for the checked attribute, consistent with existing checkboxes; no unescaped echo of new data — no finding.
  • The $type argument to Engine::verifyPassword() is hardcoded per call site in HooksHandler (verifyUserPassword / verifyPublicPassword), not attacker-influenceable, so there is no way to flip scope from an unprivileged request.

Stability

  • Same dead-toggle issue as above is also a functional/correctness bug: half of the advertised feature (public link scoping) is not wired up.
  • Minor inconsistency: the two new defaults use the string 'true' while every other _checked default in the same array uses the PHP boolean false. It happens to work today because 'true' is truthy, but it's inconsistent with the codebase convention and is worth aligning to true (boolean) for clarity/future-proofing.
  • The new if (\substr($key, -8) === '_checked') { ...set false... } branch in updatePolicy() changes the "unset & reset-to-default" resolution path for all _checked keys, not just the two new ones. It's a no-op today since existing _checked defaults were already false, but it's a broad behavioral change tucked into a feature PR — worth flagging explicitly in the PR description.

Performance
Nothing blocking.

Test coverage
No PHPUnit tests were added or updated. The repo already has tests/unit/EngineTest.php and a tests/unit/Controller suite covering exactly this surface, but the PR (3 files changed) does not touch any test file. The new scope-skip branch in Engine::verifyPassword() and the new default-reset branch in SettingsController::updatePolicy() are both untested.

Verdict

Changes requested

🤖 Automated review by Claude Code (security · stability · performance · coverage)


Generated by Claude Code

dj4oC commented Jul 8, 2026

Copy link
Copy Markdown
Contributor
  • Security: 2 findings — see review (A05:2021 Security Misconfiguration: dead "apply to public link passwords" setting, CWE-1164; and over-broad scope of "apply to user account passwords" affecting all local accounts, related CWE-521)
  • Stability: 2 findings — see review (dead link-scope toggle is also a functional bug; default-value type inconsistency for new _checked keys)
  • Performance: no findings
  • Test coverage: no PHPUnit tests added/updated for the new logic in Engine::verifyPassword() or SettingsController::updatePolicy(), despite existing tests/unit/EngineTest.php and tests/unit/Controller suites covering this surface
  • TODOs found: none
  • Dependency touched: no
  • CI status: no check runs configured/reported on the head commit; CLA assistant reports CLA not signed (commit author "Maksim Martynov" not linked to a GitHub account)
  • Stale review: no

🤖 Automated review by Claude Code (security · stability · performance · coverage)


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants