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.
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>
* 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>
* Misc updates and fixes
- Updated Rust to v1.96.1
- Updated all the crates
- Updated GitHub Actions
- Updated the web-vault to v2026.6.2
- Updated Alpine to v3.24
- Fixed several clippy lints
- The `send` UUID wrappers didn't need the special namespace anymore since an updated crate, so removed this extra mod.
Signed-off-by: BlackDex <black.dex@gmail.com>
* Update MSRV to v1.94.1
Signed-off-by: BlackDex <black.dex@gmail.com>
---------
Signed-off-by: BlackDex <black.dex@gmail.com>
* ci: remove dead BASE_TAGS reference in release bake step
steps.determine-version doesn't exist in docker-build; the expression
resolves to empty string. The HCL default (testing) would have
applied, but it's moot - the bake uses push-by-digest=true so tags are
only set in merge-manifests. Dead code.
* ci: replace unsecured curl hadolint download with an official action
hadolint/hadolint-action uses a Docker-based runner with hadolint
pre-bundled in ghcr.io/hadolint/hadolint:v2.14.0-debian,so no binary
downloaded at runtime. Pinning the action to a commit SHA covers the
Dockerfile that specifies the image version, closing the supply-chain
gap from the previous unverified curl | sudo install.
Split {debian,alpine}: the action takes a single dockerfile argument,
so debian and alpine are linted separately.
* ci: pin ubuntu-latest to ubuntu-24.04 in merge-manifests and zizmor
ubuntu-latest is a moving target that can silently change the runner OS
on the next GitHub-side update. All other jobs in this repo already pin
to ubuntu-24.04; this makes merge-manifests and zizmor consistent.
* ci: return BASE_TAGS - it's needed for bake step