If you find a vulnerability in ReadyAgents Core, please do not open a public issue.
The GitHub account readyagentsdev is a User, not an Organization.
Use private vulnerability reporting on this repository for vulnerability reports.
Public contact: info@readyagents.dev
Include:
- A description of the issue
- Steps to reproduce
- Impact (file sandbox escape, prompt/tool injection, secret leakage, etc.)
We will acknowledge the report and work on a fix before any disclosure.
--sovereign refuses non-loopback connects in-process for that run. DNS
lookups can still leak. MCP stdio children are network_uncontrolled. A native
extension can bypass the wrapper. Attestation is technical evidence, not legal
data-residency compliance. See docs/sovereign.md.
Prompt injection is not solved. With a policy file, the engine taint-tracks untrusted tool/HTTP/file/MCP/model values, enforces allow/gate/deny at the single dispatch seam, pins MCP tool descriptions, and refuses known secrets in model requests. Gates reuse the existing signed approval path. See docs/security-model.md and docs/policy.md. Without a policy file the 1.0 behaviour is unchanged.
Connectors are ordinary tools. Write-shaped ones gate by default. HTTP goes
through ConnectorContext (declared destinations + SSRF pin). The conformance
harness fails Python-level own-socket and os.environ reads; it is not an OS
sandbox. Catalog commands never print secret values. See
docs/connectors.md.
readyagents sign / verify and --require-signed check that a workflow or
pack was signed by a key in the local publisher keyring. That is provenance,
not a safety proof. Policy still decides what tools may run. There is no
default-trusted key, no Sigstore/CA, and no network key fetch. Pack
verification happens before import. See
docs/supply-chain.md.
Approver JWTs are verified against a local trust-anchor file with a real JWT
library (readyagentsdev[jwt], not in all). Fail closed on a bad anchor
when a token is presented. --actor NAME stays the default. Signed (HMAC of
the decision body) is not the same as identified (verified subject). Optional
credential brokering grants named secrets per tool at the dispatch seam; a
non-granted tool cannot read them from os.environ during the call. See
docs/identity.md and docs/credentials.md.
read_file/write_file/list_dirare sandboxed by a single helper (resolve_within): both sides are fully resolved (symlinks, junctions, macOS/tmp→/private/tmp), then compared withPath.is_relative_toplus case-aware equality from a runtime probe of the root filesystem (notsys.platform). Windows reserved names, alternate data streams, trailing dots/spaces, UNC/\\?\(unless the root is one), drive-relativeC:file.txt, and 8.3 names that resolve outside are refused. Writes are atomic (temp file in the destination dir, restrictive mode on the temp beforeos.replace).type: includepaths must stay under the parent workflow directoryhttp_getis disabled unless explicitly opted in, and even then refuses loopback, private, link-local, and metadata hosts (including after redirects)calcis a restricted arithmetic evaluator, not Pythoneval- API keys live in the environment / local env files and must never be committed
Each new audit JSONL line carries seq, prev_hash, and entry_hash.
readyagents audit verify detects a mutated or truncated line. Pre-chain
files are reported as unchained, not failed. A local attacker who can
rewrite the whole file can rewrite the chain. Copy the chain anchor off-box
if you need an independent check. ReadyAgents does not encrypt the audit
trail or run records at rest.
readyagents evidence RUN_ID writes a local pack that may include recorded
model prompts, inputs, and outputs. Redaction runs at pack time. Treat the
directory as sensitive. The pack is evidence, not a certificate.
readyagents run --record writes a cassette under $READYAGENTS_HOME/cassettes/. That
file holds full prompts and full completions (and recorded tool results). It is the
most sensitive artifact Core writes.
- Recording is opt-in (
--record/READYAGENTS_RECORD=1). - The configured redactor runs before any cassette write. A pre-write scan blocks entries that contain known secret values and marks that node unsealable.
runs freezere-verifies redaction. It warns in the terminal and in the generated README that the fixture must be reviewed before commit.- Cassettes are untrusted input: schema-validated, version-checked, size-bounded, never used to select a code path. A replay is labelled as a replay on the new run record.
--outand cassette paths go throughresolve_within.--seton fork cannot inject an approval or bypass the authorizer.- Offline replay never falls through to a live provider call.
type: memory is a persistent, cross-run store. Content written on one run is
retrieved on another — delayed prompt injection. Memory output is always
untrusted. Templated scopes that expand into another subject, .., /, or
* are refused. forget must remove records, search hits, and vectors.
memory export is confined and requires --yes. See
docs/memory.md.
readyagents a2a serve PATH is an explicit foreground command. It is not
started on install or import. Bind is loopback by default. --allow-public-bind
prints a warning; you own the exposure. Do not reverse-proxy this door onto
the public internet.
- Bearer auth (
READYAGENTS_A2A_TOKEN) on every path, including the Agent Card. - Host/Origin rebinding checks, body limits, and
Cache-Control: no-storereuse the MCP HTTP middleware. - Task id is the run id. Unknown and unauthorized ids share
Task not found. - An A2A answer to a local approval travels the existing signed-decision / RBAC / audit path. Unsigned or unauthorized answers are refused, audited, and leave the run paused.
type: a2atreats the remote agent as untrusted input. SSRF public-IP pinning applies. Credentials never follow a cross-host redirect. Delegation can exfiltrate; policy can denya2aand pin card digests.
This is a served mapping, not A2A certification. See docs/a2a.md.
v0.10 Streamable HTTP is an explicit foreground command (readyagents mcp serve --transport streamable-http). It is not started on install or import.
- Bind is loopback-only (
127.0.0.1). Non-loopback binds are rejected. - With
--auth token(default), all/mcpand/runsrequests requireAuthorization: Bearer. Token bytes are compared in constant time. Missing or wrong tokens return401withWWW-Authenticate: Bearer. - The token comes from
READYAGENTS_MCP_TOKEN(or--token-env). There is no token-value CLI flag; process listings expose argv. If the env var is empty, the process generates at least 256 bits of entropy and prints the token once to stderr. It is never persisted or logged. --auth noneis allowed only on an exact loopback bind and prints a warning. Do not expose this listener to the internet.Hostand browserOriginare checked against the configured loopback listener (DNS-rebinding defense). Responses useCache-Control: no-store.- Workspace confinement (
confine_under), SSRF public-IP pinning, secrets/RBAC/PII hooks, append-only audit, and signed decisions still apply. Provider keys are never accepted in request JSON. - Cooperative cancel does not kill a blocking tool or provider call. Status stays
cancel_requesteduntil a safe engine point. Retry backoff is a safe point and finishes ascancelled.
MCP tasks/update approvals have the same authority as readyagents decide and the localhost approval UI. They travel the existing RBAC authorizer, optional HMAC (READYAGENTS_DECISION_SECRET), and append-only audit path. An unsigned (when a decision secret is configured) or unauthorized MCP approval is refused, audited, and leaves the run paused. Do not treat a 2026 MCP client as a weaker door.
Do not reverse-proxy this door onto the public internet.
Quorum, roles, lazy deadlines, and delegation are opt-in workflow fields. Core
starts no timer; an unattended expires_in does not fire until resume, decide,
or a status query. on_expire: approve is refused at validation so stalling a
gate cannot mint an approval. Delegation is single-hop, time-bounded,
non-widening, and checked at decision time. Notify payloads are redacted and
bounded; webhook destinations use the existing SSRF pin. approvals list
does not distinguish unauthorized from missing. Every new path uses the
existing signed decision object. See docs/approvals.md.
readyagents approvals serve is an explicit foreground loopback page, not a hosted dashboard.
- Bind is loopback-only. Non-loopback hosts are rejected before a socket opens.
- A one-use bootstrap URL is printed on stderr. After one GET it 303s to
/approvalsand sets an HttpOnlySameSite=Strictsession cookie on/approvals. - Approve/reject uses one-use HMAC action tokens bound to run id, pending node, revision, and decision. Replay, stale revision, and wrong node do not resume twice.
- Host/Origin checks, CSP (
default-src 'none'plus self scripts/styles),nosniff,no-store, and frame denial apply. Query strings are not written to the access log. - The page is a redacted view. It does not display full inputs, outputs, tool traces, or secrets.
- Trust boundary is the local operator on that host. A privileged local process can still read loopback traffic.
- Outbound
on_pause_urlstill refuses loopback/private/metadata URLs; the UI does not add a loopback webhook exception.
JSON run files ($READYAGENTS_HOME/runs/) and the optional SQLite file ($READYAGENTS_HOME/runs.sqlite3, plus -wal / -shm companions) can contain prompts, outputs, and other workflow state. ReadyAgents does not encrypt run records at rest.
On POSIX, new run files and cache entries are created with owner-only modes (0o600 files, 0o700 dirs) when the filesystem honours chmod. On Windows those modes are not enforceable through the standard library (chmod is effectively a no-op; no ACL dependency is installed). readyagents doctor reports permissions_enforceable. Do not rely on file modes alone to hide API keys or PII on Windows.
Trust boundary is the local host. A privileged local process can read these files. For a consistent SQLite backup, copy the database together with -wal and -shm, or checkpoint first. Network filesystems are unsupported for SQLite (locking is not guaranteed).
JSON-to-SQLite migration never deletes the JSON sources. The append-only audit trail under $READYAGENTS_HOME/audit/ is a separate JSONL log and is not imported into the run store.
ReadyAgents does not provide encryption at rest. See docs/compliance.md.
Do not paste API keys, .env, .env-ai, or MCP bearer tokens into GitHub.