The cipher access restriction queries (direct collection access, group
collection access, and full access via groups) never checked the
organization membership status. Since users_collections and groups_users
rows are kept when a membership is revoked, revoked (and not yet
confirmed) members kept read, write, delete, attachment and
collection-move access to org ciphers via the direct-by-UUID endpoints.
Require a confirmed membership in the cipher's organization in all
three queries, matching the behavior of the sync queries.
Co-authored-by: Daniel García <dani-garcia@users.noreply.github.com>
Introduced in 2026.4.1 Mobile releases (Android and iOS), enables use of
device camera to autofill a card type item.
N.B. This feature relies on Google ML Kit. F-Droid policy disallows
Google ML Kit. Because of this, F-Droid builds do not ship with card
scanner feature. (See https://github.com/bitwarden/android/pull/6890)
When `archiveDate` is set to `null` it should unarchive it for that
specific user, which is what Bitwarden does.
This should fix this by checking and validating if it is `null`
Fixes#7581
Signed-off-by: BlackDex <black.dex@gmail.com>
* storage: route OpenDAL through HTTP client
OpenDAL 0.58 requires applications to provide an HTTP transport. Its
default installer creates a standalone client, bypassing Vaultwarden
DNS, redirect, proxy, timeout, and request configuration.
Build the client through the internal HTTP interface and inject it into
OpenDAL's public reqwest transport.
* http: honor block setting on redirects
Clients can disable host blocking for administrator-configured private
services. DNS resolution honors this setting, but the redirect policy
still performs config-backed host checks.
Capture the setting in the redirect policy and skip those checks when
blocking is disabled. This also avoids re-entering CONFIG when a remote
configuration request is redirected during startup.
* http: make DNS setup bootstrap-safe
Remote configuration can require an HTTP client while CONFIG is still
initializing. Building the DNS resolver currently reads
CONFIG.dns_prefer_ipv6(), so loading an S3-backed config can deadlock.
Build one resolver without consulting CONFIG. Order addresses for each
lookup using the merged setting when available, falling back to the
environment and then IPv4-first during bootstrap.
* aws: use internal HTTP client
The AWS SDK connector builds a raw reqwest client, bypassing
Vaultwarden TLS, DNS, redirect, proxy, timeout, and request setup.
Construct it through the internal HTTP client interface and retain the
standard ten-second request deadline. Permit private AWS metadata and
service endpoints by disabling non-global IP blocking.
Preserve timeout errors when adapting reqwest failures to the AWS SDK so
the runtime receives the correct connector error category.
* Added comment for the prefer IPv function
Signed-off-by: BlackDex <black.dex@gmail.com>
---------
Signed-off-by: BlackDex <black.dex@gmail.com>
Co-authored-by: BlackDex <black.dex@gmail.com>
- Update Rust to v1.98.1 which resolves a build issues with strange
outcomes
- Adjusted the DockerSettings and render_template to extract the
`rust_version` from the `rust-toolchain.toml` file. This should
prevent mismatches and forgetting to update DockerSettings.
- Updated typos in GHA and Pre-Commit
- Updated all possible crates including hickory which has several CVE's
fixed.
Signed-off-by: BlackDex <black.dex@gmail.com>
Docker only recognizes `#` as a valid comment indicator in .dockerignore files.
Using `//` causes the lines to be incorrectly parsed as glob patterns rather than comments.
While this may not cause fatal errors if no matching files exist, it is syntactically invalid and could lead to unexpected behavior. Corrected the syntax to use `#`.
The three "Username or password is incorrect" errors in
send_email_login() (email.rs) don't log the client IP or submitted
identifier, unlike the equivalent wrong-password error in
password_login() (identity.rs), which logs both via
format!("IP: {}. Username: {username}.", ip.ip).
This makes the two code paths inconsistent for the same underlying
error, and means log-based tooling that keys on the identity.rs
error's "IP: x.x.x.x" pattern can't do the same for this endpoint.
Bring email.rs's three call sites in line with identity.rs's existing
format. The two email-present branches log IP+Username (the email
submitted); the device-identifier-only branch (SSO path, no email in
scope) logs IP+Device instead of fabricating a username.
Verified: cargo build/test/clippy/fmt all pass with the sqlite feature
(matching one leg of this repo's own CI matrix), including the two
existing unit tests in this file.
Bring the documentation this feature ships with in line with the Google
developer documentation style guide, and clear the one lint the toolchain
bump surfaced. No behavior changes.
Documentation:
* Add a module header to sso_cookie_vendor.rs explaining the flow, why
it exists, and that the route is registered only when the feature is
on. Rewrite the item docs in descriptive third person and give each
fallible function an `# Errors` section naming every status code and
the condition behind it. Replace the comments that restated the code
with ones that explain why the cookie map is built, why the length
cap is applied to the finished link, and why shard order is
deterministic.
* Comment the two additions in api/core/mod.rs, restoring the upstream
bitwarden/server#6892 reference that was dropped along with the
`"communication": null` placeholder.
* Rewrite the admin-panel help text and .env.template entries so they
say when an operator needs the setting, not just what it is.
* Rewrite docs/sso-cookie-vendor.md: sentence-case headings, a settings
table, numbered procedures, explained placeholders. It now states
that Cloudflare Access is the only proxy verified in production
rather than implying the others are tested.
Fixes:
* `cookie.value().to_string()` twice becomes `to_owned()`, which
clippy::str_to_string began rejecting after the toolchain moved to
1.98.
* Rename test_uri_too_long_returns_400 to
test_oversize_cookie_exceeds_uri_limit. It asserts that the built URI
exceeds the cap; the 400 comes from the handler, which the test never
calls.
* The validation error now names `SSO_COOKIE_VENDOR_ENABLED` instead of
describing it in prose, so the reader knows which flag to unset.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YXT28rZFFFahdfKXJScPHy
Account recovery requires SMTP. When mail is off, treat the organization
reset-password auto-enroll policy as inactive so invite/accept flows are
not forced to supply a reset-password key.
Fixes#7459
`src/api/core/ciphers.rs:170` comment said "similar to the the
userDecryptionOptions" -> "similar to the userDecryptionOptions".
Comment-only.
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Upstream added a "communication": null placeholder for bitwarden/server#6892
after this branch last merged main. Combined with this PR's populated
"communication" key, serde_json's json! macro keeps the last duplicate key,
so the null silently overwrote the ssoCookieVendor bootstrap block and native
clients never saw it. Keep only the populated key.
* Include user email in successful login logs
* Modified disable account log to display Email instead of Display Name
---------
Co-authored-by: Alejandro Olmos <aolmos@trevenque.es>
* Update GHA and pre-commit
Signed-off-by: BlackDex <black.dex@gmail.com>
* Update admin diagnostics
Added a check if the templates are overridden and return which specific folder, `admin`, `email` or `scss`.
This way we could more quickly point users to possible outdated templates which they are using.
Also updated the Support String to use some emojis so we should be able to quicker see if there is something wrong.
Just checking `true` or `false` could be difficult sometimes, and sometimes what we had as `false` wasn't bad either.
Also adjusted the eslint comments so it will work with the latest version of eslint.
Signed-off-by: BlackDex <black.dex@gmail.com>
* Fix updating collections for a cipher
The newer clients expect a `cipherDetails` response on the `collections-admin` endpoints.
Without it, the client will cause an error and stops handling the update correctly.
This will fix this by returning the cipher json.
Fixes#7545Fixes#7546
Signed-off-by: BlackDex <black.dex@gmail.com>
* Cache CSS file in a different way
Currently we set a cache ttl of 24 hours, and users need to do a force refresh if there is anything changed to the CSS file.
In the past we have had several issue reported which were related to a still cached CSS file.
This commit will change the caching and also cache the generated CSS file in memory.
Instead of letting the browser cache it for 24 hours we generate an ETag, this is just a hash of the contents.
This ETag is returned by the browser during a request, and we can match this, and if so, just return a `304` `Not Modified`.
If the ETag is not known, we return the new content.
This should make simple refreshes by clients get updated settings or a new version of Vaultwarden which has other CSS entries get updated instantly.
If a user does a hard refresh, we will not receive the ETag and the content will be served.
The same goes if someone has the `reload_templates` feature enabled, since then we should not cache anyway.
If someone adjust settings via the `/admin` interface, the cache will be invalidated and a new CSS will be generated.
Signed-off-by: BlackDex <black.dex@gmail.com>
* Fix showing events for a specific user
Signed-off-by: BlackDex <black.dex@gmail.com>
* Update crates and adjust code.
- Updated opendal and adjusted code where needed.
- Updated yubico_ng and adjusted code where needed.
This version now supports using an own HttpClient and it pulls in no reqwest dependency anymore.
Now it will use our own client which uses custom hickory DNS and other features.
Signed-off-by: BlackDex <black.dex@gmail.com>
* Update web-vault to v2026.7.0
Signed-off-by: BlackDex <black.dex@gmail.com>
* Fix hadolint warnings
Signed-off-by: BlackDex <black.dex@gmail.com>
---------
Signed-off-by: BlackDex <black.dex@gmail.com>
The bundled web vault (2026.6.4) requires seven query parameters in the
accept-organization URL and rejects the invite client-side when any of them is
null, showing only "Unable to accept invitation" without sending a request to
the server.
send_invite() never appended initOrganization, and appended
orgUserHasExistingUser only for users who already had an account, so every
organization invitation e-mail produced a link that could not be accepted.
Web vault 2026.4.1 (shipped with 1.36.0) read these parameters null-safely,
which is why this only appeared in 1.37.0.
Fixes#7481
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
- Updated API response to more closely match v2026.6.0+ server versions.
- Updated all the crates
- Updated Rust to v1.97.1
- Updated the web-vault to v2026.6.4
- Updated GitHub Actions
Signed-off-by: BlackDex <black.dex@gmail.com>