Skip to content

Latest commit

 

History

History
261 lines (209 loc) · 13.4 KB

File metadata and controls

261 lines (209 loc) · 13.4 KB

Security

Standards metadata

  • ID: topic.security
  • Role: topic
  • Level: MUST
  • Applies when: A change affects untrusted input, protected resources, identity, authorization, sensitive data, credentials, cryptography, secure transport, executable dependency trust, or network listeners.
  • Does not apply when: No trust boundary, protected operation, sensitive data, credential, cryptographic, dependency trust, or listener behavior is affected.
  • Requires: core, workflow.verification
  • Specializes: none
  • Verification: Untrusted-input, filesystem-containment, and network-transport decision fixtures plus affected trust-boundary tests.
  • Canonical owner: topics/security.md

Identity And Permission

At a protected operation, distinguish valid input, authenticated identity, and permission to perform the requested action on the requested resource. A valid identifier or an authenticated caller does not prove authorization. Establish identity through the application's supported authentication mechanism; verify credential authenticity, intended issuer and audience, lifetime, and revocation where the mechanism requires them. Do not trust caller-supplied identity or role headers merely because their shape is valid. Enforce permission at the trusted boundary before disclosing data or performing the effect, including tenant and ownership constraints. Deny access unless the applicable policy permits it; do not rely on a hidden UI control or an earlier unrelated authorization check. Test forbidden actions, cross-owner and cross-tenant access where relevant, and revoked or expired authority.

Untrusted Execution And Delegated Authority

When executed behavior has less permitted authority than its host, a component exercises protected authority for a less-trusted caller, or an execution isolation guarantee changes, follow Untrusted Execution And Delegated Authority. Ordinary trusted subprocess use alone does not select that detail.

Sensitive Data And Credentials

Identify sensitive fields and the owners allowed to receive them. Minimize collection, retention, and disclosure across responses, logs, traces, caches, and diagnostic artifacts. Redact before exporting diagnostics; return bounded public failure information while preserving useful restricted diagnostics. Keep secrets out of source control and ordinary logs. Supply credentials through the deployment's secret mechanism with the narrowest required access, and define rotation and revocation for long-lived credentials.

For network paths carrying sensitive data or credentials, use an established secure transport with peer verification. Use maintained cryptographic implementations and the platform's secure randomness and key storage rather than custom cryptography. Select algorithms and configuration against the actual threat model and supported platform requirements.

Dependency And Build Trust

Treat downloaded packages, build tools, generated artifacts, and CI extensions as executable trust decisions. Select their source and identity explicitly, verify the integrity or provenance required by the distribution contract, and restrict the credentials and authority available to them. Keep untrusted contribution jobs away from publication secrets. Own vulnerability triage and remediation across the supported lifecycle; a clean scan alone does not prove trustworthiness. Dependencies and Build own the corresponding procedures.

Untrusted Structured Input

Decode untrusted structured input through the complete contract required by the operation before it can authorize work, resource access, or side effects. Parsing, deserialization, static typing, type assertions, generic shape checks, and envelope-only validation are not proof of operation-specific fields.

The Contracts topic owns generic runtime proof. Select the IPC boundary profile when structured messages cross a process or independently evolving component boundary. Security does not duplicate their schemas or dispatch logic.

Malformed or incomplete input returns typed invalid; a well-formed but unsupported contract or operation returns typed unsupported; unavailable required decoding capability returns typed unavailable. Do not continue with the original input, a cast, a default operation, or a weaker decoder.

Input Validation Authority

When untrusted input can authorize an operation, resource access, side effect, or security-relevant decision, select one canonical validation authority for the complete operation contract at each applicable boundary. The authority may be a decoder, smart constructor, generated validator, schema implementation, or another mechanism that proves the complete contract. It does not mandate one global validator class or utility.

The operation contract defines all applicable shape, field, domain, bound, identifier, normalization, defaulting, version, and cross-field invariants. Do not invent a regular expression, length, non-empty rule, numeric range, cast, or default independently of that contract. File paths additionally use Filesystem Containment; structured messages use the selected IPC boundary profile.

Every entry point enforcing the same operation contract must consume the same canonical contract authority. Executable validators may be generated from that authority or implemented separately when language or deployment boundaries require it, but each implementation needs conformance evidence against the complete contract. Independently copied or inline rules without that authority and evidence can diverge and are invalid. Different operation contracts or new applicable boundaries may select different authorities and may require new proof.

The Contracts topic owns the proof-bearing representation and complete decoding semantics. Security owns the requirement for proof before untrusted input can authorize work and the consequences of missing or failed proof. Return typed invalid for failed or incomplete proof, unsupported for a well-formed unsupported contract or variant, and unavailable when the selected contract material or required validation capability cannot be obtained.

Do not fall back to a global catch-all validator, fixed rules, a cast, an independent inline validator, the original input, a permissive default, or a weaker validation mechanism.

Generated Command And Configuration Text

When validated values are projected into command, launcher, desktop-entry, script, configuration, or other executable text, select the destination grammar and operation contract before serialization. Validate semantic values before encoding them, preserve argument boundaries, and encode each value for its exact destination field. Validation and destination encoding are separate proof obligations; quoting for one grammar does not authorize reuse in another.

Construct output from structured arguments or fields whenever the destination supports them. If text generation is required, use an implementation whose conformance to the selected grammar is tested. Do not concatenate raw values, evaluate generated strings, reuse shell quoting for desktop entries, infer a URL scheme, or treat a helper name as proof of validation or encoding.

Negative evidence covers spaces, separators, quotes, control characters, newlines, substitution syntax, option-like values, invalid schemes, and destination-specific metacharacters applicable to the selected grammar. Reject failed semantic validation or encoding as typed invalid; return typed unsupported for a well-formed value the destination cannot represent and typed unavailable when the required grammar, encoder, or validation authority cannot be established. Do not emit a partial command, alternate destination, raw value, or default command.

Network Transport Boundary

A listener's exposure comes from the declared service and deployment contract. Local, remote, and multi-interface exposure are deployment facts, not defaults inferred from development mode, transport type, or address family. If the required exposure cannot be established, return typed unavailable; reject contradictory or unauthorized exposure as invalid.

The listener owner defines a finite admission capacity and the corresponding overload outcome. Acquire admission before accepting work that would exceed the owned limit. Capacity exhaustion returns the declared typed overload result; it does not accept first, queue without an owned bound, or choose a default capacity.

After acceptance, register the connection work with the selected lifecycle owner. That owner observes success, failure, and cancellation. Use Concurrency for work ownership, failure observation, cancellation, drain, and shutdown behavior. Logging at a connection leaf does not transfer lifecycle ownership.

Close admission before signalling cancellation, then drain registered work. Report incomplete drain as a typed incomplete-shutdown outcome. Forced termination is permitted only when there is explicit authority and the work is proven interruption-safe; otherwise preserve the incomplete result.

Select connection-liveness behavior from protocol semantics and resource risk. Protocol closure, transport keepalive, application heartbeat, idle deadline, or another supported mechanism is valid only when the selected contract defines its behavior and capability. Missing facts or capability return typed invalid, unsupported, unavailable, overload, or incomplete-shutdown outcomes as applicable.

Message validation remains with Contracts and the selected IPC boundary profile. Transport acceptance does not prove a message schema, action payload, or dispatch variant.

No Fallback

Do not broaden exposure, select a default address, capacity, timeout, or liveness mechanism, accept before capacity, detach work, discard outcomes, substitute leaf logging for ownership, leave admission open during shutdown, force termination without authority and interruption safety, or select another runtime, thread, listener, or transport when the required contract or capability is missing.

Filesystem Containment

Treat a path as authority to a filesystem object, not as an ordinary string. Before an operation, establish:

  • the trusted root and the operation it authorizes;
  • whether the candidate must already exist or may be created;
  • the platform and filesystem identity semantics;
  • whether an attacker can modify path components concurrently; and
  • the typed result when safe resolution cannot be established.

Unknown facts produce a typed diagnostic. Do not accept a path by guessing a platform default, falling back to lexical comparison, or ignoring failed canonicalization.

Existing Candidates

Resolve the trusted root and existing candidate using filesystem-aware canonical identity. Accept the candidate only when its resolved path is the root or a component descendant permitted by the operation.

A string-prefix test is not containment. It confuses sibling names such as /srv/data and /srv/data-backup, ignores component boundaries, and does not resolve symlink aliases. Case folding and Unicode normalization follow the actual filesystem contract; operating-system labels alone are insufficient when mounted filesystems can differ.

Reject traversal or a resolved symlink escape as invalid. Return unavailable when required identity facts cannot be resolved safely.

Non-Existing Candidates

For creation, resolve and validate the nearest existing ancestor, then validate each remaining component under the intended operation. Reject parent traversal, absolute replacement, invalid components, and any target whose validated ancestor is outside the trusted root.

Use a platform capability that anchors creation to the validated directory when the threat model permits concurrent mutation. Lexically appending a non-existing suffix to a previously checked string does not establish containment.

Validation And Use

Validation followed by a path-based operation can race with symlink or directory replacement. When untrusted actors can mutate the path concurrently, use handle-relative, capability-based, or equivalent platform operations that preserve the validated authority through use.

Revalidation is sufficient only when the recorded threat model excludes concurrent mutation for the complete validation/use interval. If the required atomic or anchored operation is unavailable, return a typed unsupported or unavailable result rather than silently using a weaker path.

Verification

Affected checks cover:

  • declared local, remote, and multi-interface listener exposure;
  • admission before acceptance, overload, and tracked connection outcomes;
  • ordered listener shutdown, incomplete drain, and termination authority;
  • protocol-selected liveness and unavailable capability;
  • .. traversal and absolute-path replacement;
  • sibling-prefix confusion;
  • symlinks that remain inside or escape the trusted root;
  • the root itself when the operation permits it;
  • creation beneath validated and unvalidated ancestors;
  • platform-specific case, normalization, and alias behavior;
  • concurrent component replacement where it is in scope; and
  • typed failure when safe containment cannot be established.

Use the Cross-Platform topic for path construction, filesystem identity, and supported-platform evidence.