Skip to content

Add threat model; make .npmrc rewrites atomic#15

Merged
jgowdy-godaddy merged 2 commits intomainfrom
docs/threat-model-and-atomic-npmrc
Apr 17, 2026
Merged

Add threat model; make .npmrc rewrites atomic#15
jgowdy-godaddy merged 2 commits intomainfrom
docs/threat-model-and-atomic-npmrc

Conversation

@jgowdy-godaddy
Copy link
Copy Markdown
Contributor

Summary

This repo previously shipped only DESIGN.md — no `THREAT_MODEL.md` and no `SECURITY.md`. This PR closes that gap and fixes a latent bug uncovered during the audit.

New docs

  • `THREAT_MODEL.md` — Type 2 (EnvInterpolation) threat model for npmenc / npxenc. Headline residual risk: every `npm install` runs arbitrary JS from transitive dependency lifecycle scripts with `NPM_TOKEN_` in the environment. This is the single biggest threat specific to npm as a Type 2 target and cannot be mitigated inside npmenc — it is the operator's responsibility (granular short-lived tokens, `--ignore-scripts` on untrusted trees). Also documented: same-UID `/proc//environ` readability, VCS-stored plaintext `.npmrc` rollback, concurrent npm vs. npmenc races, HTTPS-only registry URL reconstruction, over-injection of `NPM_TOKEN_` on subcommands that don't need it, token-source timeout, `` sentinel, program resolution / PATH trust, macOS `.handle` plaintext, Windows file-ACL inheritance, WSL bridge.
  • `SECURITY.md` — boilerplate + summary of guarantees and limitations matching the sister projects' style.

Latent bug fix: atomic `.npmrc` rewrite

Five `fs::write` call sites in `install.rs` and `uninstall.rs` rewrote `.npmrc` non-atomically. A power loss or crash mid-write could leave a half-stripped file — the plaintext prefix truncated away but the managed placeholder not yet written. Replace with `npmenc-core::atomic_write::atomic_write_preserving_mode`, which writes to a sibling temp file and renames over the target, preserving the original file's Unix mode bits.

  • New module: `npmenc-core/src/atomic_write.rs` with 4 unit tests covering new-file, overwrite, mode preservation, and default-perms cases.
  • Public API: `atomic_write_preserving_mode(path, contents) -> Result<()>` — no breaking changes to consumer code.

Test plan

  • `cargo test --workspace` — 244 tests pass (4 new for atomic write, 240 prior).
  • `cargo clippy --workspace --all-targets -- -D warnings` clean.
  • `cargo fmt --all -- --check` clean.
  • CI green on macOS / Linux / Windows.

jgowdy added 2 commits April 16, 2026 22:13
This repo previously shipped only DESIGN.md — no dedicated threat model
and no security policy. Add THREAT_MODEL.md that names what npmenc does
and doesn't protect against under Type 2 (EnvInterpolation) delivery,
with explicit focus on:

- The defining residual risk: every npm install runs arbitrary JS from
  transitive dependency lifecycle scripts with NPM_TOKEN_* in the
  environment. This is the single biggest threat specific to npm as a
  Type 2 target and cannot be mitigated inside npmenc.
- Same-UID /proc/<npm-pid>/environ readability for npm's full lifetime.
- npmenc-specific concerns: rollback via VCS-stored plaintext .npmrc,
  atomic rewrites, concurrent npm vs. npmenc, HTTPS-only registry URL
  reconstruction, over-injection of NPM_TOKEN_* on subcommands that
  don't need it, token-source timeout, <redacted> sentinel, program
  resolution, macOS .handle plaintext, multi-user systems, WSL bridge.

Add SECURITY.md with the usual reporting-vulnerabilities boilerplate
plus a summary of guarantees and limitations, mirroring the sister
projects' style.

Make .npmrc rewrites atomic. The five fs::write call sites in
install.rs and uninstall.rs are replaced with a new
npmenc-core::atomic_write::atomic_write_preserving_mode that writes
to a sibling temp file and renames over the target, preserving the
original file's Unix mode bits. Power loss / crash mid-rewrite now
leaves either the pre-install or post-install contents, never a
partial mix.

4 unit tests added for the atomic-write helper; existing install /
uninstall tests continue to pass. No public API changes.
The module-level `use std::fs;` was flagged as unused on Windows by
`-D warnings` because both `fs::metadata` and `fs::set_permissions`
live inside `#[cfg(unix)]` blocks. Switch those two call sites to
fully-qualified `std::fs::...` paths and move the `use std::fs;`
into the tests module where it's consumed on all platforms by
`fs::write` / `fs::read` helpers.
@jgowdy-godaddy jgowdy-godaddy merged commit 1565f2c into main Apr 17, 2026
3 checks passed
jgowdy-godaddy pushed a commit that referenced this pull request Apr 17, 2026
- Drop the stale "Planned Future Extraction" section: enclaveapp-app-adapter
  was incubated here and has since been promoted into libenclaveapp.
- Overview and Workspace Layout no longer list the adapter as a local crate.
- Document atomic .npmrc rewrites via atomic_write_preserving_mode (PR #15).
- Document the --publish-only wrapper flag and its subcommand classification
  helpers in cli_common (PR #17).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants