README.md
September 10, 2026 ยท View on GitHub
Aguara
Check what your AI agents are about to trust.
Open-source security engine for agent instructions, tool configurations, and software dependencies.
A project brings more than source code into your environment. Its dependencies can run install scripts. Its agent settings can approve commands or start tools. Its instructions can ask an agent to read credentials or execute a helper you have not reviewed.
Aguara checks those files for known-malicious packages, suspicious behavior, and risky permissions before you use them. The report points you to the affected package or file so you can investigate before installing dependencies, running CI, or giving an agent access to the project.
Use it when evaluating a repository or skill, reviewing a change, or adding a security check to an agent workflow. You do not need an AI agent to use its package and code checks.
Analysis runs locally. No package execution, content upload, telemetry, or LLM calls.
Quick start | Coverage | CI | Integrations | Development | Security
Quick Start
Install the published release:
curl -fsSL https://raw.githubusercontent.com/garagon/aguara/v0.28.0/install.sh \
| VERSION=v0.28.0 sh
The default location is ~/.local/bin; add it to your PATH if needed. The installer verifies the archive checksum. See signature verification for verifying its signing identity, or other installation options.
From the project directory, run:
aguara audit .
This combines a malicious-package check with a content scan. It does not install dependencies or run the project's commands. Read the findings before taking the next step; a passing result is not a guarantee that the project is safe.
Trust boundary: in v0.28.0, audit, CI scans and the public scanning API ignore target-owned exclusions and suppressions by default. Local scan can still honor them; use --project-policy ignore for unfamiliar projects. Older releases may trust repository-owned policy. See the upgrade notes before changing an existing integration.
Reading a finding
For example, a .claude/settings.json containing "allow": ["Bash(*)"] grants broad shell approval. Aguara reports that configuration for review. A shortened JSON finding from v0.28.0:
{
"rule_id": "AGENTCFG_BROAD_ALLOW_001",
"rule_name": "Claude Code permissions pre-approve dangerous commands",
"severity": 2,
"file_path": ".claude/settings.json",
"line": 3,
"matched_text": "Bash(*)"
}
Here severity: 2 means MEDIUM. The finding is not a claim that the project is malware. It identifies a permission decision to review: does the tool need unrestricted shell access, or can the approval be narrowed?
aguara explain AGENTCFG_BROAD_ALLOW_001
aguara audit . --verbose
aguara audit . --format json
Review known-malicious package matches first, then the content findings and their explanations. An exit code reflects the command's failure threshold, not the absence of every risk.
What Aguara Checks
| What you are reviewing | What Aguara looks for | Command |
|---|---|---|
| A project | Package matches and content findings together | aguara audit . |
| Dependencies | Resolved packages covered by malicious-package advisories | aguara check . |
| Agent skills and instructions | Prompt injection, suspicious requests for secrets or execution, and tool poisoning | aguara scan ./skills/ |
| MCP configuration | Risky tool launch commands, embedded credentials, and configuration patterns | aguara scan --auto |
| Agent host settings | Broad approvals, fetch-and-execute hooks, and code-injection environment settings in Claude Code .claude/settings.json and settings.local.json | aguara scan .claude/ |
| Package-manager policy | Explicit npm and pnpm settings that relax install-time protections | aguara scan . |
| Project code and CI | Suspicious install hooks, credential access, execution chains, and GitHub Actions trust risks | aguara scan . |
scan --auto discovers supported MCP client configurations on the machine. Use aguara discover to inspect that inventory. Configuration coverage is specific to supported file formats; it does not imply support for every agent host.
Packages and lockfiles
Lockfiles let Aguara check resolved dependencies without installing them. Coverage depends on what the file records and what the active intelligence snapshot knows.
| Ecosystem | Evidence read |
|---|---|
| npm | node_modules, pnpm store, package-lock.json, pnpm-lock.yaml, classic and Berry yarn.lock, text bun.lock |
| PyPI | Installed site-packages, .pth files, supported cache locations |
| Go | go.sum, go.mod |
| Rust | Public-registry entries in Cargo.lock |
| PHP | composer.lock |
| Ruby | Gemfile.lock |
| Java | pom.xml, Gradle lockfiles |
| .NET | packages.lock.json, supported project files |
Matching supports exact versions and advisories affecting every version of a package. Bounded version ranges are supported for npm semver, not arbitrary ranges in every ecosystem. This is malicious-package detection, not comprehensive CVE coverage.
Unambiguous npm: aliases resolve to the real package in package-lock, pnpm, Yarn classic, Yarn Berry, and Bun. Classic Yarn uses the alias target name and the block's resolved version; conflicting descriptors and ambiguous non-registry identities are skipped rather than assigned a guessed package identity. Binary bun.lockb is not parsed; a repository with only that file returns an error asking for text bun.lock.
Lockfile and dependency-manifest inputs must be regular files no larger than 50 MiB. Leaf symlinks, including dangling links, return an error rather than being followed or silently skipped. This read boundary does not confine parent directories or guarantee that file contents remain unchanged during a check. Installed-package scanning is a separate path.
Legacy package-lock.json dependency trees have a 128-level nesting limit and a
50 MiB cumulative subtree-decoding budget, in addition to the file-size limit.
Exceeding either returns an error, not a partial successful package check.
Behavior and policy
Aguara also inspects code for behaviors that do not depend on a package already being listed in an advisory: suspicious second-stage execution, credential transmission, host-file tampering, and destructive cleanup. It combines signatures, parsed configuration, bounded code analysis, and heuristic correlations. Binding checks to actual calls reduces noise, but it does not eliminate false positives or provide whole-program dataflow analysis.
The npm checks read package.json and project .npmrc; pnpm checks read pnpm-workspace.yaml. They flag explicit settings such as blanket script approval or weakened source restrictions. A missing setting is not reported. That does not prove the effective package-manager configuration is secure: the installed version, environment, and command-line overrides also matter. See the rule reference for individual checks and use aguara explain <RULE_ID> for their scope.
Threat Intel
The binary includes an advisory snapshot sourced from OSV, including OpenSSF Malicious Packages, alongside manually curated incident records. OSV is an open-source vulnerability database developed by Google; Aguara imports a malicious-package-focused subset, not its entire CVE database.
Descriptions mentioning malware are not enough to classify a package as malicious. Imports require source evidence or explicitly reviewed affected versions. Older OSV snapshots are filtered before use, including the embedded data and verified cache, so past keyword-based classifications cannot reappear after a refresh. See the admission policy for accepted evidence and the bounded historical compatibility list. This filtering requires an updated binary; an intel refresh alone does not change older binaries.
A package finding identifies the advisory behind the match. Check that record and its affected versions when investigating; the snapshot is not a complete inventory of every malicious package.
Checks use embedded intelligence and any configured local cache without fetching the files being scanned. Refreshing intelligence is an explicit network operation:
aguara status
aguara update
aguara check . --fresh
update and --fresh fetch and verify Aguara's signed advisory bundle. Later checks can use the verified local cache offline. Snapshot age is context, not evidence that a dependency is safe or malicious.
The explicit --insecure-intel escape hatch skips signature verification only
when AGUARA_INSECURE_INTEL=1 is also set. Such downloads are labeled unverified
and cannot be reused by default checks or --allow-stale. Older cache markers
do not reliably establish that a signature was verified; run aguara update
without --insecure-intel to restore verified offline use after upgrading.
Release notices are separate from analysis: aguara version can check for a newer release; scan does not. Set AGUARA_NO_UPDATE_CHECK=1 to disable release notices. For network-isolated use, set that variable and avoid update and --fresh; no online lookup is needed to analyze the content.
Adopting Aguara in CI
Run the audit before dependency installation or project commands:
aguara audit . --ci
audit --ci fails on critical findings by default. scan --ci uses a high-or-above threshold instead. Review the threshold for the command you integrate; they are not interchangeable.
To introduce a gate in an existing project, record and review a baseline:
aguara audit . --write-baseline .aguara-baseline.json
aguara audit . --ci --baseline .aguara-baseline.json
Baseline-matched content findings remain visible but do not fail the gate. New findings are evaluated against the selected threshold. Compromised-package findings are not baselineable, and sensitive findings are omitted when writing a baseline. A missing or malformed baseline returns an error. Treat baseline changes as security decisions during review.
Installation
The following alternatives install the published release:
# Homebrew
brew install garagon/tap/aguara
# Docker: read-only project mount, non-root container
docker run --rm -v "$PWD:/repo:ro" ghcr.io/garagon/aguara:0.28.0 audit /repo
# Go: pinned release; requires Go 1.25.8 or later
go install github.com/garagon/aguara/cmd/aguara@v0.28.0
Release binaries are available for Linux, macOS, and Windows on the Releases page. The container supports Linux amd64 and arm64. Go installs do not inject release version metadata; use release artifacts when that metadata or signature verification is required.
GitHub Action
The Action runs a content scan, not the combined package audit. Pin both the Action and its binary:
- uses: garagon/aguara@v0.28.0
with:
path: .
fail-on: high
version: v0.28.0
The default SARIF upload needs security-events: write. See action.yml for inputs; use the CLI audit in a separate CI step when you also need package-intelligence checks.
Outputs and Integrations
scan offers terminal, JSON, SARIF, and Markdown output. audit offers a combined terminal or JSON report. Use SARIF from scan for GitHub Code Scanning; other SAST services may require a different schema.
The Go library exposes the same content-scanning engine for tools that need analysis without a CLI subprocess:
package main
import (
"context"
"fmt"
"log"
"github.com/garagon/aguara"
)
func main() {
result, err := aguara.ScanContent(context.Background(), "Content to inspect", "skill.md")
if err != nil {
log.Fatal(err)
}
for _, finding := range result.Findings {
fmt.Printf("%s %s:%d\n", finding.RuleID, finding.FilePath, finding.Line)
}
}
Scan accepts a file or directory; ScanContent accepts content directly without loading a file. ListRules and ExplainRule expose the catalog. Pin the Go module version in your application. Consumers can call the engine during a live workflow, but interception, authorization, session policy, and enforcement remain the consumer's responsibility.
Aguara MCP is a separate integration that exposes scanning tools to agents. Aguara itself does not require an MCP server, hosted account, or model provider.
Limitations
- A clean report is not a safety certificate. Unsupported formats, dynamic code, incomplete inputs, and threats absent from the rules or intelligence can be missed. Inspect errors and what was actually scanned.
- A finding is evidence to review, not always proof of malicious intent. Legitimate provisioning, release scripts, and examples can resemble risky behavior.
- Static analysis does not enforce runtime isolation. Aguara does not sandbox a package, revoke a credential, intercept a tool call, or prevent an agent from executing a command on its own.
- Coverage is bounded. It does not replace application SAST, general CVE/SCA analysis, or runtime monitoring. Shell parsing and dataflow support vary by detector.
- Results depend on the analysis inputs. Compare findings with the same engine version, rules, configuration, intelligence snapshot, and monitor state where applicable. Timing fields are not deterministic.
- Reports can contain sensitive material. Review findings and context before sharing or retaining them; do not assume every part of a report is safe to publish.
Development Version
v0.28.0 includes the capabilities below. Later changes on main are listed under Unreleased. Building from source is not equivalent to installing a signed release.
| Capability | What changes for the caller |
|---|---|
| Untrusted-project policy | audit and CI scans ignore target-owned suppressions by default; local scan can still trust project policy. Use --project-policy ignore explicitly when inspecting unfamiliar content. |
| Triage and agent handoff | Audit JSON adds triage, agent_handoff, and action_plan: review priorities and guidance about the next action. These fields do not enforce permissions. |
| Decision impact | Findings distinguish supporting context from review signals. Severity and explicit failure thresholds remain separate. |
| Skill and helper checks | Skill frontmatter and instruction-to-helper correlation add checks for broad tool approval and required local helpers with suspicious behavior. |
| Script analysis and catalog | Additional Python/shell analysis and unified rule enumeration expose analyzer rules through list-rules and explain. |
For a development build, clone the repository, review and check out the commit you intend to test, then run make build. Record that commit alongside your results. Use the resulting local binary, not an older installation on your PATH:
./aguara scan ./skills/ --project-policy ignore
./aguara audit . --format json
The v0.28.0 catalog contains 258 detections: 192 YAML pattern rules and 66 analyzer-emitted detections. The installed binary's aguara list-rules is the reference for its own catalog. This count is not the number of malicious-package records in the intelligence snapshot.
Rules and Architecture
Content analysis combines pattern matching and decoding, configuration parsers, language-specific checks, prompt-injection analysis, and bounded cross-file correlation. Thirteen per-file analyzers run by default; rug-pull tracking joins with --monitor. Skill-chain correlation runs separately across files.
Package-intelligence checking is a separate path used by check and combined with content analysis by audit. See CONTRIBUTING.md for the package layout and RULES.md for detection details.
| Component | Responsibility |
|---|---|
aguara.go | Public Go API and result types |
internal/scanner | File discovery, analyzer execution, and result collection |
internal/engine | Content analyzers and their registry |
internal/rules | Pattern-rule loading, compilation, and built-in definitions |
internal/packagecheck | Package and lockfile parsing |
internal/incident | Package-intelligence checks and incident evidence |
cmd/aguara | CLI commands and workflow integration |
aguara list-rules
aguara explain CRED_002
aguara scan . --rules ./my-rules/
Custom rules and local configuration can change coverage. Review .aguara.yml, .aguaraignore, custom rules, and inline suppressions before trusting a project's scan policy. Use aguara init to scaffold a local configuration. The --project-policy boundary described above is available from v0.28.0.
Verifying Signed Releases
Release archives have checksums signed with Cosign keyless and include SPDX SBOMs. Container images are signed at their digest with SBOM and SLSA provenance attestations. Verify the signing identity as well as the checksum:
VERSION=v0.28.0
ARCHIVE=aguara_${VERSION#v}_linux_amd64.tar.gz
curl -fsSLO https://github.com/garagon/aguara/releases/download/${VERSION}/${ARCHIVE}
curl -fsSLO https://github.com/garagon/aguara/releases/download/${VERSION}/checksums.txt
curl -fsSLO https://github.com/garagon/aguara/releases/download/${VERSION}/checksums.txt.bundle
cosign verify-blob \
--bundle checksums.txt.bundle \
--certificate-identity "https://github.com/garagon/aguara/.github/workflows/release.yml@refs/tags/${VERSION}" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
checksums.txt
sha256sum --check --ignore-missing checksums.txt
For the container:
cosign verify ghcr.io/garagon/aguara:${VERSION#v} \
--certificate-identity "https://github.com/garagon/aguara/.github/workflows/docker.yml@refs/tags/${VERSION}" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com"
The install script checks archive integrity but does not perform this signature-verification step. A verified release identifies the publisher and artifact; it does not guarantee detection of every threat.
Development
Use the Go version required by go.mod and install golangci-lint for the lint target. From a reviewed checkout:
make build
make test
make vet
make lint
make build writes ./aguara. make test runs the Go suite with the race detector, including positive and negative rule examples and saved fuzz inputs. The repository also includes native fuzz targets and benchmarks; see CONTRIBUTING.md and the Makefile for targeted runs.
This repository intentionally contains attack examples and detection fixtures. Scanning the Aguara checkout is not a substitute for running its tests, and findings in those fixtures are not evidence that the scanner itself is compromised.
Contributing
For a bug or false positive, open an issue with the engine version, command, expected result, and a minimal non-sensitive example. Discuss substantial changes before implementation. Detection changes should include positive cases and realistic benign cases, not just additional signatures.
See CONTRIBUTING.md for setup and the pull request process, and CODE_OF_CONDUCT.md for community expectations. Changes go through pull requests and CI. Release history is in CHANGELOG.md.
The previous Aguara Watch observatory is not a supported product surface. Current development focuses on the scanner and its integrations.
Security
Report vulnerabilities in Aguara privately through GitHub Security Advisories, not a public issue. See SECURITY.md for scope and supported versions. Do not include credentials or private project content in public reports.