メインコンテンツまでスキップ

Operational Security

The cryptographic core can be flawless and the deployment around it can still hand an attacker the keys. Operational security is the set of requirements on how the protocol is run and shipped: where secrets live, what the network exposes, what clients persist, how inputs are handled, and how builds are produced. These are not protocol internals, but a conforming EDH deployment depends on them just as much.

Secrets must be injected at runtime, never committed or bundled

OS-1 (MUST). API keys, database credentials, service-account keys, signing/MAC keys, and access tokens MUST be provided to a running service from a secrets manager (or equivalent runtime-injected configuration) and MUST NOT be committed to source control, embedded in CI configuration as literals, or compiled into client artifacts (web bundles, mobile binaries, browser extensions). Keys that are necessarily client-distributed (e.g. map/geocoding keys) MUST be provider-restricted (referrer/app/bundle and quota limits).

Rationale. Anything shipped to a client is public — a determined user can extract any key from a web bundle, a mobile binary, or an extension. Anything in git history is recoverable even after deletion. A secret in a build artifact or a repository is not "leaked if someone looks"; it is already disclosed. Runtime injection keeps the secret out of every place an outsider can read and makes rotation a configuration change rather than a code change.

OS-2 (MUST). When a secret has been exposed (committed, bundled, or logged), remediation MUST be rotation at the provider first, then removal from tracking and history. Removing the value from the current tree alone is NOT sufficient — the old value remains live and recoverable until rotated.

Conformance check. Scan tracked files, build artifacts, and history for credential patterns; confirm no live secret resolves. Confirm services read secrets from injected configuration, not embedded literals.

Network surface must be minimized and authenticated

OS-3 (MUST). Datastore and internal-service ports MUST be reachable only from their intended private network or security group, never from 0.0.0.0/0. Administrative, cluster, and storage-node control APIs MUST require authentication and MUST NOT be served with a permissive (*) CORS policy on a public interface. A comment asserting an intended scope MUST match the rule actually configured.

Rationale. A database or cluster-admin API exposed to the internet is gated only by credentials — one weak or leaked credential from defense-in-depth's last layer becomes the only layer. Permissive CORS on an admin API lets any web page the operator visits drive it. Drift between an intended scope ("within the VPC") and the configured rule ("open to all") is a frequent cause of exposure; the configuration, not the comment, is what the network enforces.

Clients must not persist tokens or plaintext PHI in general-purpose storage

OS-4 (MUST). Client applications MUST NOT store bearer/refresh tokens or plaintext PHI in general-purpose, script-readable storage (browser localStorage, mobile AsyncStorage, or equivalent). Session tokens SHOULD live in httpOnly+Secure cookies or an OS keychain; PHI MUST be held only in the encrypted store. Storage that is "encrypted" only when an optional component is present MUST NOT be relied on as encryption.

Rationale. localStorage/AsyncStorage is plaintext on disk and readable by any script in the origin — so any injection (see OS-5), malicious extension, or device-level access yields the token (full account takeover) and any PHI sitting beside it. This also undermines the sovereign-storage guarantee: data written here bypasses the encryption layer entirely. Conditional encryption that silently degrades to plaintext when its key source is absent is, for the common case, no encryption at all.

Input must be validated; identifiers must never be interpolated; errors must not leak internals

OS-5 (MUST). All external input MUST be validated against an explicit typed schema before use, and request bodies MUST NOT be mass-assigned onto persisted entities. User-supplied strings MUST NOT be interpolated into a query as SQL identifiers (column/table names) or operators; where a query is parameterized, only values may be bound, and any user-controlled key MUST be allowlisted against known entity metadata. Server-side fetches of user-supplied URLs MUST block private, loopback, and cloud-metadata address ranges and limit redirects. Error responses to clients MUST NOT include raw database or internal exception messages.

Rationale. Several distinct failures share this root — trusting input shape:

  • SQL identifier injection. Parameterization protects values, not identifiers. If a user-supplied key is concatenated into the query as a column name (even quoted), a crafted key escapes the quoting and injects arbitrary SQL — unauthenticated database compromise. The defense is an allowlist of permitted keys, not escaping.
  • Mass assignment. Copying a whole request body onto an entity lets a caller set fields they should never control (owner id, primary key, role). Validate into an explicit shape and bind only intended fields.
  • SSRF. A server that fetches an attacker-chosen URL can be steered at internal services or the cloud metadata endpoint; an allowlist plus blocking private ranges and redirects contains it.
  • Error leakage. Reflecting raw driver/exception text hands an attacker schema, query fragments, and a precise oracle for the above. Return generic messages; log the detail server-side.

Builds and deploys must enforce integrity

OS-6 (SHOULD). Dependency installation in CI/build SHOULD use integrity-pinned, reproducible installs (a committed lockfile installed with its integrity enforced), avoid a single mutable set of build inputs without verification, and avoid known-vulnerable pinned versions of security-relevant libraries. Deploy/signing keys MUST NOT fall back to well-known, default, or test private keys for any non-local network.

Rationale. A locally-referenced or non-integrity-checked dependency that is swapped for a tampered version executes at install/build time with full privileges — a supply-chain compromise. Outdated security libraries carry known, public exploits. A deploy path that silently falls back to a publicly known private key when a real one is unset can sign or deploy with a key anyone possesses.

Summary

IDRequirementPrevents
OS-1Inject secrets at runtime; restrict client-distributed keysDisclosed credentials in bundles/source
OS-2Rotate first, then untrack and purge historyLive secrets surviving "deletion"
OS-3Minimize and authenticate network surfaceInternet-exposed datastores / admin APIs
OS-4No tokens/PHI in general-purpose client storageToken theft & PHI disclosure via injection
OS-5Validate input; allowlist identifiers; block SSRF; hide errorsSQLi, mass assignment, SSRF, info leak
OS-6Integrity-pinned builds; no default deploy keysSupply-chain & deploy-key compromise