Security Policy
Relevant source files
The following files were used as context for generating this wiki page:
The Numan Registry security policy defines the trust model, architectural invariants, and operational procedures used to maintain the integrity of the official Nushell package catalog. As a data-only repository, security is centered on the cryptographic signing of the registry index and the prevention of secret leakage within the CI/CD pipeline.
The policy covers the scope of vulnerability reporting, the immutable nature of published artifacts, and the multi-stage validation process required for any catalog promotion. It ensures that Numan clients can safely download and verify plugins, modules, and scripts through a decentralized trust root.
Sources: SECURITY.md:1-6, README.md:10-18, AGENTS.md:7-10
Trust Model and Scope
The repository operates on a trust model where the production client verifies Ed25519 signatures over the canonical bytes of index.json. This trust is rooted in an official key baked into the Numan CLI. Artifacts listed in the index are immutable; remediation for compromised or incorrect data requires a newly signed index revision (yank or new version) rather than an in-place rewrite.
Scope of Security Responsibilities
| In Scope | Out of Scope |
|---|---|
| Malicious/mismatched artifacts in signed index | Bugs in the Numan CLI client |
| Signing-key exposure or signature bypass | Vulnerabilities in upstream third-party packages |
| Secret leakage (private keys, tokens) in repo | Social engineering or DoS against GitHub Pages |
| Incorrect metadata leading to unsafe fetches | Issues requiring NUMAN_ALLOW_UNSIGNED |
Sources: SECURITY.md:27-46, SECURITY.md:48-60
Artifact Integrity
Plugin artifacts must carry SHA-256 digests. The Numan client refuses to install any binary without a matching digest. Furthermore, the installation process is inert; fetching a package does not automatically run Nu plugin registration, which remains a separate, user-driven activation step.
Sources: SECURITY.md:52-56
Key Management and Provisioning
Key management is designed to ensure that the registry private key is never exposed to the source tree, build logs, or automated agents. The production private key is stored as a GitHub Environment Secret for the production environment and is only accessible to protected deployment workflows.
Provisioning Workflow
The scripts/provision-production-key.sh script is used for local keypair generation and verification. It enforces strict security measures:
- Private Key Handling: The script never prints the private key to stdout/stderr.
- Permissions: It writes the private key to a file with
600permissions. - Fingerprinting: It generates a 16-hex-character SHA-256 fingerprint for public key verification.
CI/CD Security and Workflow Safety
The repository utilizes GitHub Actions with strict permission sets to prevent unauthorized signing or publication. All workflows default to contents: read permissions.
Workflow Safety Invariants
- Pinning: Every GitHub Action must be pinned to a 40-character commit SHA to prevent supply-chain attacks via tag floating.
- Secret Isolation: The
NUMAN_REGISTRY_PRIVATE_KEYis restricted to thesign-and-publishjob in the production workflow, which requires reviewer approval. - No Shell Templates: Signing values (like
key_id) are passed as data environment variables, not as shell templates, to prevent injection.
Architectural Invariants and Review Gates
Reviewers (human and automated) must enforce specific architectural invariants to maintain the security posture of the registry.
Core Invariants
- No Private Keys: Secret scanning (
scripts/scan_for_secrets.py) must remain green; private key material (*.key,*.pem) is gitignored and prohibited in the tree. - Placeholder Signatures: The committed
registry/index.json.sigis aPLACEHOLDER. Real signatures are only generated during protected deployments. - Download-only Hashes: SHA-256 digests must be computed via
scripts/add-package.pythrough artifact download; hand-typing hashes is a P0 violation. - Binary Only: Intake of
kind: sourceis rejected; the catalog only promotes binary artifacts.
Sources: REVIEW.md:46-63, AGENTS.md:27-31
Severity Classification for Review
| Severity | Meaning |
|---|---|
| P0 | Trust bypass, private keys in tree, hand-typed hashes, unsigned-production fallback. |
| P1 | Schema/parser mismatch, incorrect intake validation, missing lifecycle evidence. |
| P2 | Maintainability issues, doc drift, misleading checklists. |
Sources: REVIEW.md:38-44
Data Integrity and Schema
The index.json file must follow the versioned schema defined in schemas/index-v1.json. Security is maintained by signing the canonical JSON bytes (sorted keys, compact encoding).
Schema Components
| Component | Requirement | Description |
|---|---|---|
schema_version | Integer (1) | Must be version 1. |
trust | Object | Contains key_id and public_key_b64 for key rotation. |
artifact | Object | Must include kind (binary/archive) and sha256. |
signature | Base64 | Detached signature over canonical bytes. |
Sources: schemas/index-v1.json:6-20, README.md:79-88
Vulnerability Reporting
The project maintains a structured approach to vulnerability disclosure to prevent public exploitation.
- Preferred Method: Open a private GitHub security advisory.
- Fallback: Open a public issue titled "Security contact request" without technical details.
- Required Info: Package ID/version, target triple, artifact URL/digest, and reproduction steps.
Sources: SECURITY.md:8-25
The security of the Numan Registry relies on the combination of cryptographic verification, strictly controlled secret management, and automated CI gates that prevent the promotion of unverified or insecure metadata.