feat: add tool surface filtering via env vars#17
Open
alex-feel wants to merge 1 commit into
Open
Conversation
Add startup-time tool surface filtering controlled by two optional environment variables: PEOPLEFORCE_ENABLED_TOOLS (allowlist) and PEOPLEFORCE_DISABLED_TOOLS (denylist). Both accept comma-separated, case-insensitive tool names with the peopleforce_ prefix optional. When unset, all 28 tools remain exposed (no behavior change). The filter pipeline applies allow-then-deny composition: tools listed in the allowlist form a candidate set (or all tools when unset), then the denylist subtracts from that set. Unknown tokens log a WARN to stderr and are ignored; an empty result fail-fasts with process.exit(1) and an actionable error. Both ListToolsRequestSchema and CallToolRequestSchema handlers consult the same filtered exposedTools array, so a disabled tool can be neither listed nor invoked. This structurally mitigates the CVE-2026-46519 / CWE-863 failure mode where filtering applied only at tools/list left tools/call open. Add five stdio smoke tests covering denylist removal, allowlist narrowing, allow+deny composition with prefix-less and case-insensitive tokens, WARN-and-continue on unknown deny tokens, and the zero-exposed exit-1 guard. Update README.md with a new "Restricting the tool surface" section, .env.example with the two new variables, CHANGELOG.md under Unreleased, CONTRIBUTING.md to note that new tools automatically participate in filtering with no code change required, and SECURITY.md to recommend denylisting peopleforce_api_request in least-privilege deployments. Bump package.json description tool count from 27 to 28 to match the actual exposed surface.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Add startup-time tool surface filtering controlled by two optional environment variables: PEOPLEFORCE_ENABLED_TOOLS (allowlist) and PEOPLEFORCE_DISABLED_TOOLS (denylist). Both accept comma-separated, case-insensitive tool names with the peopleforce_ prefix optional. When unset, all 28 tools remain exposed (no behavior change).
The filter pipeline applies allow-then-deny composition: tools listed in the allowlist form a candidate set (or all tools when unset), then the denylist subtracts from that set. Unknown tokens log a WARN to stderr and are ignored; an empty result fail-fasts with process.exit(1) and an actionable error.
Both ListToolsRequestSchema and CallToolRequestSchema handlers consult the same filtered exposedTools array, so a disabled tool can be neither listed nor invoked. This structurally mitigates the CVE-2026-46519 / CWE-863 failure mode where filtering applied only at tools/list left tools/call open.
Add five stdio smoke tests covering denylist removal, allowlist narrowing, allow+deny composition with prefix-less and case-insensitive tokens, WARN-and-continue on unknown deny tokens, and the zero-exposed exit-1 guard.
Update README.md with a new "Restricting the tool surface" section, .env.example with the two new variables, CHANGELOG.md under Unreleased, CONTRIBUTING.md to note that new tools automatically participate in filtering with no code change required, and SECURITY.md to recommend denylisting peopleforce_api_request in least-privilege deployments. Bump package.json description tool count from 27 to 28 to match the actual exposed surface.
Type of change
Checklist
npm run typecheckpasses locallynpm testpasses locally (all 9+ tests)npm run buildproduces a validdist/index.jsnpm run lintpasses (or has no new warnings introduced)test/server.test.ts)CHANGELOG.mdupdated under## [Unreleased]