feat: add scope control for password complexity rules#415
Conversation
Allow admins to selectively apply complexity rules to user account passwords, public link passwords, or both via two new checkboxes in the security settings.
|
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
left a comment
There was a problem hiding this comment.
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_checkedis added toSettingsController::DEFAULTSand rendered intemplates/admin.php, butEngine::verifyPassword()never reads it. Only the$type === 'user'branch is gated byspv_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_checkedis 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 existingrequesttoken), and no@NoCSRFRequiredannotation was introduced — no regression here. - XSS: the new template output only branches on truthiness for the
checkedattribute, consistent with existing checkboxes; no unescaped echo of new data — no finding. - The
$typeargument toEngine::verifyPassword()is hardcoded per call site inHooksHandler(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_checkeddefault in the same array uses the PHP booleanfalse. It happens to work today because'true'is truthy, but it's inconsistent with the codebase convention and is worth aligning totrue(boolean) for clarity/future-proofing. - The new
if (\substr($key, -8) === '_checked') { ...set false... }branch inupdatePolicy()changes the "unset & reset-to-default" resolution path for all_checkedkeys, not just the two new ones. It's a no-op today since existing_checkeddefaults were alreadyfalse, 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
🤖 Automated review by Claude Code (security · stability · performance · coverage) Generated by Claude Code |
Summary
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)
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
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.