---
title: "Security"
description: "Access control, supply chain, the unsafe surface, and hardening notes."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.myswift.rs/llms.txt
> Use this file to discover all available pages before exploring further.

# Security

> **Evidence boundary**
>
> The checks below are historical or source-level unless they name a current
> candidate run. They do not close G4-G8 or establish production readiness.
> Current state: G6 GREEN, G7 NOT ACCEPTED, overall production readiness NO-GO.

## Historical access-control checks

The table records a bounded earlier lab run and must be rerun on the accepted
candidate and configured pipeline:

| Check | Result |
|-------|--------|
| Cross-account read/write | `403` denied |
| Container ACL: public-read / restrict / revoke | correct, matches Python |
| No-token / bad-token | `401` |
| Unsupported method (TRACE) | `405` |
| Path-traversal object name | stored as a literal, no filesystem escape |
| ETag integrity on PUT | `422` on md5 mismatch (after the fix below) |
| Metadata length | `400` over the 256-char limit (after the fix below) |

## Supply chain and `unsafe`

- Run `cargo audit` against the exact current lockfiles and archive the output;
  an older zero-vulnerability count expires as advisories and dependencies move.
- **`unsafe`** — a small, reviewed surface: FFI (the erasure-coding codec) and
  syscall wrappers (`getifaddrs`, `flock`, xattr). No transmutes or ambient
  global-state hacks.

## Control-plane auth

The [swift-deploy-rs](/swift-deploy-rs) control API is token-guarded — plan,
validate, and apply all require the token; only `/healthz` is public. The
[swift-console](/swift-console) holds a per-session token and is meant to listen
on loopback behind the cluster load balancer.

## Validation fixes shipped

Three input-validation/format deviations from Python were found and fixed:

1. **Step 1**

   **ETag integrity.** The proxy dropped the client `ETag` before fan-out, so the
   object server's md5 check never fired and a corrupt upload returned `201`. The
   proxy now forwards it; a mismatch is `422`.
2. **Step 2**

   **ETag format.** The object server correctly returns a quoted ETag (matching
   Python's diskfile and the golden oracle); the proxy now strips the quotes for
   the client (`normalize_etag`), so the client sees the bare md5.
3. **Step 3**

   **Metadata length.** Object writes now run `check_metadata`; an oversized
   `X-Object-Meta-*` value is rejected with `400` instead of stored.

## Hardening notes

> **Caution**
>
> - `swift.conf` contains the hash prefix/suffix; restrict it to the service
> account/group (for example `0640`) and verify ownership.
> - TempURL / formpost / crypto / s3api middleware are **not** in the default
> proxy pipeline; enable them deliberately if a deployment needs those features.

## Runtime and control-plane hardening

- bind `swift-console`, `swift-deploy ui`, and `cosbench-rs serve` to loopback
  or a dedicated management network;
- place TLS and operator authentication at the management ingress;
- keep deploy tokens, Swift/S3 credentials, TLS keys, TempURL keys, and hash
  secrets outside Git and reports;
- use strict SSH host keys and avoid `--allow-password` unless a reviewed plan
  requires it;
- authorize disk, firewall, SSH, and host reconfiguration independently;
- cap file descriptors, memory, request sizes, upload lifetimes, connections,
  active requests, and blocking queues;
- verify logs redact auth tokens and signature-bearing query strings.

Source: https://docs.myswift.rs/security/index.mdx
