Mostly safe — a couple of notes worth reading.
Scanned 5/3/2026, 6:18:11 PM·Cached result·Fast Scan·45 rules·How we decide ↗
AIVSS Score
Low
Severity Breakdown
0
critical
0
high
21
medium
0
low
MCP Server Information
Findings
This package receives a B grade with a safety score of 72/100 and carries moderate risk due to 21 medium-severity findings, primarily 19 instances of ANSI escape injection vulnerabilities that could allow attackers to manipulate terminal output or inject malicious content. While no critical or high-severity issues were detected, the prevalence of injection flaws combined with one resource exhaustion and one server configuration issue suggests you should review the specific contexts where this package handles user input or terminal interactions before deployment.
No known CVEs found for this package or its dependencies.
Scan Details
Want deeper analysis?
Fast scan found 21 findings using rule-based analysis. Upgrade for LLM consensus across 5 judges, AI-generated remediation, and cross-file taint analysis.
Building your own MCP server?
Same rules, same LLM judges, same grade. Private scans stay isolated to your account and never appear in the public registry. Required for code your team hasn’t shipped yet.
21 of 21 findings
21 findings
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 89 | }, |
| 90 | |
| 91 | getPrompt: async (request: GetPromptRequest): Promise<GetPromptResult> => { |
| 92 | console.error("Received GetPromptRequest:", request); |
| 93 | |
| 94 | // Block non-read prompts in read-only mode |
| 95 | if (isReadOnlyMode && !READ_ONLY_PROMPTS.includes(request.params.name)) { |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 953 | console.log(`Task 1 Notes: ${tasks[0].notes}`); |
| 954 | } |
| 955 | }, (error) => { |
| 956 | console.error(error.response.body); |
| 957 | }); |
| 958 | ``` |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 995 | let task = result.data; |
| 996 | console.log(task.name); |
| 997 | }, (error) => { |
| 998 | console.error(error.response.body); |
| 999 | }); |
| 1000 | ``` |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 135 | export function tool_handler(asanaClient: AsanaClientWrapper): (request: CallToolRequest) => Promise<CallToolResult> { |
| 136 | return async (request: CallToolRequest) => { |
| 137 | console.error("Received CallToolRequest:", request); |
| 138 | try { |
| 139 | if (!request.params.arguments) { |
| 140 | throw new Error("No arguments provided"); |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 96 | tasksApiInstance.createTask(body, opts).then((result) => { |
| 97 | console.log('API called successfully. Returned data: ' + JSON.stringify(result.data, null, 2)); |
| 98 | }, (error) => { |
| 99 | console.error(error.response.body); |
| 100 | }); |
| 101 | ``` |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 1061 | let result = result.data; |
| 1062 | console.log(result); |
| 1063 | }, (error) => { |
| 1064 | console.error(error.response.body); |
| 1065 | }); |
| 1066 | ``` |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 366 | tasksApiInstance.getTasks(opts).then((result) => { |
| 367 | console.log(JSON.stringify(result.data, null, 2)); |
| 368 | }, (error) => { |
| 369 | console.error(error.response.body); |
| 370 | }); |
| 371 | ``` |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 121 | tasksApiInstance.updateTask(body, task_gid, opts).then((result) => { |
| 122 | console.log('API called successfully. Returned data: ' + JSON.stringify(result.data, null, 2)); |
| 123 | }, (error) => { |
| 124 | console.error(error.response.body); |
| 125 | }); |
| 126 | ``` |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 409 | tasksApiInstance.getTasks(opts).then((result) => { |
| 410 | console.log(JSON.stringify(result.data, null, 2)); |
| 411 | }, (error) => { |
| 412 | console.error(error.response.body); |
| 413 | }); |
| 414 | ``` |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 140 | tasksApiInstance.deleteTask(task_gid).then((result) => { |
| 141 | console.log('API called successfully. Returned data: ' + JSON.stringify(result.data, null, 2)); |
| 142 | }, (error) => { |
| 143 | console.error(error.response.body); |
| 144 | }); |
| 145 | ``` |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 827 | console.log(`taskName: ${taskName}`); |
| 828 | console.log(`taskNotes: ${taskNotes}`); |
| 829 | }, (error) => { |
| 830 | console.error(error.response.body); |
| 831 | }); |
| 832 | ``` |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 569 | } |
| 570 | return result; |
| 571 | }, (error) => { |
| 572 | console.error(error.response.body); |
| 573 | }); |
| 574 | // Do something with the tasks. EX: print out results |
| 575 | console.log('Tasks: ' + JSON.stringify(tasks, null, 2)); |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 49 | * Reads a resource (workspace details or project details) |
| 50 | */ |
| 51 | const readResource = async (request: ReadResourceRequest): Promise<ReadResourceResult> => { |
| 52 | console.error("Received ReadResourceRequest:", request); |
| 53 | try { |
| 54 | const { uri } = request.params; |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 685 | } |
| 686 | } |
| 687 | }, (error) => { |
| 688 | console.error(error.response.body); |
| 689 | }); |
| 690 | |
| 691 | ``` |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 1031 | let task = result.data; |
| 1032 | console.log(task.name); |
| 1033 | }, (error) => { |
| 1034 | console.error(error.response.body); |
| 1035 | }); |
| 1036 | ``` |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 915 | let task = result.data; |
| 916 | console.log(task.name); |
| 917 | }, (error) => { |
| 918 | console.error(error.response.body); |
| 919 | }); |
| 920 | ``` |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 34 | usersApiInstance.getUser(user_gid, opts).then((result) => { |
| 35 | console.log('API called successfully. Returned data: ' + JSON.stringify(result.data, null, 2)); |
| 36 | }, (error) => { |
| 37 | console.error(error.response.body); |
| 38 | }); |
| 39 | ``` |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 60 | tasksApiInstance.getTasks(opts).then((result) => { |
| 61 | console.log('API called successfully. Returned data: ' + JSON.stringify(result.data, null, 2)); |
| 62 | }, (error) => { |
| 63 | console.error(error.response.body); |
| 64 | }); |
| 65 | ``` |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 853 | console.log(task); |
| 854 | console.log(headers); |
| 855 | }, (error) => { |
| 856 | console.error(error.response.body); |
| 857 | }); |
| 858 | ``` |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 96 | client.tasks |
| 97 | .findAll({ limit: 50, project: "1199684513975168" }) |
| 98 | .then((collection) => { |
| 99 | collection.fetch(200).then((tasks) => { |
| 100 | console.log(tasks); |
| 101 | }); |
| 102 | }); |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Package declares an install-time hook (npm postinstall/preinstall/prepare, setup.py cmdclass override, custom setuptools install class, or non-default pyproject build-backend). Anyone installing this package runs the hook. Confirm the hook is necessary and review its contents; prefer shipping a plain library without install-time execution.
Evidence
| 21 | ], |
| 22 | "scripts": { |
| 23 | "build": "node build.js", |
| 24 | "prepare": "npm run build", |
| 25 | "start": "node dist/index.js", |
| 26 | "dev": "NODE_ENV=development NODE_OPTIONS='--loader ts-node/esm' node --experimental-specifier-resolution=node src/index.ts", |
| 27 | "watch": "tsc -w", |
Remediation
Prefer libraries that do not require install-time code execution: - Drop `postinstall`/`preinstall`/`prepare` scripts if the work can happen at runtime or build-time instead. - Ship pre-built native binaries rather than compiling via a custom `cmdclass` or `build_ext` override. - For Dockerfiles: replace `RUN curl … | sh` with a pinned download + checksum verification + explicit `RUN` of a named script. - If the hook is unavoidable, document exactly what it does so downstream reviewers