The dominant pattern is a full external-input-to-host-execution chain with no code-level interposition at any hop. Untrusted content (web pages via web_fetch, inbound messages, imported Living UI projects) reaches the LLM context unsanitized — the PromptSanitizer that exists is wired to nothing — and the model's output is executed as Python through exec()/subprocess in executor.py, where the "sandbox" is a same-user venv that shares the host filesystem, network, and environment. Every high-impact approval the remit requires lives only as instruction text in the system prompt (agent_core/core/prompts/context.py/action.py); there is no code-enforced approval gate.
Layered on top, the agent's own system-prompt-injected identity file (SOUL.md) and scheduled auto-written MEMORY.md are writable without operator confirmation, turning the same injection path into an ASI06 persistence chain. Genuine controls do exist — the operator control plane binds localhost, a consecutive-LLM-failure abort caps runaway loops, and error strings are redacted — but they sit beside the unguarded exec/approval core.
agent_core action framework plus an app/ layer (CLI and browser/WebSocket UI, LangGraph-style orchestration, scheduler, proactive engine, Living UI manager, and 20+ craftos_integrations messaging/social connectors). The action system executes model-generated Python via exec() in agent_core/core/impl/action/executor.py (both in-process "internal" and a persistent-venv "sandboxed" mode) and via subprocess.run. Session identity is file-backed in agent_file_system/ (SOUL.md is injected into the system prompt; AGENT.md, USER.md, MEMORY.md); a PromptSanitizer exists in app/security/prompt_sanitizer.py but is never called. The operator browser adapter binds localhost, but Living UI backends launch uvicorn on 0.0.0.0. Secrets live as plaintext JSON in .credentials/ and app/config/settings.json; a 157-server MCP marketplace ships in app/config/mcp_config.json (filesystem and playwright enabled by default via unpinned npx -y).Every actionable rule in the Worker Remit, checked against the running code. Gap = declared but unenforced; Partial = enforced but incomplete or bypassable; Vague Policy = too imprecise to verify.
| Rule ID | Section | Rule (quoted) | Status | Finding |
|---|---|---|---|---|
| R-01 | Mission | "It must act solely on behalf of, and under the control of, the operator who runs it — never as an autonomous party acting against the operator's interest, and never as a service exposed to untrusted third parties." | Enforcement Not Possible | — |
| R-02 | Non-Goals (Out of Scope) | "Exposing its control surface (task execution, settings, files, credentials) to the public internet or to other users." | Partial | PRAX-2026-07-11-008 |
| R-03 | Non-Goals (Out of Scope) | "Exfiltrating the operator's data or credentials to any destination the operator did not direct." | Enforcement Not Possible | — |
| R-04 | Approved Communication Channels | "The primary operator interface; must be reachable only from the local machine." | Verified | — |
| R-05 | Approved Communication Channels | "Inbound messages from a messaging channel must never be treated as authenticated operator commands without a sender-identity check." | Gap | PRAX-2026-07-11-003 |
| R-06 | Tools and Capabilities | "Because this capability can read, modify, or destroy any file the operator can and can reach the network, it MUST run isolated from the host or require operator approval before executing a state-changing or destructive command, and it MUST NOT silently inherit the operator's full secret-bearing environment." | Gap | PRAX-2026-07-11-001 |
| R-07 | Tools and Capabilities | "These MUST be isolated from the operator's credentials and broader filesystem and MUST come from a source the operator approved." | Partial | PRAX-2026-07-11-010 |
| R-08 | Tools and Capabilities | "Any capability that exposes agent control, files, or credentials to a network-reachable, unauthenticated caller." | Gap | PRAX-2026-07-11-008 |
| R-09 | Data Boundaries | "Credentials or secrets MUST NOT be written to chat, logs, or any world-readable or version-controlled file." | Partial | PRAX-2026-07-11-013 |
| R-10 | Data Boundaries | "Secrets MUST be stored protected at rest (OS keychain or encrypted store), not as plaintext files, and MUST be excluded from any data the agent transmits." | Gap | PRAX-2026-07-11-007 |
| R-11 | Action Boundaries | "an agent-initiated high-impact action requires explicit operator approval, and this gating MUST be enforced by code, not left to model discretion alone." | Gap | PRAX-2026-07-11-002 |
| R-12 | Action Boundaries | "Any irreversible or externally-visible action: sending email/messages, posting publicly, making payments or other financial operations, and creating/modifying/deleting data in a connected third-party account." | Partial | PRAX-2026-07-11-002 |
| R-13 | Action Boundaries | "Fabricating success for an action that failed." | Enforcement Not Possible | — |
| R-14 | Action Boundaries | "Editing the operator-owned identity/policy files (SOUL.md, USER.md, AGENT.md) or the long-term memory store without operator confirmation." | Gap | PRAX-2026-07-11-009 |
| R-15 | Escalation Rules | "Repeated identical failures (a loop), or a consecutive-LLM-failure condition." | Verified | — |
| R-16 | Behavioral Expectations | "Maximum retries before escalation: one retry for a transient error; then stop and escalate." | Vague Policy | — |
| R-17 | Authorized Counterparties | "Unknown inbound senders on any messaging channel, treated as trusted commanders without an identity check." | Gap | PRAX-2026-07-11-003 |
Findings, ordered by severity — each linked to its remit rule, evidence, and a recommended action. Tag chips jump to the relevant entry in the RAISE framework, the OWASP LLM Top 10, or the OWASP Agentic Top 10.
LLM06 primary — the finding's main OWASP categoryASI10 secondary — a category it also touches
CRITICAL PRAX-2026-07-11-001 Model-generated Python is executed on the host via exec()/subprocess with no isolation, no code approval, and the operator's full environment.
"Because this capability can read, modify, or destroy any file the operator can and can reach the network, it MUST run isolated from the host or require operator approval before executing a state-changing or destructive command, and it MUST NOT silently inherit the operator's full secret-bearing environment."
- Run all model-generated code in a real isolation boundary (container/microVM with dropped network and a scrubbed environment) instead of a same-user venv, and strip secret-bearing env vars before exec.
- Gate any state-changing or destructive execution behind a code-enforced operator approval step in executor.py, not prompt text.
CRITICAL PRAX-2026-07-11-002 Every high-impact approval the remit requires exists only as system-prompt instructions; there is no code-enforced approval gate.
"an agent-initiated high-impact action requires explicit operator approval, and this gating MUST be enforced by code, not left to model discretion alone. / Any irreversible or externally-visible action: sending email/messages, posting publicly, making payments or other financial operations, and creating/modifying/deleting data in a connected third-party account."
- Introduce a code-level approval checkpoint in the action executor/manager that blocks send/post/pay/delete/exec actions until an explicit operator confirmation is recorded.
- Classify actions by impact and require approval for the high-impact classes regardless of model output.
CRITICAL PRAX-2026-07-11-003 Inbound messaging defaults to auto_reply=true with no sender-identity check, so an unknown sender can drive the agent as the operator.
"Inbound messages from a messaging channel must never be treated as authenticated operator commands without a sender-identity check. / Unknown inbound senders on any messaging channel, treated as trusted commanders without an identity check."
- Add an operator-identity allowlist check that runs before any inbound message is treated as a command or auto-replied, defaulting auto_reply to false.
- Route messages from unrecognized senders to an approval/notification path rather than the command pipeline.
CRITICAL PRAX-2026-07-11-004 Untrusted external content reaches the LLM context unsanitized and the model's output is executed as host code — a one-hop injection-to-RCE chain.
- Treat all external/tool-returned content as untrusted: wire the existing PromptSanitizer (or a stronger boundary) into the ingestion path and mark such content non-executable-provenance.
- Combine with the code-enforced exec approval and isolation from findings 001/002 to break the chain end to end.
CRITICAL PRAX-2026-07-11-005 Writable system-prompt identity file (SOUL.md) and auto-written MEMORY.md plus the injection-to-exec path form an ASI06 persistence-and-execution chain.
- Require code-enforced operator confirmation before any write to SOUL.md/AGENT.md/USER.md or the memory store, and keep these files version-controlled/audited.
- Break the persistence chain by fixing the injection ingress (004) and the exec/approval gaps (001/002).
HIGH PRAX-2026-07-11-006 A full PromptSanitizer injection-filter module exists but is never called anywhere in the codebase.
- Invoke the sanitizer (or a stronger trust boundary) at every ingestion point for user, web, and tool-returned content.
- Treat the regex denylist as defense-in-depth only; do not rely on it as the sole injection control.
HIGH PRAX-2026-07-11-007 Operator secrets are stored as plaintext JSON at rest — integration tokens in .credentials/ and LLM API keys in settings.json — not in a keychain or encrypted store.
"Secrets MUST be stored protected at rest (OS keychain or encrypted store), not as plaintext files, and MUST be excluded from any data the agent transmits."
- Move secrets to an OS keychain (Keychain/DPAPI/libsecret) or an encrypted store; keep only references in settings.json / .credentials/.
- Migrate existing plaintext secrets on upgrade and scrub them from the config files.
HIGH PRAX-2026-07-11-008 Living UI backends launch uvicorn bound to 0.0.0.0, exposing agent-operated services to the whole local network unauthenticated.
"Exposing its control surface (task execution, settings, files, credentials) to the public internet or to other users. / Any capability that exposes agent control, files, or credentials to a network-reachable, unauthenticated caller."
- Bind Living UI backends and the sidecar proxy to 127.0.0.1 by default; require explicit operator opt-in and authentication for any non-loopback bind.
- Remove shell=True from the Windows uvicorn launch to avoid command-construction risk.
HIGH PRAX-2026-07-11-009 The agent can rewrite its own identity/policy files (SOUL.md, AGENT.md, USER.md) and long-term MEMORY.md without code-enforced operator confirmation.
"Editing the operator-owned identity/policy files (SOUL.md, USER.md, AGENT.md) or the long-term memory store without operator confirmation."
- Require an explicit operator-confirmation step in code before any write to the identity/policy files or the memory store.
- Version-control and audit these files so unattended edits are detectable.
HIGH PRAX-2026-07-11-010 Third-party MCP servers and imported code run without isolation or provenance vetting; the filesystem MCP is enabled by default with broad write scope.
"These MUST be isolated from the operator's credentials and broader filesystem and MUST come from a source the operator approved."
- Pin MCP server versions and require an operator-approved allowlist before a server may run; scope the filesystem server to a designated workspace path, not ".".
- Run MCP servers and imported projects in an isolated context without access to the operator's credential store.
MEDIUM PRAX-2026-07-11-011 Python dependencies are entirely unpinned with no lockfile, enabling version-swap and dependency-confusion risk.
- Pin dependencies to exact versions and commit a lockfile with hashes.
- Add a dependency-audit step to CI.
MEDIUM PRAX-2026-07-11-012 No adversarial/injection testing exists and the CI workflow is checked in disabled.
- Add an adversarial test suite covering injection via web content, inbound messages, and imported Living UI, and gate merges on it.
- Re-enable CI so functional and security tests run on every change.
MEDIUM PRAX-2026-07-11-013 Action logs capture call args and results without secret redaction; scrubbing exists only in the error handler.
"Credentials or secrets MUST NOT be written to chat, logs, or any world-readable or version-controlled file."
- Apply the secret-redaction filter to all log sinks, not just error strings.
- Exclude credential-bearing fields from logged action args/results.
MEDIUM PRAX-2026-07-11-014 Domain scope is enforced only in prompt text while a 157-server MCP marketplace and broad action framework form a large latent tool surface.
- Enforce an operator-configured capability allowlist in code so disabled/unapproved MCP servers and action classes cannot be invoked even if the prompt is subverted.
- Keep the marketplace opt-in and require explicit enable + approval per server.
Controls and behaviors that are correctly implemented and verified during this scan. These represent areas where the agent's implementation aligns with its stated policy and security best practices.
Operator control plane binds localhost by default
The browser/WebSocket operator interface defaults to host "localhost", keeping the primary control surface off the network unless deliberately changed.
Consecutive-LLM-failure abort caps runaway loops
The LLM interface tracks consecutive failures and raises LLMConsecutiveFailureError once the threshold (5) is hit, satisfying the remit's loop/consecutive-failure halt expectation.
Credential files written with owner-only permissions
The credentials store chmods its directory and files to user-only (0600/0700), limiting local read exposure of the plaintext credential JSON.
Error-string redaction and API-key masking
The error handler substitutes secret-shaped patterns with [REDACTED] and settings UIs mask API keys to first/last four characters before display.
Structured file logging and event stream
loguru file sinks (main.log, all.log, per-subagent) plus an event-stream and log_events decorator provide action-level, parseable runtime logs.
Log files found in the agent's workspace during this scan. Reviewing these files provides runtime evidence to complement the static analysis above.
| Path | Source | Content Type | Purpose | Last Modified | Status |
|---|---|---|---|---|---|
| <run_dir>/main.log | app/logger.py setup_logging loguru sink | plaintext application log | Primary runtime log of agent operation | unknown | Inferred |
| <run_dir>/all.log | app/logger.py setup_logging loguru sink | plaintext application log (verbose) | Full-verbosity runtime log including subprocess/uvicorn capture | unknown | Inferred |
| <run_dir>/<agent_tag>.log | app/logger.py add_subagent_log_sink | plaintext per-subagent log | Isolated log lines for an individual sub-agent run | unknown | Inferred |
| logs/<name>.log | agent_core/utils/logger.py | plaintext component log | agent_core component-level logging | unknown | Inferred |
Each card represents one category and shows the top 3 findings. All items in the Findings section.
Each card represents one category and shows the top 3 findings. All items in the Findings section.
Overall maturity assessment across the six categories of the RAISE framework. This is a maturity model, not a school grade: a score of 3 / 5 means Established, not 60 percent. Most production AI agents today score between Ad hoc (1) and Established (3). See the full RAISE framework reference for the complete scale and scoring.
Maturity Scoring Rubric
Every score above is based on this scale. A score is a snapshot of observable posture — not a verdict on the people or team behind the system.
| Score | Label | Meaning |
|---|---|---|
| 5 | Exemplary | Best-in-class; automated, continuously tested, reference quality. Rarely achieved in shipping systems. |
| 4 | Strong | Comprehensive controls, active management, minor gaps. Production-ready. |
| 3 | Established | Documented controls consistently applied; known gaps accepted. A respectable baseline. |
| 2 | Partial | Some controls exist but coverage is incomplete; key gaps remain. |
| 1 | Ad hoc | Informal or inconsistent measures; relies on individual judgment. |
| 0 | Absent | No evidence this category is addressed at all. |