molecule-core/workspace/adapters/smolagents/safe_env.py
Hongming Wang 479a027e4b chore: open-source restructure — rename dirs, remove internal files, scrub secrets
Renames:
- platform/ → workspace-server/ (Go module path stays as "platform" for
  external dep compat — will update after plugin module republish)
- workspace-template/ → workspace/

Removed (moved to separate repos or deleted):
- PLAN.md — internal roadmap (move to private project board)
- HANDOFF.md, AGENTS.md — one-time internal session docs
- .claude/ — gitignored entirely (local agent config)
- infra/cloudflare-worker/ → Molecule-AI/molecule-tenant-proxy
- org-templates/molecule-dev/ → standalone template repo
- .mcp-eval/ → molecule-mcp-server repo
- test-results/ — ephemeral, gitignored

Security scrubbing:
- Cloudflare account/zone/KV IDs → placeholders
- Real EC2 IPs → <EC2_IP> in all docs
- CF token prefix, Neon project ID, Fly app names → redacted
- Langfuse dev credentials → parameterized
- Personal runner username/machine name → generic

Community files:
- CONTRIBUTING.md — build, test, branch conventions
- CODE_OF_CONDUCT.md — Contributor Covenant 2.1

All Dockerfiles, CI workflows, docker-compose, railway.toml, render.yaml,
README, CLAUDE.md updated for new directory names.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-18 00:24:44 -07:00

62 lines
1.7 KiB
Python

"""Denylist-based environment sanitization for smolagents (issue #826 — C3 CRITICAL).
This module provides a simple denylist approach: well-known secret variable
names plus ``*_API_KEY`` and ``*_TOKEN`` suffix patterns are stripped before
env is passed to agent-executed code.
For a stricter allowlist-based alternative that only passes explicitly-safe
variables through, see :mod:`adapters.smolagents.env_sanitize`.
Usage::
from adapters.smolagents.safe_env import make_safe_env
executor = LocalPythonExecutor(...)
# Pass only the sanitised env to the subprocess / exec context:
safe = make_safe_env()
"""
import copy
import os
# Named API keys and tokens known to be used by smolagents / LLM clients.
# These are removed regardless of the suffix-pattern below.
SMOLAGENTS_ENV_DENYLIST: frozenset = frozenset(
{
"OPENAI_API_KEY",
"ANTHROPIC_API_KEY",
"GROQ_API_KEY",
"CEREBRAS_API_KEY",
"QIANFAN_API_KEY",
"LANGFUSE_SECRET_KEY",
"LANGFUSE_PUBLIC_KEY",
"HF_TOKEN",
}
)
def make_safe_env() -> dict:
"""Return a sanitised copy of ``os.environ`` with secrets removed.
Removes any key that:
- Is in :data:`SMOLAGENTS_ENV_DENYLIST`, OR
- Ends with ``_API_KEY``, OR
- Ends with ``_TOKEN``
``os.environ`` is **never mutated** — a fresh ``dict`` copy is returned.
Returns
-------
dict
A copy of the current environment with secret keys removed.
"""
env = copy.copy(dict(os.environ))
for key in list(env.keys()):
if (
key in SMOLAGENTS_ENV_DENYLIST
or key.endswith("_API_KEY")
or key.endswith("_TOKEN")
):
del env[key]
return env