Repository navigation
Conversation
… refuse an answer for another account The web app refuses a certificate lookup answer whose cloud id isn't the one asked for, after the server's own normalisation. The share form refuses it; a share-save suspends that partner share as one whose certificate no longer verifies, so the save and the offline queue go on. The verifier refuses what the browser extension's port refuses: a self-issued intermediate, an empty cloud id on either side, an outer signature algorithm that differs from the TBS one, a signature with unused bits, strict common-name rules on the leaf only, and strict RSA-PSS parameters. It also refuses a leaf marked cA=TRUE, without backwards compatibility, and folds only the host's case of a cloud id. PARTNER_GONE pairs each reason with its status, so a reason on another status, such as a proxy's 500, is an ordinary error and suspends nothing. The browser root pin is dropped: the web app trusts its own server, which the spec records as a known limit. Closes #1257
Contributor
Quality Report — ConductionNL/keepiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| check-l10n-js | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| composer | ✅ | ✅ 114/114 | |||
| npm | ✅ | ✅ 660/660 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ✅ | ||||
| lockfile sync | ✅ | ||||
| PHPUnit | ✅ 2321/2321 · 3 skipped | ||||
| Newman | ✅ 177/177 · 20 skipped | ||||
| Playwright | ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it locally with npx playwright test, or from the Actions tab on a branch with no open pull request into development. |
||||
| Hydra gates | ✅ |
Quality workflow — 2026-10-16 15:15 UTC
Download the full PDF report from the workflow artifacts.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #1257, which includes #1281. It hardens how the web app checks a partner recipient's certificate. The two open questions on the issue were answered by the backend lead (see the questions comment): the web app trusts its own server, so there is no browser-side root pin, and a leaf with
cA=TRUEis refused without backwards compatibility.Cloud id check
lookup(src/store/modules/federatedShare.js) refuses an answer whose cloud id doesn't match the requested one, or an empty requested id, withCloudIdMismatchError.stripShareLinkFragmentsnormalisation (backslashes,/index.php, trailing slashes), and the scheme and host case are ignored on both sides, so every form the server accepts still matches.cloud_id_mismatch, as one whose certificate no longer verifies. It doesn't block the save or the offline queue: a mismatch there can only come from an honest server whose cloud id resolver rewrites the id, and it would happen on every save.Verifier (
src/crypto/federatedCertificate.js)It now refuses what the browser extension's port refuses, plus a CA leaf:
cA=TRUE(bad_chain), whatever its keyUsage says;malformedinstead of aTypeError.canonicalCloudIdfolds only the host's case, so the case of a cloud id's path now counts.Partner gone
PARTNER_GONE(src/services/shareSave.js) pairs each reason with its status:unknown_recipient404,not_a_partner403,bad_chain502. The same reason on another status, such as a proxy's 500, is an ordinary error and suspends nothing.Docs
openspec/specs/federated-sharing/spec.md: the lookup requirement lists the new refusals and the trust in the own server as a known limit, with two new scenarios; a cloud id mismatch suspends a share.openspec/changes/sharing-atomic-share-save/: the same suspension rule and the reason/status pairing, with a scenario.[Unreleased]Security: the CA:TRUE leaf refusal and the suspension it causes, and a Web app partner certificate check: trust in the own server, and verifier strictness #1257 entry.Related
cA=TRUEleaf too, on feat: Edit items and folders, share edits, themes and layout in the browser extension #1249 (848e5d89).Test plan
npx vitest run: 206 files, 1793 tests pass. Every guard has a test that fails without it, checked by reverting each one.npm run lint(0 errors),format,stylelint,test:l10n,check:l10n-jsandcheck:manifestpass.