# Reported issues for codecalc

Pod holds 14 of 14 problems reported by people outside the maintainer team. Issues filed by the project's own owners, members and collaborators are excluded entirely — a maintainer's release checklist is not a warning to a prospective user.

Back to [codecalc](/mcp/codecalc).

## Most discussed

### security (low): session_files stats through symlinks that session_read_file refuses, leaking size/existence of paths outside the workspace

**Environment:** codecalc 0.3.1 from PyPI, macOS arm64, contract 1.2.0. Low severity — an existence/size oracle, not a read.

`session_read_file` and the `codecalc://session/<id>/files/<path>` resource both resolve symlinks before deciding, and both correctly refuse one that points outside the workspace. `session_files` does not: it stats through the link and publishes the target's size.

```python
session_start(language="python")
session_write_file(path="mk.py", content='import os; os.symlink("

[Read the thread](https://github.com/The-40-Thieves/codecalc/issues/208) · 2026-08-20 · closed · external user · 0 comments

### bug: argument rejections across 7 tools return code `internal` and tell the caller to report a defect

**Environment:** codecalc 0.3.1 from PyPI (`uv tool install 'codecalc[full]'`), macOS arm64, Python 3.14.0, backend `rust`, contract 1.2.0.

Every one of these is a **rejected argument**, and every one of them comes back telling the caller that codecalc is broken and to report it verbatim:

| call | `error` | `code` |
|---|---|---|
| `percentage(part="50", total="0")` | `total is zero` | `internal` |
| `percentiles(nums=[])` | `need at least 1 number` | `internal` |
| `calc_stats(nums=[5])` | `n

[Read the thread](https://github.com/The-40-Thieves/codecalc/issues/196) · 2026-08-20 · closed · external user · 1 comment

### enhancement: Improved Installation UX

# Installation UX - assessment and suggestions

This enhancement is more of a nice-to-have than a need, primarily taking into account average user experience with a forward-looking perspective - when the project is noticed and gains in popularity a smoother install/setup experience makes life a tad bit easier for maintainers as well as end users.

## High-Leverage Improvements

> I suggest splitting these into separate PRs, but a few of them can be grouped.
> - **Installation UX & Onboarding: It

[Read the thread](https://github.com/The-40-Thieves/codecalc/issues/88) · 2026-08-09 · closed · external user · 3 comments

### security: `update_runtimes(apply=True)` invokes sudo with no operator confirmation gate

## what is reachable

`update_runtimes` is an `@mcp.tool()` (server.py:394), so any model connected to
the server can call it. With `apply=True` the manager commands run as a
subprocess from the server process, runtimes.py:436:

```python
run = _run(cmd, timeout=timeout)
```

One of those commands is elevated, runtimes.py:298:

```python
UPDATE_COMMANDS: dict[str, list[str]] = {
    "mise": ["mise", "up"],
    "rustup": ["rustup", "update"],
    "swiftly": ["swiftly", "update"],
    "apt": ["sud

[Read the thread](https://github.com/The-40-Thieves/codecalc/issues/63) · 2026-08-09 · closed · external user · 0 comments

### security: `execute_code_stream` cannot apply the memory or CPU ceilings `execute_code` declares

## what differs

`execute_code` (server.py:102) takes four ceilings and forwards all of them:

```python
def execute_code(language, code, stdin="", timeout=10, session_id=None,
                 max_memory_mb=0, max_output_kb=0, max_cpu=0, no_net=False,
                 compact=False):
    timeout = min(timeout, 120)
```

`execute_code_stream` (server.py:212) takes two:

```python
async def execute_code_stream(language, code, stdin="", timeout=30,
                              max_output_kb=0, no

[Read the thread](https://github.com/The-40-Thieves/codecalc/issues/61) · 2026-08-09 · closed · external user · 0 comments

### bug: non-finite and deeply nested inputs escape as unhandled exceptions

## Problem

Several tools convert incoming numbers with `Fraction()` or `int()` without screening for non-finite values, so a `nan` or `inf` in the input raises out of the tool instead of returning `{"ok": False, "error": ...}`.

Per [codecalc/mcp_middleware.py#L98-L102](https://github.com/The-40-Thieves/codecalc/blob/e26fa15ba403f3d7599938bdca42ad163294895a/codecalc/mcp_middleware.py#L98-L102), any exception other than `MCPError` is flattened by the dispatcher to "Internal server error" with no

[Read the thread](https://github.com/The-40-Thieves/codecalc/issues/36) · 2026-08-09 · closed · external user · 0 comments

### bug: calc_exact has no bound on exponentiation and leaks ValueError to the caller

## Problem

`calc_exact` evaluates `**` with no bound on the operand or result size, and is not covered by the response-deadline table.

Relevant code:
- [codecalc/exact.py#L72-L91](https://github.com/The-40-Thieves/codecalc/blob/e26fa15ba403f3d7599938bdca42ad163294895a/codecalc/exact.py#L72-L91) - `_int_op` handles `**` with no magnitude guard
- [codecalc/exact.py#L156](https://github.com/The-40-Thieves/codecalc/blob/e26fa15ba403f3d7599938bdca42ad163294895a/codecalc/exact.py#L156) - `eval_exact

[Read the thread](https://github.com/The-40-Thieves/codecalc/issues/32) · 2026-08-09 · closed · external user · 0 comments

### security: sandbox package installation before exposing install_package

## Problem

`install_package` launches package managers directly from the MCP server process. The working directory is scoped to a session, but the installer process itself is not confined.

Relevant code:
- [codecalc/packages.py#L33-L36](https://github.com/The-40-Thieves/codecalc/blob/e26fa15ba403f3d7599938bdca42ad163294895a/codecalc/packages.py#L33-L36)
- [codecalc/packages.py#L115-L123](https://github.com/The-40-Thieves/codecalc/blob/e26fa15ba403f3d7599938bdca42ad163294895a/codecalc/packages.

[Read the thread](https://github.com/The-40-Thieves/codecalc/issues/23) · 2026-08-09 · closed · outside contributor · 2 comments

## Most recent

### gap: matrices are unreachable — the RCE screen denies `[` at token level, so list literals fall with subscript access

**Environment:** codecalc 0.3.1 from PyPI, macOS arm64, `[full]` (sympy 1.14.0 present).

Not a feature request — the capability is already reachable through the tools you ship, and one line of the RCE screen removes it as a side effect. Worth separating those two things.

**Everything else in SymPy's surface works through `evaluate_expression`:**

```
diff(x**2, x)              -> 2*x
integrate(x**2, x)         -> x**3/3
series(sin(x), x, 0, 5)    -> x - x**3/6 + O(x**5)
expand((x+1)**3)       

[Read the thread](https://github.com/The-40-Thieves/codecalc/issues/223) · 2026-08-21 · closed · external user · 0 comments

### contract: workspace-guard refusals bypass the result contract (no ok/code/remedy), and pydantic errors echo caller arguments unredacted

**Environment:** codecalc 0.3.1 from PyPI, macOS arm64, contract 1.2.0.

Refusals leave the server by two different doors, and only one of them is the contract the README documents.

**Door 1 — the contract**, which is the good one:

```json
{"ok": false, "error": "...", "code": "validation",
 "remedy": "fix the arguments and retry; the message names the field",
 "contract_version": "1.2.0"}
```

**Door 2 — an MCP protocol error**, `isError: true`, no `ok`, no `code`, no `remedy`, no `contract_v

[Read the thread](https://github.com/The-40-Thieves/codecalc/issues/212) · 2026-08-20 · closed · external user · 0 comments

### security: serve-http's DNS-rebinding protection is inherited from an SDK default, and codecalc's own loopback allowlist is wider than the one that enables it

**Environment:** codecalc 0.3.1 from PyPI, `mcp` 2.0.0, macOS arm64.

I went looking for a DNS-rebinding hole in `serve-http` and did **not** find one on the documented default. It is worth saying why, because the protection is not yours — it is inherited from an SDK default that your own bind policy can step outside of.

**Verified holding on `--host 127.0.0.1`** (live, no token set):

```
POST /mcp  Origin: https://evil.example              -> 403 Invalid Origin header
POST /mcp  Host: attacke

[Read the thread](https://github.com/The-40-Thieves/codecalc/issues/211) · 2026-08-20 · closed · external user · 0 comments

### UX: `codecalc --help` and `--version` print nothing and exit 0 (they start the MCP server instead)

**Environment:** codecalc 0.3.1 from PyPI, macOS arm64, Python 3.14.0.

```
$ codecalc --help </dev/null   ; echo "exit=$?"
exit=0
$ codecalc --version </dev/null ; echo "exit=$?"
exit=0
```

No output, on either stream, exit 0. From a terminal without the redirect it hangs instead, because what actually happened is that the stdio MCP server started and waited for a client.

`server.main()` inspects `argv` for `doctor`, `--check`, `--check-install`, `serve-strict` and `serve-http`, and ignores e

[Read the thread](https://github.com/The-40-Thieves/codecalc/issues/201) · 2026-08-20 · closed · external user · 0 comments

### security: extend the guarded-evaluation bound to the remaining SymPy entry points

Follow-up to #78, which put `evaluate_expression` behind a killable child. Filed explicitly rather than left in a commit message, because the remainder is most of the surface.

## What is guarded, and what is not

| function | file | guarded? |
|---|---|---|
| `evaluate_expression` | logic.py | **yes** (#78) |
| `solve_linear` | logic.py | no |
| `simplify_expression` | exact.py | no |
| `solve_expression` | exact.py | no |
| `limit_expression` | exact.py | no |
| `algebraic_equiv` | exact.py | 

[Read the thread](https://github.com/The-40-Thieves/codecalc/issues/84) · 2026-08-09 · closed · outside contributor · 0 comments

### security: run SymPy where it can be killed, rather than trusting a pre-screen

The remaining piece of #67. Filed late — the #76 commit body said this was "filed separately" when it was not; that is corrected here rather than left to read as done.

## Why a screen is not the end state

#76 bounds the shapes **known** to explode (power towers, symbolic exponents, oversized arguments to heavy functions) and #77 documents that `safe_expr.py` screens for reach. Both are denylists, and a denylist is a bet that the list is complete.

Upstream has already made and lost that bet. S

[Read the thread](https://github.com/The-40-Thieves/codecalc/issues/78) · 2026-08-09 · closed · outside contributor · 0 comments

The remaining reports are on [the project's issue tracker](https://github.com/The-40-Thieves/codecalc/issues).
