# Security Policy Security is a priority for the NautilusTrader project, and we value the work of those who help identify and resolve vulnerabilities. We apply layered controls across the development and release lifecycle, with signed and attested releases, continuous vulnerability management, and transparent development practices. If you have found a security issue, please follow the guidelines below. For our full security policies, see . ## Scope This policy covers: - NautilusTrader open-source software and official repositories. - Nautech Systems websites (nautilustrader.io). Third-party services, exchanges, and data providers are excluded. ## Reporting a Vulnerability **Preferred method:** [GitHub Security Advisories](https://github.com/nautechsystems/nautilus_trader/security/advisories/new) This allows private disclosure and coordination before public release. You'll receive credit in the security advisory and release notes. **Alternative:** Email For sensitive reports via email, you may request our PGP key for encrypted communication. Please include: vulnerability description, reproduction steps, affected versions, and suggested remediation if available. ## Response Timeline We commit to: - **Initial response**: Within 48 hours of report submission. - **Status update**: Within 7 days with initial assessment. - **Fix timeline**: Critical vulnerabilities patched within 30 days; other issues within 90 days. - **Coordinated disclosure**: We'll work with you to agree on a public disclosure date. ## Responsible Disclosure We encourage responsible disclosure of any security vulnerabilities you may discover. When reporting, we ask that you: - Do not publicly disclose the vulnerability before a fix is available. - Only exploit the issue to the extent necessary to demonstrate it. - Do not access unauthorized data or disrupt systems. - Comply with all applicable laws. We will acknowledge your contribution in our security advisories and release notes unless you prefer to remain anonymous. ## Supported Versions We only support the latest version of NautilusTrader. If you are using an older version, it is possible that vulnerabilities may have been fixed in a later release. ## Bug Bounty Program At this time, we do not have a formal bug bounty program. We appreciate any efforts to help us improve the security of our platform and will do our best to properly recognize and credit your contributions. ## Security Infrastructure The sections below detail the controls at each layer of that lifecycle. ### Public posture - **OpenSSF Scorecard**: The repository publishes Scorecard results for the public badge and API, and uploads SARIF to GitHub code scanning. Scorecard is an automated repository-health signal that complements manual review and security audits. ### Source and review controls - **CODEOWNERS**: Critical infrastructure files, dependency manifests, and lock files require Core team review before merge. - **Branch and tag rulesets**: Protected branches require signed commits and passing CI checks. Release tags matching `v*` are immutable after creation. - **Source restrictions**: Rust packages are sourced exclusively from crates.io. Git dependencies and unknown registries are prohibited. ### Dependency intake controls - **Version pinning and lock files**: Rust dependencies are pinned in `Cargo.lock` with cryptographic checksums. Python dependencies are pinned in `python/uv.lock` with integrity hashes. Wildcard version requirements are prohibited. - **Dependency cooldowns**: Python dependency resolution excludes packages published within the last 7 days through `exclude-newer` in `python/pyproject.toml`. Rust crate updates remain subject to a 3‑day cooldown and cargo-vet review. A security fix or critical bug fix may bypass either cooldown after explicit review. These windows give the community time to detect and quarantine compromised releases. Development tools are pinned to explicit versions across `tools.toml`, `Cargo.toml`, and related manifests, and version bumps are reviewed during security audits. - **Wheel-only Python installs**: The `no-build-package` list in `[tool.uv]` enumerates every third-party package locked in `python/uv.lock` and forbids `uv` from building any of them from source. In normal operation uv prefers wheels, so the setting is a no-op; it kicks in only if a listed upstream stops publishing wheels for the target platform, in which case `uv lock` fails instead of silently building from an sdist. The local workspace package is intentionally absent because it must be built by the workspace's own build backend. The `check-no-build-packages` pre-commit hook verifies the list stays in lock-step with `python/uv.lock` on every commit that touches the lock or the manifest. - **Toolchain pinning**: `python/pyproject.toml` limits local uv use to the supported minor series. `tools.toml` pins the exact uv version used by CI, Docker, pre‑commit, and project install commands. Release and audit tool Python CLIs are also pinned in `tools.toml`. - **License compliance**: Automated checks verify Rust dependencies against an allow list of licenses compatible with NautilusTrader's `LGPL-3.0-only` license. ### Pre-merge and scheduled scanning - **Pre-commit security**: Gitleaks credential screening, private key detection, Zizmor GitHub Actions auditing, and Unicode control character detection run before changes land. - **Dependency auditing**: Automated security scanning runs via cargo-audit, cargo-deny, cargo-vet, and OSV Scanner (Rust), pip-audit (Python), and Zizmor (GitHub Actions). - **Supply chain provenance**: cargo-vet verifies Rust dependency provenance by importing trusted audit data from organizations including Bytecode Alliance, Google, Mozilla, and Embark Studios. - **Fuzzing**: cargo-fuzz targets cover selected adapter and signing surfaces, including Derive wire-model/signing internals and Lighter cryptographic/signing internals. - **Code scanning**: CodeQL static analysis covers Python and Rust code on PRs to `master`, pushes to `nightly`, and manual dispatch. The scheduled security audit also uploads Zizmor SARIF results for GitHub Actions workflow findings when token permissions allow it. ### Build and publish controls - **Build integrity**: SLSA build provenance attestations for Python release artifacts, GitHub release checksum manifests, immutable GitHub release attestations, immutable GitHub Actions pinned to commit SHAs, container digest pinning, Docker image signing via Sigstore cosign, SPDX SBOM generation and Sigstore attestation for container images, and hardened CI runners with network egress blocked to an explicit allow-list. - **Release sequencing**: Stable releases create a draft GitHub release and attach wheel and sdist assets before publishing to package indexes (`packages.nautechsystems.io`, PyPI, crates.io). CI verifies the registries, attaches final checksum and provenance assets, then publishes the GitHub release and verifies its release attestation. This keeps the GitHub release and checksum manifest as the anchor for downstream registry verification while staying compatible with GitHub release immutability. - **Deployment environments**: Release and package publishing jobs use scoped GitHub deployment environments (`release`, `r2-develop`, and `r2-nightly`) so publishing credentials and OIDC trusted-publisher identities stay isolated from test, lint, and build-only jobs. - **Publish authentication**: PyPI and crates.io uploads use Trusted Publishing (OIDC) bound to the `release` GitHub Environment, eliminating long-lived API tokens. Each publish mints a short-lived token scoped to the specific repo, workflow, and environment. - **GHCR authentication**: Container image pushes to GitHub Container Registry use the short-lived `GITHUB_TOKEN` scoped to the workflow run, not a long-lived personal access token. - **Post-publish verification**: CI verifies PyPI wheels and sdists against the GitHub release manifest and expected PyPI publisher identity, verifies crates.io entries were trusted-published by this repository, records whether each crate matches the release commit or was already published, verifies the final GitHub release attestation, and verifies container image signatures and SBOM attestations against the expected GitHub Actions workflow identities after publishing. ### Runtime cryptography - **Cryptography**: TLS and most runtime cryptography use [aws-lc-rs](https://github.com/aws/aws-lc-rs), the Rust binding for AWS-LC. Ed25519 signing uses [ed25519-dalek](https://github.com/dalek-cryptography/curve25519-dalek). AWS-LC runs in non-FIPS mode because the FIPS 140-3 module (`aws-lc-fips-sys`) requires the Go toolchain as a build dependency. The AWS-LC primitives used here (AES-GCM, SHA-2, ECDSA, ChaCha20-Poly1305) are identical in both modes; the FIPS module adds runtime self-tests and module boundary enforcement required for federal certification. For our full supply chain security policy, see . For the end-to-end release supply chain model, see [Security Architecture](docs/developer_guide/security.md). For detailed CI/CD security practices, see [.github/OVERVIEW.md](.github/OVERVIEW.md#security). ## Known vulnerability management Where a known advisory exists in a transitive dependency without an available fix, we document the risk assessment, context, and mitigation in our audit configuration. Accepted risks are categorized by severity, scope (direct vs. transitive, runtime vs. dev-time), and monitored for upstream resolution. When a new vulnerability is identified in a dependency: - The nightly security audit flags the advisory automatically. - The Core team assesses severity and exposure within the NautilusTrader context. - Critical vulnerabilities in direct dependencies are patched or mitigated within 30 days. - Users are notified through release notes and, where appropriate, security advisories. Users who build NautilusTrader from source or extend it with additional dependencies are responsible for auditing their own dependency trees. The controls described in this policy apply to official NautilusTrader releases and the canonical repository. ## Advisories addressed Third‑party security advisories we have addressed via dependency upgrades. Security scanning is not delayed by the dependency cooldowns described above. When an advisory requires a newer package, a reviewed fix can bypass the applicable cooldown. - **1.227.0**: - [GHSA-mf9v-mfxr-j63j](https://github.com/urllib3/urllib3/security/advisories/GHSA-mf9v-mfxr-j63j): `urllib3` decompression-bomb safeguard bypass via `HTTPResponse.drain_conn()` after partial decompression, and via the second `read(amt=N)`/`stream(amt=N)` call when Brotli-decompressed. Upgraded `urllib3` to v2.7.0. - [GHSA-qccp-gfcp-xxvc](https://github.com/urllib3/urllib3/security/advisories/GHSA-qccp-gfcp-xxvc): `urllib3` pools created via `ProxyManager.connection_from_url` not stripping headers listed in `Retry.remove_headers_on_redirect` when redirecting cross-host. Upgraded `urllib3` to v2.7.0. ## Verifying releases Python release artifacts and Docker images are signed or attested via Sigstore-backed workflows. Cargo crates are published through crates.io Trusted Publishing. The release verifier records whether each crate version was published by the current release commit or already existed from an earlier trusted-published commit in this repository. Emergency token-publish recovery requires an explicit `CRATES_IO_MANUAL_PUBLISH_EXCEPTIONS` `crate@version` entry, and the recovered crate version is recorded in `crates-manifest.json` with `release_status: "manual_token_publish"`. You can independently verify artifacts before installing them. ### Python wheels and sdist GitHub releases include a generated checksum table, an aggregate `SHA256SUMS` file, per-asset `.sha256` files, and a machine-readable `dist-manifest.json` for Python wheels and the sdist. Check the downloaded artifact against one of those checksum sources before installation. GitHub releases also include `.sigstore` Sigstore bundles and `.intoto.jsonl` DSSE envelope siblings for each Python artifact. The GitHub CLI fetches attestations from the GitHub API by default; use `--bundle .sigstore` to verify against a downloaded Sigstore bundle instead. After downloading from PyPI or the GitHub release, verify each artifact with the GitHub CLI. The `--cert-identity-regex` and `--cert-oidc-issuer` flags bind verification to the `build.yml` release workflow, not just the repository: ```bash ISSUER=https://token.actions.githubusercontent.com IDENTITY='^https://github\.com/nautechsystems/nautilus_trader/\.github/workflows/build\.yml@refs/heads/(master|nightly)$' # `gh attestation verify` takes one subject per call, so loop over wheels for whl in nautilus_trader-*.whl; do gh attestation verify "$whl" \ --repo nautechsystems/nautilus_trader \ --cert-identity-regex "$IDENTITY" \ --cert-oidc-issuer "$ISSUER" done gh attestation verify nautilus_trader-*.tar.gz \ --repo nautechsystems/nautilus_trader \ --cert-identity-regex "$IDENTITY" \ --cert-oidc-issuer "$ISSUER" ``` ### Docker images Resolve the mutable tag to an immutable digest first so every check, the subsequent `docker pull`, and the `docker run` operate on the same image: ```bash # Use crane (or `docker buildx imagetools inspect --format '{{.Manifest.Digest}}'`) DIGEST=$(crane digest ghcr.io/nautechsystems/nautilus_trader:latest) IMAGE=ghcr.io/nautechsystems/nautilus_trader@${DIGEST} ISSUER=https://token.actions.githubusercontent.com IDENTITY='^https://github\.com/nautechsystems/nautilus_trader/\.github/workflows/docker\.yml@refs/heads/(master|nightly)$' ``` Verify the cosign signature, which proves the image was produced by the NautilusTrader CI workflow: ```bash cosign verify "$IMAGE" \ --certificate-identity-regexp "$IDENTITY" \ --certificate-oidc-issuer "$ISSUER" ``` Verify the SPDX SBOM attestation is bound to the same image digest: ```bash cosign verify-attestation --type https://spdx.dev/Document/v2.3 "$IMAGE" \ --certificate-identity-regexp "$IDENTITY" \ --certificate-oidc-issuer "$ISSUER" ``` The GitHub CLI can also verify the SBOM attestation, but does not check the cosign image signature, so use it in addition to `cosign verify` above: ```bash gh attestation verify "oci://${IMAGE}" \ --repo nautechsystems/nautilus_trader \ --predicate-type https://spdx.dev/Document/v2.3 \ --cert-identity-regex "$IDENTITY" \ --cert-oidc-issuer "$ISSUER" ```