Skip to content

Security: Amaljeevs/agentguard

Security

SECURITY.md

Security Policy

Reporting vulnerabilities

Report privately to amaljeevs3739@gmail.com or use a private GitHub Security Advisory. Include the affected module/version, impact, reproduction steps, and a minimal proof of concept where possible. Do not include live credentials or sensitive customer data in the report. We will coordinate investigation, fixes, and disclosure with the reporter.

Release status

Version Status
1.0.0 Upcoming production stable release; finalized API contracts, full adversarial test suite, enterprise identity, and durable PostgreSQL store
0.2.1 Active release on Maven Central; verified identity, bound approvals, Spring AI, Postgres durable store, Micrometer metrics, and REST API
0.2.0 Previous release
0.1.0 Initial release; does not include the new hardening or approval/Spring AI modules
Older versions Unsupported pre-release builds

See CHANGELOG.md for version-specific changes. No independent security audit or universal non-bypassability guarantee is claimed.

Trust boundary and architecture flow

AgentGuard enforces deterministic policy decisions at application execution boundaries. It operates strictly within this trust chain:

Identity provider (OAuth2/OIDC/Entra/Keycloak/SPIFFE)
  → Verified identity (VerifiedClaims: sub, roles, scopes, tenant, delegation)
    → AgentGuard (deterministic policy evaluation & exact-request binding)
      → Policy decision (ALLOW / DENY / APPROVAL_REQUIRED)
        → Guarded tool / API execution

Model Intent vs. Application Authority

  • Model Intent: An autonomous agent or LLM proposes a tool name and arguments. This proposal is untrusted model intent.
  • Application Authority: The host application authenticates the caller, resolves verified claims into an immutable AgentIdentity, and presents the request to AgentGuard.
  • AgentGuard never evaluates prompt text, does not detect or classify prompt injection, and does not let LLMs decide their own authorization.
  • Regardless of why an action was proposed (legitimate agent reasoning, model hallucination, or adversarial prompt manipulation), AgentGuard deterministically enforces application safety rules before tool execution.

Precise Security Invariants

AgentGuard:

  • Prevents tool execution when deterministic authorization denies it (fail-closed, deny-by-default).
  • Binds human approval to an exact request using canonical SHA-256 argument fingerprinting (ApprovalTicket).
  • Detects modification of an approved request before single-use execution, halting execution if arguments, actor, or policy changed.
  • Enforces delegation constraints ensuring child authority is a strict subset of parent authority (child ⊆ parent), detecting cycles, enforcing max depth limits, and enforcing tenant isolation.
  • Generates sanitized authorization/audit evidence without leaking sensitive credentials or argument secrets.
  • Complements upstream security: Designed to work with OAuth2, OIDC, Spring Security, Microsoft Entra ID, Keycloak, and SPIFFE rather than replacing authentication or IAM.
  • Does not sandbox arbitrary OS code: It intercepts execution through its proxies and guarded tool callbacks; unproxied calls or self-invocation bypass aspect boundaries. Register only guarded tool callbacks.

Policy enforcement invariants

  • Deny by default when no explicit grant or matching permission exists.
  • Explicit DENY takes precedence over grants and approval rules.
  • Approval is a restriction on an otherwise permitted action; it is not a grant.
  • Configured expressions resolving to errors, null or blank deny rather than falling back to development/default resource values.
  • Identities must satisfy issuedAt <= evaluationTime < expiresAt.
  • A delegated request is evaluated for each ancestor returned by a trusted AgentIdentityLookup. Unknown parents, lookup failures, cycles, depth greater than the supported chain limit and child validity outside parent validity deny. The engine also requires each child's effective direct/role permissions to be conservatively contained by its parent's permissions and verifies the complete claimed chain against looked-up ancestors.
  • Missing or invalid policy files prevent default Spring policy initialization.

Approval storage and execution

The approval module binds tickets to identity/session, delegation chain, action, canonical arguments, resource, environment, expiry, and policy content revision with SHA-256. Separate approvers need agentguard.approval.approve; self-approval is rejected. Execution rechecks policy, verifies the binding and atomically consumes the ticket first. Failed execution does not restore a consumed ticket.

agentguard-approval provides two store implementations:

  1. InMemoryApprovalStore: Fast, bounded, in-memory reference store for unit tests and local prototyping.
  2. PostgresApprovalStore: Production-ready durable store backed by standard javax.sql.DataSource. It leverages PostgreSQL row-level locks (SELECT ... FOR UPDATE) to guarantee atomic single-use state transitions (APPROVED -> CONSUMED) and strictly prevent double-consumption or replay across clustered application replicas. DDL schema with indexing on subject_id, state, and expires_at is provided in schema-postgresql.sql.

Application code owns business transactions, idempotency, crash recovery and reconciliation; approval consumption is not an exactly-once distributed transaction.

Use an immutable/version-consistent PolicyEngine instance during each approval operation. Custom engines must expose a revision that changes whenever effective policy changes. Resolve current trusted identities at each request rather than replaying stale caller-created identity objects.

Audit redaction and failure behavior

Sanitization is structured and key/annotation based. It covers maps, collections, arrays, records and public bean getters with bounded traversal. Unknown objects, cycles and excessive depth are masked. Standard audit-event construction sanitizes parameters and context metadata. The JSON publisher emits an arguments hash instead of raw arguments and includes identity, delegation, policy, risk, approval and trace evidence.

It does not detect secrets embedded in arbitrary strings, intercept every logger, redact database contents, or guarantee that all personal data is removed. Configure sensitive keys for your domain, keep credentials out of free-form fields, and configure third-party request/SQL logging separately. Manually constructing and publishing raw AuditEvent records bypasses the standard construction sanitizer; custom publishers must enforce their own input contract.

The starter's enforcement path defaults to FAIL_CLOSED for publisher failures; BEST_EFFORT must be chosen explicitly. Custom composite publishers have their own failure policy. An AUTHORIZATION event is a policy decision, not proof of a committed side effect. EXECUTION_SUCCEEDED means the callback returned normally; post-execution publication can fail after side effects. No durable delivery or non-repudiation guarantee is provided by console/in-memory publishers.

Example applications

Example accounts, passwords, in-memory databases and review endpoints are local demonstrations, not production identity or retention systems. The H2 dashboard keeps CSRF protection. The separate stateless MCP machine-client example excludes CSRF for its authenticated JSON API and MCP endpoint; do not apply that exclusion to a browser-session application.

There aren't any published security advisories