PRAISONAI_ALLOW_LOCAL_TOOLS; without it, dangerous local tools stay blocked by default.
Quick Start
1
Simple Usage
Enable local
tools.py loading before starting an agent:2
With Configuration
Enable job workflows and remote browser access when required:
How It Works
Environment Variables
PRAISONAI_TOOL_SAFETY
Controls whether dangerous built-in tools (shell exec, file delete/move/copy, code execution) are gated by the approval system. Default: unset →default preset active (blocks destructive ops in CI, asks on TTY)
--dangerously-skip-approval on praisonai code automatically exports PRAISONAI_TOOL_SAFETY=off so that child processes inherit the bypass.PRAISONAI_ALLOW_LOCAL_TOOLS
Controls automatic loading oftools.py files from the current working directory.
Security Risk: Remote Code Execution (RCE) via malicious tools.py files
83b8b14c):
praisonaiwrapper agent generator (generate_crew_and_kickoffand_run_praisonai), now delegating toToolResolver.get_local_callables()/ToolResolver.get_local_tool_classes()praisonai.tool_resolver.ToolResolver._load_local_tools(single source of truth; the env-var gate itself is enforced bypraisonai._safe_loader.load_user_module)praisonai runYAML workflows (recipetools.pyunder_run_yaml_workflow)praisonai research --tools <file.py>praisonai chat --rewrite-tools <file.py>and--expand-tools <file.py>- Generic CLI
_load_tools(tools_path) - HTTP API:
praisonai.api.call.import_tools_from_file(raisesValueErrorif disabled) - Path-traversal guard: files outside the current working directory are refused even when
PRAISONAI_ALLOW_LOCAL_TOOLS=true praisonaiagents.workflows.workflows.AgentFlow(SDK-level: skipstools.pynext to the workflow class when unset)
Even when
PRAISONAI_ALLOW_LOCAL_TOOLS=true, the loader refuses any path outside the current working directory. This is a deliberate defence-in-depth layer for HTTP-API callers (praisonai.api.call.import_tools_from_file) where the path can come from network input. Move the tools.py you want to load into your CWD if you hit Refusing to exec ... outside working directory. in the logs.PRAISONAI_ALLOW_LOCAL_TOOLS accepts only true (case-insensitive) in the wrapper (praisonai). Values like 1, yes, or on are not truthy for the wrapper (unlike PRAISONAI_ALLOW_TEMPLATE_TOOLS).
Truthy-value inconsistency across surfaces: The wrapper (
praisonai) accepts only true; the SDK’s AgentFlow (praisonaiagents.workflows.workflows) accepts true, 1, or yes; the SDK’s recipe path in workflows.py accepts true, 1, yes, or on. If you rely on PRAISONAI_ALLOW_LOCAL_TOOLS=1, the wrapper will reject it even though the SDK’s AgentFlow will accept it. This is the SDK’s actual behavior — set true to be safe across all surfaces.PRAISONAI_ALLOW_TEMPLATE_TOOLS
Controls implicittools.py autoload by the template tool-override system, both from the current working directory and from a recipe’s template directory.
Security Risk: Remote Code Execution (RCE) when loading recipes/templates from untrusted sources (e.g. recipes fetched from a remote registry)
Accepted truthy values:
1, true, yes, on (case-insensitive, whitespace-stripped)
Affected Components:
praisonai.templates.tool_override.create_tool_registry_with_overridespraisonai.templates.tool_override.resolve_tools
override_files, override_dirs, and tools_sources continue to work without this opt-in and are the recommended way to load custom tools.
PRAISONAI_ALLOW_TEMPLATE_TOOLS and PRAISONAI_ALLOW_LOCAL_TOOLS are intentionally distinct gates — the wrapper keeps its own template/CWD tools.py autoload (with PRAISONAI_ALLOW_TEMPLATE_TOOLS) even though the canonical resolver now owns praisonai-tools discovery (PraisonAI#3122). Reason: the wrapper gate is skip-on-error and allows an explicit template directory outside the CWD, which the canonical PRAISONAI_ALLOW_LOCAL_TOOLS + CWD-boundary gate does not. Set the one that matches your load path — set both if a recipe ships a tools.py in a template directory and you also depend on the canonical loader.PRAISONAI_AUTH_CONTENT
Loads the entire credential store from a JSON environment variable, bypassing disk I/O entirely (zero-disk mode). Intended for ephemeral containers/CI where OAuth tokens and API keys must not be persisted. Security value: secret hygiene — not an RCE gate. It reduces on-disk secret sprawl. The env var itself must be treated as a secret; inject it only from a secrets manager, never commit it, and prefer a CI runtime that scrubs env vars from build logs.~/.praisonai/credentials.json is used (unchanged behaviour).
Value shape: a JSON object mapping provider → credential object (not 1/true). Each credential mirrors ProviderCredential — api_key + auth_method for API keys, plus access_token, refresh_token, expires_at for OAuth.
Affected Components (verified against PR #3775 head 52f33362):
praisonai_code.cli.configuration.credentials.CredentialStore—__init__(env-blob parsing),_read_credentials(returns the in-memory blob),_write_credentials(no-ops disk I/O; updates the in-memory store only), and theis_in_memorypropertypraisonai_code.cli.commands.auth.auth_list/auth_status— label theSourcecolumnenv (in-memory)when the store is in memory
Usage Example:
Precedence is env blob > disk file. Per-provider API-key env vars (
OPENAI_API_KEY, …) still win for that specific provider. See Auth → Zero-disk mode for the full reference.PRAISONAI_CONFIG_CONTENT
Supplies the entire user-config layer as an inline JSON/YAML blob parsed in memory. When set, PraisonAI never reads~/.praisonai/config.yaml or a walk-up praisonai.yaml project file — the direct sibling of PRAISONAI_AUTH_CONTENT for a fully zero-disk run in ephemeral containers/CI.
Security value: secret hygiene / stateless-run control — not an RCE gate. It keeps config.yaml (MCP server blocks, permissions arrays, model allowlists, hooks) off disk. Treat the env var itself as a secret: inject it from a secrets manager, never commit it, and only use it in CI runtimes that scrub env vars from build logs.
config.yaml. The value must be a mapping, not a list or scalar.
Interpolation: ${VAR}, {env:VAR}, and {file:...} directives still resolve — the blob composes with the same conventions as an on-disk file.
Precedence: occupies the same slot as discovered global/project files. Inline content wins over PRAISONAI_CONFIG (path). Per-key env vars (PRAISONAI_MODEL, …) and CLI flags still override it; managed policy is still enforced on top.
Validation / error paths (verified against PR #3983 head 382c6fd6):
Usage Example (auth + config in one env set):
Higher-precedence layers still win: per-key env vars (
PRAISONAI_MODEL, …) and CLI flags (--model) override any scalar the blob sets. Managed policy still layers below user config. See PRAISONAI_AUTH_CONTENT for the credential sibling, Env → Related Environment Variables, and Env Config Injection for the full reference and decision diagram.PRAISONAI_CONFIG
Names an explicit config file path to load as the user-config layer, replacing the discovered global + project files. Lower precedence thanPRAISONAI_CONFIG_CONTENT (inline wins). Useful when the config is materialised via a mounted secret (Docker/Kubernetes secret volume or Kubernetes ConfigMap) but you don’t want it discoverable via file walk-up.
UserWarning: "PRAISONAI_CONFIG points at '<path>', which could not be read as a config file; falling back to file discovery." and falls back to discovery. A non-mapping file body is skipped the same way.
When both
PRAISONAI_CONFIG_CONTENT and PRAISONAI_CONFIG are set, the inline content wins and this path is ignored (no warning, by design).praisonai config provenance) reports a layer of env-config for keys supplied this way — source is env:PRAISONAI_CONFIG_CONTENT for inline content, or the absolute file path for explicit-path mode.
PRAISONAI_ALLOW_PLUGIN_DISCOVERY
Controls automatic discovery and loading of plugins from.praisonai/plugins/ (project-level) and ~/.praisonai/plugins/ (user-level) directories.
Security Risk: Remote Code Execution (RCE) via malicious third-party plugins discovered on sys.path.
Accepted truthy values:
true, 1, yes (case-insensitive, whitespace-stripped). on is not accepted.
Affected Component: praisonaiagents.plugins.manager.PluginManager.discover_and_load_plugins
Default behavior when unset: discover_and_load_plugins() is a no-op and returns 0. A logger.debug message fires: Plugin auto-discovery disabled; set PRAISONAI_ALLOW_PLUGIN_DISCOVERY=true.
Usage Example:
PRAISONAI_NO_PLUGINS
Suppresses external-plugin discovery for the current process — the inverse ofPRAISONAI_ALLOW_PLUGIN_DISCOVERY. Use for clean, deterministic baselines while debugging or in CI.
Security value: reproduces a known-clean run when triaging whether a hook-injecting plugin is influencing behaviour. Does not change persisted .praisonai/config.yaml state.
Accepted truthy values:
true, 1, yes (case-insensitive, whitespace-stripped). on is not accepted.
Affected Component: praisonaiagents.plugins.manager.PluginManager.discover_entry_points and .auto_discover_plugins — both short-circuit to 0 when the var is truthy or the constructor was called with disabled=True.
Precedence: PluginManager(disabled=True|False) constructor param > PRAISONAI_NO_PLUGINS env var > default (load plugins).
Usage Example:
PRAISONAI_PROJECT_ROOT
Sets the allowed root directory for agent output file writes. Writes outside this root are silently blocked. Security Risk: Path-traversal write outside the project tree (e.g.output_file="../../etc/passwd").
os.getcwd() at save timeAffected Component:
praisonaiagents.agent.memory_mixin.MemoryMixin._save_output_to_file
Silent-failure semantics: When the output path resolves outside the project root, the save returns False, logs Output file %r is outside project root %r; skipping save at logging.warning, and prints ⚠️ Output path outside project root: <path> to stdout. No exception is raised.
Usage Example:
ALLOW_LOCAL_CRAWL
Bypasses SSRF protection for loopback, private, link-local, multicast, and unspecified IP addresses in web crawl tools. Security Risk: Server-Side Request Forgery (SSRF) — agents fetchinghttp://169.254.169.254/... (cloud metadata), http://localhost:6379 (Redis), etc.
{"error": "URL blocked by SSRF policy"} per blocked URLAccepted truthy values:
true only — exact, case-sensitive match. This is stricter than other env vars on this page.
Affected Components:
praisonaiagents.tools.web_crawl_tools—_is_safe_crawl_urlcallsis_safe_http_url(url)with no allowlist, so the crawler goes through the strict path.praisonaiagents.tools.url_safety.is_safe_http_url— accepts an explicitallowlistkeyword; only the web crawler uses the no-allowlist path. SearXNG passes its own loopback allowlist (seeSEARXNG_URL_ALLOWLIST).
web_crawl blocks loopback (127.0.0.1, localhost, ::1) by default — set ALLOW_LOCAL_CRAWL=true to reach a local dev server. SearXNG reaches loopback by design and does not need this flag. That is why localhost:32768 works for SearXNG search while 127.0.0.1 stays blocked for crawling.is_safe_http_url) serves both callers; the SearXNG path opts into a loopback allowlist, the crawler passes none.
Usage Example:
SEARXNG_URL_ALLOWLIST
Adds extra hostnames the SearXNG search call sites may reach, on top of the built-in loopback set (localhost, 127.0.0.1, ::1). For self-hosting SearXNG on a custom host that resolves to loopback.
Security Risk: Server-Side Request Forgery (SSRF) — a misconfigured allowlist that reached private ranges could expose internal services. This env var is designed so it cannot: entries can only exempt the loopback class.
web_crawl / _is_safe_crawl_url) does not read this list.Format: comma-separated hostnames — whitespace is trimmed and each host is lowercased. Empty or unset → only the built-in loopback set applies.
Default: unset → SearXNG reaches only
localhost, 127.0.0.1, ::1.
Affected Components:
praisonaiagents.tools.url_safety._env_allowlist— readsSEARXNG_URL_ALLOWLISTpraisonaiagents.tools.url_safety.validate_searxng_url— merges the env list with the built-in loopback set and passes it as theallowlisttois_safe_http_urlpraisonaiagents.tools.searxng_tools.searxng_searchandpraisonaiagents.tools.web_search(SearXNG provider)
PRAISONAI_ALLOW_JOB_WORKFLOWS
Controls execution of job and hybrid workflow types that can run shell commands and scripts. Security Risk: Remote Code Execution (RCE) via malicious YAML workflows- Job workflows: Direct shell, Python, and script execution
- Hybrid workflows: Combined agent + job execution
PRAISONAI_BROWSER_ALLOW_REMOTE
Controls browser server binding to non-loopback interfaces (0.0.0.0, remote IPs). Security Risk: WebSocket session hijacking and unauthorized browser access- Binds to
127.0.0.1(localhost only) - Blocks attempts to bind to
0.0.0.0or remote interfaces
PRAISONAI_RUN_SYNC_TIMEOUT
Default maximum seconds the wrapper’s sync-to-async bridge will wait for a coroutine to complete. Default:300 (5 minutes)
- Every
praisonaiCLI entry and wrapper-based server (gateway, a2u, mcp_server, scheduler) viapraisonai._async_bridge.run_sync. - Every ACP/LSP agent-centric tool call in
praison "…"andpraisonai tui launchvia the siblingpraisonai_code.cli.features.agent_tools._run_syncbridge (added in PR #3361).
praisonaiagents) uses its own separate bridge — see Async Bridge for the full map.
Common Patterns
- Development Mode
- Production Mode
- Docker Deployment
Migration Guide
Upgrading from Vulnerable Versions
1
Identify Usage
Check if you use any of these features:
- Local
tools.pyfiles - Recipes / templates that ship a
tools.pyand rely on it being implicitly loaded - Job or hybrid workflows with shell/script execution
- Browser server binding to
0.0.0.0 - HTTP API callers that pass a
file_pathtopraisonai.api.call.import_tools_from_file— these now raiseValueErroruntil you opt in
2
Add Environment Variables
3
Test Functionality
Verify your existing workflows still work:
4
Review Security
Evaluate if you really need each dangerous feature:
- Can you avoid local tools.py files?
- Can you use agent workflows instead of job workflows?
- Can you use localhost-only browser access?
Best Practices
🔒 Principle of Least Privilege
🔒 Principle of Least Privilege
Only enable environment variables for features you actively use. Each variable increases your attack surface.
🏢 Production Environment Isolation
🏢 Production Environment Isolation
Never enable dangerous variables in production unless absolutely necessary. Use staging environments for testing.
📁 File System Security
📁 File System Security
When
PRAISONAI_ALLOW_LOCAL_TOOLS=true or PRAISONAI_ALLOW_TEMPLATE_TOOLS=1 is set, ensure your working directory doesn’t contain untrusted tools.py files. This is especially risky for recipes fetched from remote registries.🌐 Network Security
🌐 Network Security
When
PRAISONAI_BROWSER_ALLOW_REMOTE=true, use firewalls and authentication to protect browser endpoints.Security Advisories
These environment variables address the following security vulnerabilities:
CVE IDs: Pending assignment by GitHub Security Advisory system
Fixed Versions:
- praisonai:
>=0.0.57 - praisonaiagents:
>=0.0.23
PRAISONAI_ALLOW_LOCAL_TOOLS enforcement to research/rewrite/expand/recipe tool-loading paths and the HTTP API, and added a CWD-only path constraint as defence-in-depth. No new advisory was filed; the threat model is unchanged from GHSA-g985-wjh9-qxxc.
Related
Guardrails
Content filtering and safety controls
Permissions
Agent permission management system

