Security Review Remediations#91
Conversation
…ons in CI and release workflows
There was a problem hiding this comment.
Pull request overview
Implements a set of security-focused remediations across the Smartsheet MCP server, including stricter input validation, safer request construction/logging, updated dependencies/tooling, and enabling CI test execution.
Changes:
- Add Zod validation hardening for tool inputs (numeric IDs, email format) and constrain sheet cell
valuetypes. - Improve Smartsheet API client safety: enforce HTTPS endpoint, avoid logging query strings/base URL, sanitize error logging, cap rate-limit backoff, and pass query params via
request(..., queryParams). - Add Jest tests + CI workflow, update GitHub Actions usage, and refresh dependency/toolchain versions.
Reviewed changes
Copilot reviewed 15 out of 19 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tsconfig.json | Excludes __tests__ from TypeScript compilation. |
| src/tools/smartsheet-workspace-tools.ts | Minor handler signature cleanup. |
| src/tools/smartsheet-user-tools.ts | Add numeric ID validation for userId. |
| src/tools/smartsheet-update-request-tools.ts | Add numeric ID + email validation. |
| src/tools/smartsheet-sheet-tools.ts | Add numeric ID validation; restrict cell value types; tweak URL parsing regex. |
| src/tools/smartsheet-search-tools.ts | Add numeric ID validation; tweak URL parsing regex. |
| src/tools/smartsheet-folder-tools.ts | Add numeric ID validation for folder/workspace IDs. |
| src/tools/smartsheet-discussion-tools.ts | Add numeric ID validation for sheet/row IDs. |
| src/tools/tests/smartsheet-sheet-tools.test.ts | New tests verifying cell value validation behavior. |
| src/apis/smartsheet-search-api.ts | Use request(..., queryParams) instead of interpolating query strings. |
| src/apis/smartsheet-api.ts | Enforce HTTPS base URL, sanitize logs, cap backoff delay, reduce request log sensitivity. |
| src/apis/tests/smartsheet-api.test.ts | New tests for HTTPS enforcement and token/query/baseURL leakage prevention. |
| package.json | Update engines/deps/devDeps; add Jest typings. |
| jest.config.js | Disable ts-jest diagnostics. |
| .gitignore | Ignore Claude plans directory. |
| .github/workflows/release.yml | Pin actions to SHAs, bump Node version, run tests during release. |
| .github/workflows/ci.yml | New CI workflow running lint/typecheck/build/test. |
| .eslintrc.json | Add ESLint configuration for TypeScript. |
Comments suppressed due to low confidence (1)
package.json:72
@types/jestis^30.0.0whilejestis^29.5.0. This major-version mismatch can introduce incompatible typings and typecheck failures. Align@types/jestto the same major asjest(or upgrade Jest to match).
"@types/jest": "^30.0.0",
"@types/node": "^22.13.10",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
"eslint": "^8.57.0",
"husky": "^8.0.3",
"jest": "^29.5.0",
"lint-staged": "^15.2.0",
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| throw new Error('SMARTSHEET_ENDPOINT environment variable is not set'); | ||
| } | ||
|
|
||
| if (!this.baseUrl.startsWith('https://')) { |
There was a problem hiding this comment.
The HTTPS enforcement uses a case-sensitive startsWith('https://') check. Valid HTTPS URLs with an uppercase or mixed-case scheme (which are still valid per URL parsing) will be rejected. Consider validating with new URL(baseUrl) and checking url.protocol === 'https:' instead; it’s more robust and avoids rejecting otherwise-valid configuration.
| if (!this.baseUrl.startsWith('https://')) { | |
| let parsedUrl: URL; | |
| try { | |
| parsedUrl = new URL(this.baseUrl); | |
| } catch { | |
| throw new Error('SMARTSHEET_ENDPOINT is not a valid URL'); | |
| } | |
| if (parsedUrl.protocol !== 'https:') { |
| "engines": { | ||
| "node": ">=16.0.0", | ||
| "npm": ">=7.0.0" | ||
| "node": ">=25.8.2", |
There was a problem hiding this comment.
The engines field now requires Node >=25.8.2, which is a breaking change for consumers and may also be stricter than your CI configuration (workflows currently use node-version: 25). Consider either relaxing the engine constraint (e.g., >=25) or pinning CI to 25.8.2 (or higher) so installs don’t fail due to an engines mismatch.
| "node": ">=25.8.2", | |
| "node": ">=25", |
| uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6 | ||
| with: | ||
| node-version: 22 | ||
| node-version: 25 |
There was a problem hiding this comment.
This workflow uses node-version: 25, but package.json requires Node >=25.8.2. If setup-node resolves to an earlier 25.x release, installs can fail due to the engines check. Consider pinning the workflow to 25.8.2 (or higher) or relaxing the engine requirement.
| node-version: 25 | |
| node-version: 25.8.2 |
| - name: Setup Node.js | ||
| uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6 | ||
| with: | ||
| node-version: 25 |
There was a problem hiding this comment.
This workflow uses node-version: 25, but package.json requires Node >=25.8.2. If setup-node installs an earlier 25.x version, npm ci may fail because of the engines constraint. Pin to 25.8.2 (or higher) or relax the engine requirement to match CI.
| node-version: 25 | |
| node-version: 25.8.2 |
Pull Request
Description
Related Issue
Type of Change
How Has This Been Tested?
Checklist