Skip to content

Address repository audit hardening - #61

Closed
ar27111994 wants to merge 6 commits into
mainfrom
feature/audit-hardening
Closed

Address repository audit hardening#61
ar27111994 wants to merge 6 commits into
mainfrom
feature/audit-hardening

Conversation

@ar27111994

@ar27111994 ar27111994 commented May 2, 2026

Copy link
Copy Markdown
Owner

Summary

Addresses the post-merge repository audit with focused hardening, safer defaults, and updated documentation.

Security and runtime hardening

  • reject mirror multi-file artifact path traversal outside the raw mirror root
  • add guarded HTTP helpers with origin allowlists, timeouts, and response byte limits
  • use guarded fetches for official index content, official page summaries, raw GitHub file content, npm metadata, and PyPI metadata
  • validate and normalize PyPI metadata field-by-field before repository URL extraction
  • reset GitHub process-local rate-limit and health-update state during CLI bootstrap
  • resolve the VS Code settings path lazily after .env loading and runtime config reset

Lifecycle and CLI behavior

  • make wire <host> default to preview; require explicit --apply or --reset for mutations
  • run recommend report explicitly in workspace orchestration instead of relying on discover select side effects
  • fix install batching so missing progress state is not treated as completion
  • centralize CLI option parsing and reject flag-looking values as missing option values
  • document doctor and default recommend report behavior

Source utilization and docs

  • attempt guarded summaries for docs, registry, and marketplace reference sources
  • distinguish active, reference-only, and dormant source utilization
  • update roadmap and implementation-plan status so remaining roadmap-scale work is accurately tracked
  • align package description with current host support

Tests

  • add regression tests for dotenv duplicate/multiline behavior
  • add CLI option missing-value tests
  • add safe mirror path and PyPI normalization tests
  • add VS Code settings read/patch tests

Validation

  • npm run typecheck
  • npm run lint
  • npm run format:check
  • npm run build
  • npm test
  • npm run smoke:cli
  • npm run benchmark:scan
  • npm run quality:detection
  • npm run quality:policy
  • npm run validate:recommendations
  • git diff --check
  • node ./dist/cli.js setup doctor --host --other (fails with the expected missing-value message)
  • node ./dist/cli.js wire cursor (defaults to preview)

Summary by CodeRabbit

Release Notes

  • New Features

    • Wire command defaults to preview mode; use --apply or --reset for mutations
    • Workspace runs now explicitly invoke recommendations after discovery
  • Bug Fixes

    • Safe mirror artifact paths against traversal attacks
    • Guarded HTTP fetching with origin allowlists and byte limits
    • PyPI metadata field validation and normalization
    • Process-local GitHub state reset between CLI invocations
    • Install batching progress state handling
    • Lazy VS Code settings path resolution for .env overrides
    • CLI option parsing rejects invalid flag tokens
  • Documentation & Tests

    • Updated lifecycle and command documentation
    • Added tests for dotenv parsing, CLI options, and security hardening

Copilot AI review requested due to automatic review settings May 2, 2026 14:46
@qodo-code-review

Copy link
Copy Markdown
ⓘ You've reached your Qodo monthly free-tier limit. Reviews pause until next month — upgrade your plan to continue now, or link your paid account if you already have one.

@coderabbitai

coderabbitai Bot commented May 2, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@ar27111994 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 33 minutes and 42 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 88afa489-2fc6-4133-839a-e670d76e697a

📥 Commits

Reviewing files that changed from the base of the PR and between 13fa0ab and 1a5632e.

📒 Files selected for processing (11)
  • CHANGELOG.md
  • src/cli.ts
  • src/discover.ts
  • src/lib/http.ts
  • src/mirror.ts
  • src/official-index.ts
  • src/package-registries.ts
  • src/pipeline.ts
  • src/tests/cli-options.test.ts
  • src/tests/security-hardening.test.ts
  • src/wire.ts
📝 Walkthrough

Walkthrough

This PR introduces v1.0.0 hardening and feature updates: centralized CLI option parsing with validation, guarded HTTP fetching with origin allowlists and byte limits, mirror path traversal protection, PyPI metadata field validation, preview-by-default wire mode, explicit workspace recommendation execution, lazy VS Code settings path resolution, and resettable in-process GitHub state. Documentation and test coverage are updated accordingly.

Changes

V1.0.0 Hardening & Feature Release

Layer / File(s) Summary
Shared Infrastructure
src/lib/cli-options.ts, src/lib/http.ts
New getOptionValue and getOptionValues utilities centralize CLI flag parsing with validation (rejecting missing/flag-like values). New guarded HTTP utilities (fetchWithTimeout, fetchTextWithGuards, fetchJsonWithGuards, assertAllowedHttpUrl, readResponseTextWithLimit) enforce HTTPS, origin allowlists, timeouts, and response byte limits.
CLI Integration
src/activate.ts, src/recommend.ts, src/setup.ts, src/install.ts, src/workspace.ts, src/cli.ts
All CLI-consuming modules replace local getOptionValue implementations with imports from shared lib/cli-options. CLI now initializes clearGitHubState() at startup and logs error.message in error handler; help adds doctor command alias.
Discovery & Registry Hardening
src/discover.ts, src/official-index.ts, src/package-registries.ts, src/mirror.ts
Official index and registry fetches switch to fetchTextWithGuards/fetchJsonWithGuards with configured allowlists and byte limits. PyPI and npm metadata now undergo field-by-field normalization and validation before use. Mirror writes route through resolveSafeMirrorFilePath to block directory traversal. Discover harvests reference sources via new harvestReferenceSource and evaluates operational status via isOperationalCatalogEntry.
Feature & Behavior Changes
src/wire.ts, src/pipeline.ts, src/host-adapters/vscode.ts, src/github.ts
Wire defaults to "preview" mode instead of "apply". Workspace pipeline explicitly invokes runRecommend(["report"]) after discovery selection. VS Code wiring resolves settings path locally and threads it through patch/reset operations for .env override support. Added clearGitHubState() export to reset process-local rate-limit and health-update state.
Test Coverage
src/tests/cli-options.test.ts, src/tests/env-file.test.ts, src/tests/security-hardening.test.ts, src/tests/vscode-settings.test.ts
New test suites validate centralized CLI option parsing (single/repeatable flags with error handling), dotenv multiline/duplicate/export parsing, mirror path traversal rejection, PyPI metadata normalization/filtering, and VS Code settings JSONC read/write with parent directory creation.
Documentation
CHANGELOG.md, README.md, IMPLEMENTATION-PLAN.md, Roadmap.md, package.json
CHANGELOG documents v1.0.0 added/changed/fixed items. README updates lifecycle steps and clarifies wire preview-by-default semantics. IMPLEMENTATION-PLAN and Roadmap enumerate hardening wave outcomes and remaining tracked work. Package.json description updated to reflect CLI's discover/stage/activate/wire workflow.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Poem

🐰 With guards and paths now safe and sound,
CLI parsing centralized all around,
HTTP calls with allowlists bright,
Wire previews first—much safer quite!
The rabbit hops through v1.0.0 with glee, 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 19.70% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Address repository audit hardening' directly summarizes the main purpose of the PR: implementing security and hardening improvements from an audit.
Description check ✅ Passed The PR description is comprehensive, covering Summary, Background (implicit in objectives), Changes (organized into logical sections), Validation (extensive command list), and documentation impact.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/audit-hardening

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 33 minutes and 42 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements post-audit hardening across the CLI lifecycle pipeline: safer mirror writes, guarded external HTTP reads, stricter CLI option parsing, and behavioral tweaks to make mutating operations more explicit—along with regression tests and documentation updates.

Changes:

  • Add guarded HTTP utilities (origin allowlists, timeouts, byte limits) and apply them to official-index, GitHub raw reads, and registry metadata fetches.
  • Harden filesystem writes for mirrored multi-file artifacts via safe path resolution to prevent traversal outside the raw mirror root.
  • Centralize CLI option parsing (reject missing/flag-like values) and adjust lifecycle orchestration (explicit recommend report, preview-by-default wire intent), with accompanying tests/docs.

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/lib/http.ts New guarded fetch helpers with allowlists, timeouts, and response size limits.
src/lib/cli-options.ts New shared CLI option parsing helpers with missing-value rejection.
src/package-registries.ts Use guarded JSON fetches and normalize npm/PyPI metadata before use.
src/official-index.ts Use guarded text fetch for official index page summaries with origin allowlist.
src/mirror.ts Prevent mirror artifact path traversal; guarded GitHub raw fetch; summary materialization for *-summary methods.
src/discover.ts Guarded official index fetch; reference-source harvesting changes; utilization reporting refinements.
src/pipeline.ts Workspace pipeline now explicitly runs recommend report; fix install batching completion check.
src/wire.ts Change wire mode default to preview (but see review comment about --apply).
src/cli.ts Reset process-local GitHub state on bootstrap; add doctor alias; simplify top-level error output.
src/github.ts Add clearGitHubState() to reset throttling/health-update state between in-process invocations.
src/host-adapters/vscode.ts Resolve VS Code settings path lazily and thread it through patch/reset flows.
src/workspace.ts / src/setup.ts / src/recommend.ts / src/install.ts / src/activate.ts Adopt shared CLI option parsing helpers and remove local duplicates.
src/tests/*.test.ts Add regression coverage for dotenv parsing, CLI option parsing, mirror path safety, PyPI normalization, and VS Code settings.
README.md / Roadmap.md / IMPLEMENTATION-PLAN.md / CHANGELOG.md / package.json Update docs/metadata to reflect new defaults and hardening behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/wire.ts
Comment thread src/lib/http.ts
Comment thread src/lib/http.ts Outdated
Comment thread src/official-index.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/wire.ts (1)

61-79: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

--apply is silently treated as --preview — critical regression.

--apply is included in modeFlags for conflict detection but has no explicit return "apply" branch. Before this PR, falling through to the default return "apply" made it work by coincidence. Now that the default was changed to return "preview", any invocation of wire <host> --apply quietly produces preview-only behaviour: no host settings are mutated, no error is raised, and the caller has no indication that the apply was skipped.

🐛 Proposed fix
   if (modeFlags[0] === "--preview") {
     return "preview";
   }
 
+  if (modeFlags[0] === "--apply") {
+    return "apply";
+  }
+
   return "preview";
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/wire.ts` around lines 61 - 79, The function getWireMode currently detects
--apply in modeFlags but lacks an explicit branch, so --apply falls through to
the default "preview"; update getWireMode to explicitly handle the "--apply"
flag (check modeFlags[0] or use a switch over the detected flag) and return
"apply" when present, keeping existing conflict detection and retaining the
default behaviour for no flags; reference the getWireMode function and the
modeFlags variable when making the fix.
🧹 Nitpick comments (1)
src/cli.ts (1)

98-101: ⚡ Quick win

Stack trace is suppressed for all Error instances — consider preserving it for unexpected failures.

error instanceof Error ? error.message : error strips the stack trace for every Error, including unexpected internal errors (I/O failures, assertion violations, etc.). User-facing CLI errors like "Missing value for '--host'." read fine, but a buggy code path would only surface its message with no location.

The existing console.error(error) call in Node.js already prints the message prominently at the top, followed by the stack — which is the best of both worlds.

♻️ Proposed alternatives

Option A — restore full error output (simplest):

-    console.error(error instanceof Error ? error.message : error);
+    console.error(error);

Option B — clean output by default, stack on --debug:

-    console.error(error instanceof Error ? error.message : error);
+    const debug = process.argv.includes("--debug");
+    console.error(error instanceof Error && !debug ? error.message : error);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cli.ts` around lines 98 - 101, The catch handler in src/cli.ts currently
logs only error messages (console.error(error instanceof Error ? error.message :
error)), which strips Error stacks; change the handler to pass the original
error through to console.error (i.e., log the error object rather than just
error.message) so stack traces are preserved for unexpected failures (keep
setting process.exitCode = 1), or implement conditional stack printing using the
same catch handler (check error instanceof Error and print error.stack when a
debug flag/ENV is set).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/discover.ts`:
- Around line 472-490: The per-source status logic now distinguishes
"reference-only" (has catalog entries but no operational entries) from "dormant"
(no entries), but the aggregate dormantSourceCount still counts every
non-operational source; update the dormantSourceCount calculation to match the
per-source status by counting only sources with zero catalog entries (i.e.,
sourceEntries.length === 0) rather than all non-operational ones. Locate the
block that builds sources (the enabledSources.map producing
id/kind/configured/operational/harvestedEntries/operationalEntries/status) and
ensure the dormantSourceCount computation uses the same criteria (check
sourceEntries.length) so that dormantSourceCount only increments when a source's
status === "dormant".

In `@src/lib/http.ts`:
- Around line 17-29: fetchWithTimeout currently overwrites any caller-provided
options.signal, preventing upstream cancellation; modify fetchWithTimeout to
preserve and merge the incoming options.signal with the timeout AbortController
(e.g., create a timeout controller and if options.signal exists use
AbortSignal.any([options.signal, timeoutController.signal]) for the final signal
or attach a listener that aborts the timeout controller when options.signal
fires), pass that merged signal into fetch, and ensure you still clear the
timeout and remove any listeners in the finally block so no leaks occur; update
references in fetchWithTimeout to use the merged signal instead of directly
using controller.signal.

In `@src/package-registries.ts`:
- Around line 120-139: Normalize and validate PyPI URL fields before storing:
when building the returned info object in package-registries (fields
info.home_page and info.project_urls via normalizeStringRecord), parse each URL
string and only keep values that are valid absolute URLs with scheme "http" or
"https" and a non-empty host; otherwise set home_page to undefined and
drop/replace invalid project_urls entries. Update normalizeStringRecord (or its
caller) to perform this filtering/normalization so downstream functions like
extractRepositoryUrlFromPypiMetadata only see bona fide http(s) URLs; apply the
same validation logic to the other similar block that constructs
info.project_urls/info.home_page later in the file (the block referenced in the
review).

---

Outside diff comments:
In `@src/wire.ts`:
- Around line 61-79: The function getWireMode currently detects --apply in
modeFlags but lacks an explicit branch, so --apply falls through to the default
"preview"; update getWireMode to explicitly handle the "--apply" flag (check
modeFlags[0] or use a switch over the detected flag) and return "apply" when
present, keeping existing conflict detection and retaining the default behaviour
for no flags; reference the getWireMode function and the modeFlags variable when
making the fix.

---

Nitpick comments:
In `@src/cli.ts`:
- Around line 98-101: The catch handler in src/cli.ts currently logs only error
messages (console.error(error instanceof Error ? error.message : error)), which
strips Error stacks; change the handler to pass the original error through to
console.error (i.e., log the error object rather than just error.message) so
stack traces are preserved for unexpected failures (keep setting
process.exitCode = 1), or implement conditional stack printing using the same
catch handler (check error instanceof Error and print error.stack when a debug
flag/ENV is set).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2e08c7aa-d4c8-432d-ab7c-8afea5e36c33

📥 Commits

Reviewing files that changed from the base of the PR and between a909708 and 13fa0ab.

📒 Files selected for processing (25)
  • CHANGELOG.md
  • IMPLEMENTATION-PLAN.md
  • README.md
  • Roadmap.md
  • package.json
  • src/activate.ts
  • src/cli.ts
  • src/discover.ts
  • src/github.ts
  • src/host-adapters/vscode.ts
  • src/install.ts
  • src/lib/cli-options.ts
  • src/lib/http.ts
  • src/mirror.ts
  • src/official-index.ts
  • src/package-registries.ts
  • src/pipeline.ts
  • src/recommend.ts
  • src/setup.ts
  • src/tests/cli-options.test.ts
  • src/tests/env-file.test.ts
  • src/tests/security-hardening.test.ts
  • src/tests/vscode-settings.test.ts
  • src/wire.ts
  • src/workspace.ts

Comment thread src/discover.ts
Comment thread src/lib/http.ts
Comment thread src/package-registries.ts
Copilot AI review requested due to automatic review settings May 2, 2026 15:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 25 out of 25 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/pipeline.ts
Comment thread src/mirror.ts
@ar27111994 ar27111994 closed this May 2, 2026
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