View on GitHub

Matimo - AI Tools Ecosystem

Define tools once in YAML, use them everywhere

Download this project as a .zip file Download this project as a tar.gz file

Matimo — Full-Repository Security & Safety Audit

Date: 2026-04-10

This document summarizes a repository-wide static scan and manual review of Matimo’s codebase, the results, evidence links, exploit likelihood/impact, and prioritized remediation recommendations. It was produced by running heuristic searches for dangerous patterns across the entire workspace and inspecting the core runtime modules (executors, mcp, policy, approval manifest, matimo-instance, skill-loader).


Scope & Methodology

Note: this is a static review, not a formal programmatic SAST scan nor runtime fuzzing. Heuristic search can miss obfuscated or generated code; dynamic analysis is recommended as a follow-up.


Was the scan run on the entire project or just partial?

Answer: The scan was run repository-wide using broad regex heuristics against every file in the workspace and then focused manual inspections were performed on the most sensitive modules. That means:

Limitations: heuristic/static grep is not a proof of exploitability. Some threats require environment-specific runtime tests, dynamic analysis, or manual threat modeling of deployment scenarios.


Key Findings (summary)

  1. Embedded-code RCE risk (FunctionExecutor) — critical
    • Location: typescript/packages/core/src/executors/function-executor.ts
    • Symptom: The executor supports executing embedded code via new Function(...) when MATIMO_ALLOW_EMBEDDED_CODE=true. Embedded code has access to fs, path, axios, and can run arbitrary JS.
    • Impact: Remote code execution and secrets exfiltration if untrusted YAML/tool definitions are accepted.
    • Likelihood: Medium (feature is opt-in by env, but docs and examples show how it can be enabled).
  2. Global environment seeding of resolved secrets (MCPServer.seedEnvironmentSecrets) — high
    • Location: typescript/packages/core/src/mcp/mcp-server.ts
    • Symptom: Resolved auth placeholders are written into process.env (and MATIMO_ prefixed vars), making secrets globally available to the running process and any child processes.
    • Impact: Secrets leakage across unrelated modules and child processes; harder to implement least-privilege and secret lifecycle management.
    • Likelihood: High (this runs during MCP server start).
  3. Approval manifest ephemeral secret fallback (ApprovalManifest) — medium
    • Location: typescript/packages/core/src/policy/approval-manifest.ts
    • Symptom: If MATIMO_APPROVAL_SECRET is not set, an ephemeral UUID is generated and used; approvals are HMAC-signed but ephemeral, and in some modes (stdio) logging is silent so users may not realize approvals are ephemeral.
    • Impact: Approvals may appear to succeed but will be invalid after restart; in stdio mode there’s little visibility to warn operators.
    • Likelihood: High (common in local/dev without configured env).
  4. Templated command injection surface (CommandExecutor.templateString) — high
    • Location: typescript/packages/core/src/executors/command-executor.ts
    • Symptom: execution.command and args are string-templated with {param} placeholders. The command itself is templated and then passed directly to spawn(), enabling arbitrary executable injection or argument injection if untrusted values are placed into placeholders.
    • Impact: Arbitrary command execution on the host.
    • Likelihood: Low→Medium (depends on tool YAML, but non-negligible for agent-generated tools).
  5. Templating regex & replacement correctness (multiple executors) — medium
    • Location: templateString() and related functions in HttpExecutor and CommandExecutor.
    • Symptom: Placeholder replacement uses new RegExp(placeholder, 'g') without escaping placeholder and uses String(value) replacement; unescaped placeholder characters can create incorrect regexes and replacement semantics (also $ in replacement text has special meaning in String.replace with regex replacements). This can cause unexpected substitutions or runtime exceptions.
    • Impact: subtle template-bypass, errors, or malformed commands/requests.
    • Likelihood: Medium.
  6. Documentation contains dangerous examples — informational risk
    • Location: SECURITY.md and various docs (examples that call execSync with user input, eval, new Function). See SECURITY.md.
    • Symptom: Tutorials and examples include both unsafe and safe variants; unsafe examples may be copied by users.
    • Impact: Developer confusion; accidental unsafe deployments.
  7. Wide use of process.env for secrets and token lifecycle in multiple places — design risk
    • Locations: many docs and packages (OAuth docs, token injection, MCP docs). Examples: docs/architecture/OAUTH.md, various provider READMEs.
    • Symptom: Secrets are frequently read from / written to process.env (including some code paths that assign tokens back into process.env). This pattern increases coupling between secret resolution and global state.
    • Impact: Harder enforcement of least-privilege and secret scoping; risk of accidental leakage to child processes.
  8. Policy defences are conservative but rely on correct initialization and operator awareness — partial mitigation

Evidence / Where matches were found (representative)

Note: many other hits were found across docs, tests, examples, and provider packages where process.env is referenced; these are expected usage points for configured secrets but amplify the importance of scoping secrets carefully.


  1. Disable or block embedded code execution unless the tool is trusted and pre-approved.
    • Change: In FunctionExecutor, refuse to execute embedded code unless the tool’s definition is from a trusted path or has an explicit approval record in the approval manifest. (Remove or make MATIMO_ALLOW_EMBEDDED_CODE ineffective for untrusted tools.)
    • Why: Prevents an opt-in flag from becoming an RCE vector when untrusted definitions are accepted.
  2. Stop seeding resolved secrets into global process.env.
    • Change: Modify MCPServer.seedEnvironmentSecrets() to return a Map<string,string> or pass a secrets object into MatimoInstance and keep all lookups in-memory. Do NOT write secrets to process.env by default. If process.env writes are needed for compatibility, make it opt-in and scoped to child process env only (per-spawn) and ephemeral.
    • Why: Prevents global leakage of secrets to unrelated modules and child processes.
  3. Fail fast in production for missing approval secret.
    • Change: In ApprovalManifest constructor, if NODE_ENV === 'production' and no approvalSecret provided (or env var), throw and refuse to start. Also surface a clear abort/error in stdio mode where logging might be silent.
  4. Disallow placeholders in execution.command.
    • Change: Only allow templating in args; require command to be a fixed executable path/name (no {...} placeholders). Validate during tool-load time and reject untrusted tools that violate this.
  5. Escape placeholders during template replacement.
    • Change: Replace new RegExp(placeholder, 'g') with a safe .split(placeholder).join(String(value)) or escape regex metacharacters before constructing RegExp, and ensure String.replace does not treat $ specially.

Medium-term (P1) Recommendations


Quick Patches I Can Apply Now

Pick one or more and I will implement and run tests locally:


Suggested Tests & CI Additions


Patches Applied in v0.1.0-alpha.14

All four recommended patches (A, B, C, D) have been implemented and deployed across both TypeScript and Python SDKs. Tests pass (1884 TS + 649 Python), and CodeQL violations are resolved.

Patch A — Stop seeding secrets into process.env (TS only)

Status: ✅ Applied

File: typescript/packages/core/src/mcp/mcp-server.ts

Changes:

Why Python is unaffected: Python’s MCP server was designed correctly from the start — it resolves secrets on-demand per tool call and passes them directly as credentials=, never touching os.environ.

Impact: Secrets no longer leak into other modules or child processes spawned by unrelated code in the same Node.js process.

Patch B — Block {placeholders} in command field (TS + Python)

Status: ✅ Applied

Files:

Changes:

Example:

# BEFORE (vulnerable): could inject arbitrary commands
command: "post-to-{platform}"  # ← now blocked
args: ["--data", "{data}"]

# AFTER (correct)
command: "post-to-slack"  # ← fixed executable
args: ["--platform", "{platform}", "--data", "{data}"]

Impact: Prevents command injection vector even if untrusted values are passed in params.

Patch C — Production fail-fast without MATIMO_APPROVAL_SECRET (TS + Python)

Status: ✅ Applied

Files:

Changes:

Impact: Prevents silent false security guarantees in production. Operators will discover missing secret at bootstrap time, not during a restart that invalidates all approvals.

Patch D — Hardened embedded code execution (TS) + path traversal protection (Python)

Status: ✅ Applied

TypeScript (typescript/packages/core/src/executors/function-executor.ts):

Python (python/packages/core/src/matimo/executors/function_executor.py):

Impact: Embedded code regains legitimate use (pure computation) while blocking dangerous patterns. File-based function tools receive full SDK capability but with auditability via HMAC integrity tracking.

CodeQL Violations Fixed

  1. Workflow permissions: Added explicit permissions: {} (deny-all default) + per-job declarations
    • Files: .github/workflows/ci.yml, .github/workflows/publish-python.yml, .github/workflows/test-python.yml
  2. Clear-text API key logging: Removed prompt echoing containing server-prefix derived from API key
    • File: typescript/examples/tools/mailchimp/mailchimp-langchain.ts
  3. Polynomial regex vulnerability: Added length limit before regex test
    • File: typescript/packages/core/src/executors/command-executor.ts
    • Pattern: Commands must be ≤1024 chars (well within normal bounds for executables)

Test Results

Breaking Changes

Minimal — no shipped provider tools affected:


  1. Deploy alpha.14 with patches applied and verified
  2. Add runtime security tests and fuzzing for executor flows
  3. Schedule follow-up pentest for live MCP server scenarios
  4. Consider formal SAST/DAST scanning in CI pipeline

Report generated by the review process; file saved at: docs/reviews/MATIMO_FULL_REPO_SECURITY_AUDIT.md