This document defines the security boundary for Apache OpenDAL Reqsign. The documentation is for maintainers, security reporters, downstream users, Apache OpenDAL integrators, direct reqsign users, and automated security scanners that need to decide whether a report describes a Reqsign vulnerability or a responsibility of the embedding application, a cloud provider, or a deployment.
The canonical disclosure process is documented in SECURITY.md. Reports that may affect reqsign security should be sent privately to private@opendal.apache.org before public disclosure. If you are unsure where to send the report, use security@apache.org.
Reqsign is an in-process Rust library for signing HTTP API requests. Reqsign provides runtime-agnostic core traits, pluggable context adapters, credential-provider chains, and service-specific signing implementations for cloud providers.
Reqsign is not an identity provider, authorization service, key-management system, TLS stack, network sandbox, process sandbox, or multi-tenant broker. Reqsign does not decide whether a caller is allowed to access a resource but signs the HTTP request that a trusted caller gives it, using credentials that the trusted caller configured or allowed reqsign to discover.
The purpose of this document is to help maintainers triage security reports by answering four questions:
The most important premises are:
Reqsign trusts its caller to construct the request, choose the endpoint, choose service and region values, and configure credential-provider sources.
Reqsign must still preserve its own library boundary: sign according to the selected service contract, isolate cached credentials, avoid credential leaks, respect explicit provider-chain configuration, and handle inputs without memory-safety violations.
OpenDAL is Reqsign‘s primary integration and can use Reqsign to sign requests for custom keys and cloud-provider authentication. Other applications can also embed Reqsign directly. In every embedding, the host application remains responsible for its own user authentication, authorization, request construction, endpoint selection, and user-facing API behavior. OpenDAL-specific storage semantics, operator authorization, path policy, and backend trust decisions are covered by OpenDAL’s own security model. Reqsign is responsible for the request-signing and credential-loading behavior described here.
A Reqsign deployment has these participants.
| Participant | Boundary summary |
|---|---|
| Host application | Trusted caller outside Reqsign's security boundary. |
| Reqsign | In-process signing library and the subject of this model. |
| Credential source | External source selected by the caller or documented Reqsign behavior. |
| Cloud provider or API service | External verifier and authorizer. |
| End user of the host application | Outside Reqsign's direct model. |
| Network attacker | Outside by default, except for Reqsign-owned leaks or transport weakening. |
Reqsign does not define a principal model. A configured Reqsign signing setup signs with the authority of its configured credentials. Every request signed by that setup uses the same Reqsign-level authority until the caller changes the credential or signing configuration.
A typical interaction looks like this:
Credential source <----> Reqsign <----> Host application <----> End user | v Signed HTTP request | v Cloud provider or API service
Host application policy, including OpenDAL storage semantics when Reqsign is used through OpenDAL, cloud provider enforcement, and deployment controls are separate boundaries.
Reqsign protects:
Reqsign's security boundary is the public library boundary plus the internal state that Reqsign owns behind that boundary.
The following properties are in scope for Reqsign security.
Reqsign must handle inputs accepted by public APIs without memory-safety violations, data races, panics across FFI-like boundaries, or inconsistent internal state.
Examples:
Signer::sign must not use a poisoned, stale, or unrelated credential in a way that violates its documented cache behavior.SigningRequest::build and SigningRequest::apply must preserve request method, scheme, authority, path, query, and headers according to their API contract.MaybeSend support must not introduce unsoundness in supported non-WASM and wasm32-unknown-unknown builds.Reqsign does not decide whether the host application's end user is allowed to sign a request. That policy belongs to the host application. Once the trusted caller passes a request into Reqsign, Reqsign must not sign a different request than the request implied by the selected signing implementation.
Reqsign must not leak credentials between independent signers, credential providers, services, or contexts inside the same process.
Expected behavior:
Signer B must not use credentials loaded by independent Signer A unless the caller explicitly shares a provider, context, or signer.with_credential_provider must clear the cached credential for that signer.build().slot(provider) methods, removal no_slot() methods, and no fallback-based re-enabling of removed slots.SigningCredential.Sharing a Signer, provider, or Context across tenants, threads, async tasks, or processes is a caller decision. It is in scope only if Reqsign violates its own documented isolation or cache behavior.
Reqsign must avoid exposing credentials through Debug output, error chains, log lines, tracing spans, metrics labels, panic messages, and test helpers that are part of shipped library behavior.
Secrets include, at minimum:
Expected behavior:
Debug implementations redact secret fields.Request paths, endpoint hostnames, regions, account names, and provider names can be sensitive in some deployments. Reqsign does not treat them as credentials by default; callers that need stronger privacy must choose their logging and tracing sinks accordingly.
Reqsign's credential providers must use only the credential sources documented or explicitly configured for that provider chain.
Examples:
Context::new() has no-op file, HTTP, environment, and command adapters. It must not silently read the process environment, local files, metadata endpoints, or external commands.default_context() may use OS environment variables, file reads, HTTP requests, and command execution through its default adapters. Those accesses must match the documented default providers for the selected service.no_env(), no_profile(), no_imds(), no_process(), no_web_identity(), no_oidc(), no_vm_metadata(), and similar removal methods must prevent the corresponding ambient source from participating.If a trusted caller configures a malicious file path, command, environment implementation, metadata endpoint, HTTP client, or custom provider, using that source is caller responsibility. If Reqsign ignores explicit source removal, mixes sources from another signer, or silently adds a credential source, that is in scope.
Reqsign must construct and apply signatures according to the selected service's signing contract.
Examples:
Provider-side acceptance or rejection is not by itself the security boundary. A compatibility bug that causes a legitimate request to fail may be a normal bug. It becomes security-relevant when it grants unintended authority, signs a meaningfully different request, exposes secret material, bypasses explicit caller configuration, or violates an in-scope provider contract.
Reqsign is designed to support custom request-signing implementations. OpenDAL is a primary consumer of this capability for custom key signing, and other host applications may provide their own custom signers too. Custom signers and credential providers are trusted code from Reqsign‘s perspective, but Reqsign’s core abstractions must not make custom key signing unsound.
In scope:
Signer must pass the credential selected by its provider to the configured request signer without cross-service or cross-signer substitution;Context, credential provider, or request signer.Out of scope by default:
ProvideCredential, SignRequest, FileRead, HttpSend, Env, or CommandExecute implementation intentionally leaks or misuses secrets;Reqsign can read local credential files and execute local credential-helper commands when the caller configures adapters and providers that require those features.
In scope:
Out of scope by default:
Reqsign providers may use HTTP to retrieve metadata credentials, exchange tokens, refresh OAuth credentials, or call service-specific identity endpoints.
In scope:
Out of scope by default:
reqsign-core and the supported subset of services are expected to compile for wasm32-unknown-unknown.
In scope:
Out of scope by default:
The following are not Reqsign vulnerabilities by default.
Reqsign does not authenticate end users, authorize operations, or decide whether end-user input is allowed to become a request URL, header, query parameter, service name, region, credential-source path, command, or endpoint.
Examples:
These may be serious vulnerabilities in the host application, but they are not Reqsign vulnerabilities unless Reqsign violates one of the boundaries in section 4.
The trusted caller is responsible for choosing endpoints, HTTP clients, context adapters, credential providers, request signers, service names, regions, and accounts.
Examples:
HttpSend implementation that logs request bodies and headers.Env implementation that returns attacker credentials.SignRequest implementation that signs the wrong bytes.Cloud-provider policy and identity behavior belong to the provider and the operator of that account.
Examples:
Reqsign can fail safely when provider responses are malformed, but it does not prove provider-side authorization correctness.
Reqsign signs requests according to provider rules. It does not provide end-to-end authentication of response bytes, object contents, metadata, timestamps, ETags, or backend state.
Applications that need end-to-end integrity must add it above Reqsign and above their storage/API client.
Reqsign is not a default DoS shield.
Examples:
Resource-exhaustion reports are Reqsign vulnerabilities only when they show Reqsign violates a documented bound, ignores configured timeout or cancellation behavior that Reqsign owns, or consumes resources independently of the operation requested by the trusted caller.
TLS certificate validation, CA bundles, proxies, redirect policy, DNS, socket options, and network egress controls are properties of the configured HTTP client and host environment. A report is in scope only if Reqsign silently weakens transport contrary to its documented meaning or sends Reqsign-owned secret material to an endpoint outside the provider contract.
Dependency freshness, GitHub Actions hardening, release signing, branch protection, and ASF infrastructure policy are important, but they are outside this library threat boundary unless a separate project policy says otherwise.
| Disposition | Use when |
|---|---|
VALID | The report shows a violation of an in-scope boundary in section 4, reachable through documented Reqsign APIs or shipped Reqsign library behavior. |
VALID-HARDENING | There is no clear security-boundary violation, but Reqsign's API, defaults, logging, or documentation make dangerous misuse common enough that maintainers choose to harden behavior or docs. |
OUT-OF-SCOPE: caller-authz | The report depends on the host application forwarding unauthorized end-user input into Reqsign. |
OUT-OF-SCOPE: caller-config | The report depends on a trusted caller choosing a malicious endpoint, provider, context adapter, credential file, command, HTTP client, service name, region, or custom signer. |
OUT-OF-SCOPE: provider-authz | The report is about cloud-provider policy, role trust, OAuth scope, bucket policy, or provider-side signature verification rather than Reqsign behavior. |
OUT-OF-SCOPE: transport | The report is about TLS, proxy, DNS, redirect, timeout, or socket behavior owned by the configured HTTP client or host environment. |
OUT-OF-SCOPE: infrastructure | The report is about release, CI, dependency, or ASF infrastructure policy rather than the Reqsign library boundary. |
BY-DESIGN: property-not-provided | The report asks Reqsign to provide a property explicitly not provided here, such as host-application authorization, endpoint trust, response integrity, or default DoS protection. |
MODEL-GAP | The report cannot be classified by this document. Treat this as evidence that the model needs revision. |
VALID)Signer B signs a request with credentials cached by unrelated Signer A.Debug implementation prints a secret access key, account key, private key, session token, or OAuth token.no_imds() is configured, but the built provider still contacts IMDS.Context::new() reads environment variables, local files, HTTP endpoints, or external commands without the caller installing adapters.OUT-OF-SCOPE: caller-config: a caller signs an attacker-supplied URL with production credentials.OUT-OF-SCOPE: caller-config: a caller configures an attacker-controlled S3-compatible endpoint and that endpoint receives signed requests.OUT-OF-SCOPE: caller-authz: a host application, including OpenDAL, authorizes the wrong tenant before calling Reqsign.OUT-OF-SCOPE: provider-authz: a bucket policy, IAM role, service account, storage account, or OAuth scope is overprivileged.OUT-OF-SCOPE: caller-config: a caller-provided custom signer intentionally logs the canonical request and secret key.OUT-OF-SCOPE: provider-authz: a cloud provider accepts a bad signature due to a provider-side verifier bug.OUT-OF-SCOPE: caller-config: a credential-helper command configured by the caller is malicious.BY-DESIGN: property-not-provided: a credential file is huge and the caller did not provide resource limits.VALID-HARDENING)The following decisions are part of this model.
| Topic | Decision |
|---|---|
| Host application trust | Reqsign treats OpenDAL and other embedding applications as trusted callers that authorize users, choose endpoints, construct requests, and decide which inputs may be signed. |
| Custom key signing | Caller-provided custom signers and providers are trusted code, but Reqsign must preserve type relationships, request integrity, credential isolation, and explicit customization. |
| No-op context default | Context::new() and Context::default() must remain no-op for file reads, HTTP sends, environment reads, and command execution. Ambient access belongs to explicit adapters such as default_context(). |
| Default credential providers | Future API changes around DefaultCredentialProvider must follow docs/default-credential-provider-api.md; reintroducing configure_*, disable_*(bool), or build-time fallback re-enabling of removed slots is a design regression unless explicitly approved. |
| Credential redaction | Credentials and reusable signing material are secrets and must be redacted. Paths, endpoints, regions, account names, and provider names are operational context by default. |
| Presigned URLs | Presigned URLs and signed query strings can grant access and should be treated as secret-bearing material when emitted by Reqsign-owned logs, errors, or debug output. |
| Transport | Reqsign delegates TLS, proxy, DNS, redirect, and socket policy to the configured HTTP client and host environment. |
| OpenDAL integration boundary | OpenDAL-level storage semantics, operator authorization, path policy, and backend trust decisions are covered by OpenDAL's own security model, not this Reqsign model. Other host applications own equivalent application-level policy in their own security models. |
| Version binding | A report should be triaged against the threat model version present in the affected release tag or maintenance branch. |
| Capability drift | When credential loading, request signing, context capabilities, WASM support, or custom signing APIs change, this file should be updated in the same pull request or a linked follow-up. |
We will revisit this threat model when any of the following changes:
MODEL-GAP.Reqsign is a sub-project related to Apache OpenDAL, and OpenDAL is the primary integration this model expects maintainers to consider. Reqsign is still a reusable library: direct reqsign users and other embedding applications get the same Reqsign security properties and retain the same host-application responsibilities.
Reqsign owns:
OpenDAL and other host applications own:
For OpenDAL, this threat model is additive. It does not replace OpenDAL‘s threat model or the Apache Software Foundation disclosure process. For other embedding applications, this model defines only Reqsign’s library boundary; the embedding application must define its own authorization, input-validation, endpoint-trust, and deployment boundaries.