Skip to content

Potential fix for code scanning alert no. 1: Workflow does not contain permissions#5

Merged
m1ngshum merged 1 commit into
mainfrom
fix/alert-autofix-1
May 11, 2026
Merged

Potential fix for code scanning alert no. 1: Workflow does not contain permissions#5
m1ngshum merged 1 commit into
mainfrom
fix/alert-autofix-1

Conversation

@m1ngshum

Copy link
Copy Markdown
Member

Potential fix for https://github.com/getmcpm/cli/security/code-scanning/1

Add an explicit permissions block in .github/workflows/ci.yml at the workflow root (recommended here since there is one job and all steps are read-only). Use least privilege:

  • contents: read

This preserves existing functionality (checkout and CI commands continue to work) while preventing accidental write-capable token use if defaults change.

Suggested fixes powered by Copilot Autofix. Review carefully before merging.

…n permissions

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
@m1ngshum m1ngshum marked this pull request as ready for review May 11, 2026 18:14
@m1ngshum m1ngshum merged commit 0670848 into main May 11, 2026
7 checks passed
@m1ngshum m1ngshum deleted the fix/alert-autofix-1 branch May 11, 2026 18:14
m1ngshum added a commit that referenced this pull request Jun 1, 2026
…-disable

Applies review findings #1#5 from the multi-perspective review:

- #1/#5: extract the secret→placeholder swap into a single
  `applyKeychainSecrets()` in keychain.ts (also now the home of
  `SecretsMode`). install.ts and up.ts both delegate to it, so the
  "no plaintext secret in config" invariant lives in one place and
  can't diverge. Drops the duplicated loop + the `storedSecretKeys`
  array (now a returned count).
- #2: guard disable's placeholder warning is now a static import,
  never throws (advisory scan can't break a successful disable), and
  surfaces non-ENOENT config-read errors instead of swallowing them.
- #3: `up --secrets keychain` only prints the "run mcpm guard enable"
  notice when a secret was actually stored (threaded via storedCount).
- #4: add tests for applyKeychainSecrets, the slash-name keychain-id
  round-trip, and placeholderEnvKeys (the disable-warning detector).

1088 tests pass; typecheck + build clean.
m1ngshum added a commit that referenced this pull request Jun 1, 2026
* feat: add `--secrets keychain` to install/up + guard-disable safety

Phase 2 of encrypted secrets. Opt-in, default unchanged (plaintext), so
no existing flow regresses.

- install/up `--secrets keychain`: secret-flagged env vars are stored
  AES-GCM-encrypted in ~/.mcpm and written into client configs as
  `mcpm:keychain:server/KEY` placeholders instead of plaintext.
  Non-secret vars stay inline. mcpm guard resolves the placeholders at
  launch (Phase 1). Both commands print a "run `mcpm guard enable`" note.
- `up --secrets keychain` is rejected under `--ci` (never persist
  secrets to a CI runner's keychain).
- keychain.ts: add deriveKeychainId() — maps slash-containing registry
  ids (io.github.owner/repo) to a placeholder-safe keychain id.
- guard disable: read-only post-disable scan warns when an unwrapped
  config still references `mcpm:keychain:` placeholders (they only
  resolve under guard). Never silently rewrites plaintext (security-first).

Tests: 9 new (deriveKeychainId, install/up keychain placeholder writes,
plaintext no-regression, missing-dep + --ci guards). 1082 pass;
coverage 80.85% lines / 87.57% branches. typecheck + build clean.

* refactor: address PR review — consolidate keychain swap, harden guard-disable

Applies review findings #1#5 from the multi-perspective review:

- #1/#5: extract the secret→placeholder swap into a single
  `applyKeychainSecrets()` in keychain.ts (also now the home of
  `SecretsMode`). install.ts and up.ts both delegate to it, so the
  "no plaintext secret in config" invariant lives in one place and
  can't diverge. Drops the duplicated loop + the `storedSecretKeys`
  array (now a returned count).
- #2: guard disable's placeholder warning is now a static import,
  never throws (advisory scan can't break a successful disable), and
  surfaces non-ENOENT config-read errors instead of swallowing them.
- #3: `up --secrets keychain` only prints the "run mcpm guard enable"
  notice when a secret was actually stored (threaded via storedCount).
- #4: add tests for applyKeychainSecrets, the slash-name keychain-id
  round-trip, and placeholderEnvKeys (the disable-warning detector).

1088 tests pass; typecheck + build clean.

* fix(security): injective keychain id + atomic secret store + honest messaging

Addresses the dedicated security audit of the secrets feature:

- CRIT-1: deriveKeychainId is now injective — sanitized prefix + a
  sha256 suffix — so names differing only in unsafe chars
  ("owner/repo" vs "owner_repo") can no longer collide into one secret
  namespace (cross-server secret confusion/exposure).
- MED-1: applyKeychainSecrets persists all of a server's secrets in a
  single atomic batch (new keychain.setSecrets) BEFORE returning the env
  written to config — no orphaned half-written secrets if one fails.
  install/up deps switch from setSecret to setSecrets accordingly.
- MED-4: install/up notices no longer overclaim — they state secrets are
  "encrypted at rest (protects against other-user/offline access, not
  same-user processes)", matching keychain.ts's documented posture.

Tests updated to the batch API + an explicit collision-injectivity test.
1088 pass; typecheck + build clean.

Pre-existing guard/keychain findings (full-env forward, event-log
sanitization, store write lock, log rotation) are out of scope here and
tracked separately.
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.

1 participant