bitwarden/server · error · NotFoundException

Resource not found.

Error message

Resource not found.

What it means

Thrown at SecretsManagerPortingController.cs:45 inside Export (GET sm/{org}/export). The caller is not an OrganizationAdmin for that org OR lacks Secrets Manager access (_currentContext.AccessSecretsManager false). Either condition throws NotFoundException -> HTTP 404. Export is restricted to organization admins with SM access.

Source

Thrown at src/Api/SecretsManager/Controllers/SecretsManagerPortingController.cs:45

    public SecretsManagerPortingController(ISecretRepository secretRepository, IProjectRepository projectRepository,
        IUserService userService, IMaxProjectsQuery maxProjectsQuery, IImportCommand importCommand,
        ICurrentContext currentContext)
    {
        _secretRepository = secretRepository;
        _projectRepository = projectRepository;
        _userService = userService;
        _maxProjectsQuery = maxProjectsQuery;
        _importCommand = importCommand;
        _currentContext = currentContext;
    }

    [HttpGet("sm/{organizationId}/export")]
    public async Task<SMExportResponseModel> Export([FromRoute] Guid organizationId)
    {
        if (!await _currentContext.OrganizationAdmin(organizationId) || !_currentContext.AccessSecretsManager(organizationId))
        {
            throw new NotFoundException();
        }

        var userId = _userService.GetProperUserId(User).Value;
        var projects = await _projectRepository.GetManyByOrganizationIdAsync(organizationId, userId, AccessClientType.NoAccessCheck);
        var secrets = await _secretRepository.GetManyDetailsByOrganizationIdAsync(organizationId, userId, AccessClientType.NoAccessCheck);

        if (projects == null && secrets == null)
        {
            throw new NotFoundException();
        }

        return new SMExportResponseModel(projects.Select(p => p.Project), secrets.Select(s => s.Secret));
    }

    [HttpPost("sm/{organizationId}/import")]
    public async Task Import([FromRoute] Guid organizationId, [FromBody] SMImportRequestModel importRequest)
    {
        if (!await _currentContext.OrganizationAdmin(organizationId) || !_currentContext.AccessSecretsManager(organizationId))

View on GitHub (pinned to e93b962371)

Solutions

  1. Run the export as an organization admin who also has Secrets Manager access.
  2. Use an admin-level API token for automated exports.
  3. Confirm the organization has Secrets Manager enabled for the admin.

Example fix

// before: non-admin token attempts export
await memberClient.GetAsync($"/sm/{orgId}/export"); // 404

// after: use an admin credential
var adminClient = ClientFor(orgAdminCredential);
await adminClient.GetAsync($"/sm/{orgId}/export");
Defensive patterns

Strategy: validation

Validate before calling

if (!await IsOrganizationAdminAsync(orgId) || !await HasSecretsManagerAccessAsync(orgId))
    throw new UnauthorizedAccessException("Export requires org admin with SM access");
await adminClient.GetAsync($"/sm/{orgId}/export");

Try / catch

try { await client.GetAsync($"/sm/{orgId}/export"); }
catch (ApiException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { Log.Warn("Export denied; use an admin with SM access"); }

Prevention

When it happens

Trigger: GET /sm/{orgId}/export by a non-admin SM user, a standard org member, or an admin without the Secrets Manager add-on/access.

Common situations: A custom-role or standard user attempts an export; admin whose SM access was revoked; scripted export run with a non-admin token.

Related errors


AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13). Data as JSON: /api/errors/8a93600614bb2aea. Report an issue: GitHub.