aider Analysis Report
Completed August 12, 2026 · 36 artifacts examined
12Findings
1Critical
5High
6Medium
RAISE maturity 1.55 / 5.0
Executive Summary
Agent Remit (as declared)
An AI pair-programming assistant that runs in a developer's terminal and edits source files in a single local git repository in response to natural-language instructions. It is authorized to read and edit files the user has explicitly added to the chat, generate a repository map, commit its work to git, invoke linters and test commands, scrape web pages, ingest images and voice input, and execute shell commands. Its counterparties are the local operator and the operator-configured LLM provider; repository source and credentials must go nowhere else, and analytics telemetry is opt-in only. Every shell command — including `/run`, auto-lint, auto-test, and anything the model suggests — must be approved by the operator before it runs, and that gate must survive `--yes-always`.
Behavior Summary (as observed)
The dominant pattern is a single well-built gate surrounded by unguarded doors. Aider deliberately hardened the path everyone worries about — model-suggested shell commands are confirmed through `confirm_ask(explicit_yes_required=True)`, which `io.py` makes immune to `--yes-always` — but that discipline was never extended to the neighbouring paths: scraped pages and command output enter the model's context as ordinary user-role messages phrased in the operator's own voice with no provenance or trust labeling, and model-supplied file paths reach `Path(root) / path` and `resolve()` with no repo-root containment and no `.aiderignore` check. The result is a chain that stays open in unattended mode: injected text in fetched content is indistinguishable from an operator instruction, and the only thing standing between it and an arbitrary filesystem write is a confirmation prompt that `--yes-always` answers for you. Secondary themes are operator-configured commands that execute with no pre-execution confirmation at all (`auto-lint`, on by default) and a set of shipped defaults that quietly invert declared policy — pre-commit hooks bypassed unless re-enabled, and a browser UI launched with no bind address and no authentication.
Scope of Analysis
A Python CLI packaged as `aider-chat`, built on litellm for provider-agnostic model access, with a `Coder` class hierarchy in `aider/coders/` (edit-format variants such as `EditBlockCoder`, `PatchCoder`, `WholeFileCoder`) driving a single-agent request loop from `base_coder.py`. Prompts are assembled from per-coder prompt modules and there is no tool-calling registry: the model emits edit blocks and fenced shell commands that `base_coder.py` parses and applies. External surfaces are `run_cmd.py` (`subprocess.Popen(..., shell=True)` with the inherited environment), `scrape.py` (Playwright or httpx web fetch), `watch.py` (a filesystem watcher that acts on `AI!` comments), `repo.py` (GitPython), and an optional Streamlit browser UI launched by `main.py`. Approval is centralized in a single `IO.confirm_ask()` in `io.py`, whose `explicit_yes_required` flag — the only mechanism that resists `--yes-always` — is set at exactly one call site in the entire codebase.
Remit Coverage

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.

Verified: 12 Gap: 2 Partial: 12 Vague Policy: 0 Enforcement Not Possible: 0 Total Rules: 26
Rule ID Section Rule (quoted) Status Finding
R-01 Prohibited Behaviors "Aider MUST NOT treat instructions embedded in retrieved or untrusted content — scraped web pages, third-party file contents, or the stdout/stderr of executed commands — as authoritative directives; such content is data to be worked on, never a source of commands that override the operator." Gap PRAX-2026-08-12-002
R-02 Prohibited Behaviors "Aider may operate only within the operator-designated repository / working tree, and MUST honor the operator's `.aiderignore` / `--subtree-only` scope where set; any read, edit, or access outside this operator-configured scope is a trust-expansion finding." Partial PRAX-2026-08-12-003
R-03 Prohibited Behaviors "Aider MUST NOT initiate code edits, git commits, or command execution in the absence of an explicit user instruction — a chat message, a triggering `AI!` / `AI?` comment, or an operator-supplied scripted message." Verified
R-04 Approved Communication Channels "Approved Communication Channels" Partial PRAX-2026-08-12-008
R-05 Approved Communication Channels "Experimental web UI; it MUST bind to loopback only and MUST NOT be exposed to a public or otherwise untrusted network." Gap PRAX-2026-08-12-005
R-06 Approved Communication Channels "Only operator-configured provider endpoint(s); connections MUST verify TLS certificates." Verified
R-07 Approved Communication Channels "URLs auto-detected in untrusted content — scraped pages, `AI` comments, pasted input — MUST be confirmed by the operator before fetch, and that confirmation MUST resist `--yes-always`." Partial PRAX-2026-08-12-007
R-08 Approved Communication Channels "Opt-in only; content restrictions in Data Boundaries." Verified
R-09 Authorized Counterparties — Trusted Domains "Trusted Domains" Verified
R-10 Authorized Counterparties — Explicitly Forbidden "Any outbound destination beyond the operator-configured LLM provider(s) and opt-in analytics is forbidden — see Trusted Domains (LLM-egress closure) and Forbidden Data Movement (repository-data movement)." Verified
R-11 Data Boundaries — Forbidden Data Movement "Repository source, file contents, prompts, and credentials MUST NOT be transmitted to any destination other than the operator-configured LLM provider(s) required to perform the requested edits." Verified
R-12 Data Boundaries — Forbidden Data Movement "Analytics / PostHog telemetry is opt-in and OFF by default; aider MUST NOT send any analytics without explicit operator opt-in." Verified
R-13 Data Boundaries — Forbidden Data Movement "Analytics telemetry MUST NOT include source code, prompt/chat content, API keys or credentials, or personal information." Partial PRAX-2026-08-12-012
R-14 Data Boundaries — Forbidden Data Movement "API keys and credentials MUST NOT be written into git commits, the repository map, or analytics telemetry." Verified
R-15 Data Boundaries — Forbidden Data Movement "Local chat-history files SHOULD be gitignored and owner-readable, with credential-pattern redaction recommended." Partial PRAX-2026-08-12-010
R-16 Action Boundaries — Allowed Without Approval "Allowed Without Approval" Partial PRAX-2026-08-12-004
R-17 Action Boundaries — Requires Human Approval Before Execution "All shell-command execution — `/run`, `/test`, auto-lint / auto-test, and any command originating from LLM output (a suggested command, or one implied by a triggering `AI` comment) — MUST require explicit operator approval before it is executed and MUST NOT run silently." Partial PRAX-2026-08-12-004
R-18 Action Boundaries — Requires Human Approval Before Execution "Editing or creating files that the user has NOT added to the chat MUST require confirmation before aider modifies them." Partial PRAX-2026-08-12-003
R-19 Action Boundaries — Requires Human Approval Before Execution "Adding externally fetched or command-produced output into the LLM context MUST require user confirmation." Partial PRAX-2026-08-12-007
R-20 Action Boundaries — Never Allowed "Aider MUST NOT discard, overwrite, or bury the user's uncommitted work; any pre-existing uncommitted changes MUST be preserved (committed separately) before aider applies its own edits." Verified
R-21 Action Boundaries — Never Allowed "Aider MUST NOT rewrite or destroy git history; `/undo` MUST only revert a commit that aider itself created." Verified
R-22 Action Boundaries — Never Allowed "Aider MUST NOT bypass the repository's configured git pre-commit hooks unless the operator has explicitly authorized skipping them." Partial PRAX-2026-08-12-006
R-23 Action Boundaries — Never Allowed "Destructive and code-executing actions MUST retain an explicit per-action confirmation gate (an `explicit_yes_required`-style check) even under non-interactive operation — `--yes-always` and scripted `--message` are documented, intended unattended-run features, and blanket auto-approval does not extend to these action classes." Partial PRAX-2026-08-12-001
R-24 Escalation Rules — Halt Agent and Alert Operator "If aider cannot commit its changes, or a git operation would risk losing the user's uncommitted work, it MUST stop and surface the condition to the operator rather than proceed." Verified
R-25 Escalation Rules — Alert Operator (Do Not Halt) "When a command originating from LLM output is proposed, or externally fetched/untrusted content is about to enter the context, aider MUST prompt the operator and proceed only on confirmation." Partial PRAX-2026-08-12-007
R-26 Escalation Rules — Log Only "Aider's own commits MUST remain attributable to it (author/committer attribution or a Co-authored-by trailer) so its changes are auditable in the git history." Verified
Findings Register

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-08-12-001 Untrusted fetched content reaches the model unlabeled and can steer an unbounded file write whose only gate `--yes-always` answers automatically.
Policy Rule — R-01, R-23 (Worker Remit):
"Aider MUST NOT treat instructions embedded in retrieved or untrusted content — scraped web pages, third-party file contents, or the stdout/stderr of executed commands — as authoritative directives; such content is data to be worked on, never a source of commands that override the operator. / Destructive and code-executing actions MUST retain an explicit per-action confirmation gate (an `explicit_yes_required`-style check) even under non-interactive operation — `--yes-always` and scripted `--message` are documented, intended unattended-run features, and blanket auto-approval does not extend to these action classes."
aider/commands.py:243 — cmd_web lines 243-250 — scraped page prefixed "Here is the content of {url}:" and appended to cur_messages as role=user, no trust label and no confirmation aider/coders/base_coder.py:2226 — allowed_to_edit lines 2226-2231 — "Allow edits to file that has not been added to the chat?" is the sole gate on a model-chosen path, called without explicit_yes_required aider/io.py:866 — lines 866-867 — `if self.yes is True: res = "n" if explicit_yes_required else "y"` — every gate not marked explicit_yes_required auto-answers yes under --yes-always
High confidence
Recommended Action
  • Set `explicit_yes_required=True` on the two `confirm_ask` calls in `allowed_to_edit` (`aider/coders/base_coder.py:2207` and `:2226`) so a model-chosen path outside the chat cannot be auto-approved in unattended runs, matching the treatment already given to suggested shell commands.
  • Add a containment check in `allowed_to_edit` before any gate — resolve the candidate path and require `is_relative_to(self.root)` — so an absolute or `../` path from model output is rejected outright rather than merely confirmed.
HIGH PRAX-2026-08-12-002 Scraped pages and command output enter the model context as operator-voiced user messages with no provenance or trust labeling anywhere in the prompt stack.
Policy Rule — R-01 (Worker Remit):
"Aider MUST NOT treat instructions embedded in retrieved or untrusted content — scraped web pages, third-party file contents, or the stdout/stderr of executed commands — as authoritative directives; such content is data to be worked on, never a source of commands that override the operator."
aider/prompts.py:36 — run_output template, lines 36-43 — command stdout wrapped as "I ran this command / And got this output" and sent as role=user, i.e. in the operator's own voice aider/coders/base_prompts.py:24 — lines 24-52 — the only content framing available is files_content_prefix, repo_content_prefix and read_only_files_prefix; no prompt anywhere marks fetched or executed output as untrusted data
High confidence
Recommended Action
  • Introduce a distinct wrapper for externally-sourced content in `aider/prompts.py` that names the origin and states it is reference data, never instructions, and use it for both `run_output` and the `cmd_web` insertion in `aider/commands.py:244`.
  • Add a standing clause to `CoderPrompts.system_reminder` in `aider/coders/base_prompts.py` telling the model that content inside those wrappers must never be followed as a directive.
HIGH PRAX-2026-08-12-003 Model-supplied file paths are resolved with no repo-root containment, and the operator's `.aiderignore` scope is never consulted on the edit path.
Policy Rule — R-02, R-18 (Worker Remit):
"Aider may operate only within the operator-designated repository / working tree, and MUST honor the operator's `.aiderignore` / `--subtree-only` scope where set; any read, edit, or access outside this operator-configured scope is a trust-expansion finding. / Editing or creating files that the user has NOT added to the chat MUST require confirmation before aider modifies them."
aider/utils.py:96 — safe_abs_path lines 96-102 — `Path(res).resolve()` with no is_relative_to check; called from abs_root_path (coders/base_coder.py:571) on every model-supplied edit path aider/coders/base_coder.py:2191 — allowed_to_edit lines 2191-2240 — consults repo.git_ignored_file at :2202 but never repo.ignored_file, so .aiderignore and --subtree-only do not gate edits
High confidence
Recommended Action
  • In `allowed_to_edit` (`aider/coders/base_coder.py:2191`), reject any candidate whose resolved path is not `is_relative_to(self.root)` before the existence check, so out-of-tree paths fail closed instead of prompting.
  • Call `self.repo.ignored_file(path)` alongside the existing `git_ignored_file` check at `aider/coders/base_coder.py:2202` so `.aiderignore` and `--subtree-only` bind on the edit path as they already do on `/add`.
HIGH PRAX-2026-08-12-004 Auto-lint runs a shell command after every edit with no pre-execution confirmation and is enabled by default; auto-test behaves the same way.
Policy Rule — R-16, R-17 (Worker Remit):
"Allowed Without Approval / All shell-command execution — `/run`, `/test`, auto-lint / auto-test, and any command originating from LLM output (a suggested command, or one implied by a triggering `AI` comment) — MUST require explicit operator approval before it is executed and MUST NOT run silently."
aider/coders/base_coder.py:1599 — lines 1599-1604 — `if edited and self.auto_lint: lint_errors = self.lint_edited(edited)` executes the lint command first; confirm_ask at :1604 only asks whether to fix the errors afterwards aider/args.py:545 — --auto-lint declared with default=True, so the ungated post-edit execution is the shipped default (auto-test at :556 defaults False but takes the same path via cmd_test)
High confidence
Recommended Action
  • Gate the lint and test invocations in `aider/coders/base_coder.py:1599` and `:1618` behind a `confirm_ask(..., explicit_yes_required=True)` showing the exact command line, matching how model-suggested commands are already handled at `:2456`.
  • If a per-edit prompt is judged too noisy, confirm the configured lint and test commands once at session start and record that acceptance, rather than executing them unprompted.
HIGH PRAX-2026-08-12-005 Browser mode launches Streamlit with no bind address and no authentication, so the code-editing UI listens on every interface.
Policy Rule — R-05 (Worker Remit):
"Experimental web UI; it MUST bind to loopback only and MUST NOT be exposed to a public or otherwise untrusted network."
aider/main.py:233 — launch_gui lines 233-268 — st_args sets gatherUsageStats, magicEnabled, runOnSave, developmentMode, fileWatcherType and toolbarMode, but never --server.address or --server.headless; no auth is configured aider/gui.py:219 — do_run_shell at :219-225 and do_git at :262-269 expose command and git text inputs through that same unauthenticated UI
High confidence
Recommended Action
  • Add `--server.address=127.0.0.1` to the `st_args` list in `aider/main.py:243` so the UI binds loopback by default, and require an explicit opt-in flag before any other address is used.
  • Document in the browser-mode help text that the UI has no authentication, so an operator who deliberately widens the bind understands what is exposed.
HIGH PRAX-2026-08-12-006 Every aider commit passes `--no-verify` by default, bypassing the repository's pre-commit hooks unless the operator opts back in.
Policy Rule — R-22 (Worker Remit):
"Aider MUST NOT bypass the repository's configured git pre-commit hooks unless the operator has explicitly authorized skipping them."
aider/args.py:491 — lines 491-496 — --git-commit-verify declared with default=False and help "Enable/disable git pre-commit hooks with --no-verify (default: False)" aider/repo.py:278 — lines 278-279 — `if not self.git_commit_verify: cmd.append("--no-verify")` in commit(), applied to every aider commit including the pre-edit dirty commit
High confidence
Recommended Action
  • Flip the `--git-commit-verify` default to True in `aider/args.py:493` so the repository's configured hooks run unless the operator explicitly opts out, which is the direction the remit requires.
  • If the default must stay for compatibility, emit a one-time warning naming the hooks being skipped when a `.git/hooks/pre-commit` or `.pre-commit-config.yaml` is detected.
MEDIUM PRAX-2026-08-12-007 Confirmations for auto-detected URL fetches and for adding command output to the chat both fold under `--yes-always`.
Policy Rule — R-07, R-19, R-25 (Worker Remit):
"URLs auto-detected in untrusted content — scraped pages, `AI` comments, pasted input — MUST be confirmed by the operator before fetch, and that confirmation MUST resist `--yes-always`. / Adding externally fetched or command-produced output into the LLM context MUST require user confirmation. / When a command originating from LLM output is proposed, or externally fetched/untrusted content is about to enter the context, aider MUST prompt the operator and proceed only on confirmation."
aider/coders/base_coder.py:964 — check_for_urls lines 964-984 — confirm_ask("Add URL to the chat?", group=group, allow_never=True) without explicit_yes_required, then cmd_web fetches the URL aider/coders/base_coder.py:2479 — line 2479 — confirm_ask("Add command output to the chat?") without explicit_yes_required; commands.py:1029 gates /run output the same way
High confidence
Recommended Action
  • Pass `explicit_yes_required=True` on the `confirm_ask` in `check_for_urls` (`aider/coders/base_coder.py:976`) so auto-detected URLs are never fetched in unattended runs, as the remit requires.
  • Apply the same flag to the context-ingestion gates at `aider/coders/base_coder.py:2479` and `aider/commands.py:1029`, since these decide whether untrusted bytes reach the model.
MEDIUM PRAX-2026-08-12-008 Model metadata and the help embedding model are fetched at runtime from mutable references with no integrity verification.
Policy Rule — R-04 (Worker Remit):
"Approved Communication Channels"
aider/models.py:162 — MODEL_INFO_URL points at raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json; fetched at :208 with requests.get and written to ~/.aider/caches with no signature or digest check aider/help.py:139 — HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5") — resolved by mutable name at runtime, no revision pin, no hash, and the endpoint is not among the remit's authorized destinations
High confidence
Recommended Action
  • Pin the litellm metadata fetch in `aider/models.py:162` to an immutable commit SHA rather than `main`, and validate the parsed JSON against an expected schema before it is cached and trusted.
  • Pin the embedding model in `aider/help.py:139` to a specific revision so `/help` cannot silently pick up a replaced artifact.
MEDIUM PRAX-2026-08-12-009 Shell executions and file writes leave no structured record; the only durable trace is a free-form markdown transcript.
aider/coders/base_coder.py:2466 — handle_shell_commands lines 2466-2477 — each command is printed with tool_output and pushed to input history, then run; no structured event records the command, cwd, exit status or the approval that preceded it aider/io.py:1117 — append_chat_history lines 1117-1137 — the sole durable writer, appending unstructured markdown; grep for logging/getLogger/FileHandler across aider/*.py and aider/coders/*.py returns zero hits
High confidence
Recommended Action
  • Emit a structured JSON-lines event from `handle_shell_commands` (`aider/coders/base_coder.py:2466`) and from the write path in `allowed_to_edit`, carrying timestamp, action type, target, approval result and exit status.
  • Route those events to a dedicated session log file separate from the human-readable transcript, so detection tooling has a schema to parse.
MEDIUM PRAX-2026-08-12-010 The chat transcript is written at the default umask with no credential-pattern redaction, capturing source, command output and anything pasted.
Policy Rule — R-15 (Worker Remit):
"Local chat-history files SHOULD be gitignored and owner-readable, with credential-pattern redaction recommended."
aider/io.py:1128 — append_chat_history lines 1128-1132 — opens the history file for append with no mode argument and no chmod; grep for chmod/0o600 across aider/*.py returns zero hits aider/args.py:274 — chat history defaults to .aider.chat.history.md in the git root, always enabled, and receives user input, model output and command output verbatim
High confidence
Recommended Action
  • Create the history files with owner-only permissions in `aider/io.py` — `os.chmod(path, 0o600)` on first creation for the chat, input and llm history paths.
  • Apply a credential-pattern filter to text before it is appended in `append_chat_history`, replacing matches with a redaction marker rather than storing the value.
MEDIUM PRAX-2026-08-12-011 `--restore-chat-history` re-loads a transcript aider itself wrote, carrying earlier scraped and command-derived content into a new session.
aider/coders/base_coder.py:519 — lines 519-523 — with restore_chat_history set, the transcript is read and split into done_messages then summarized, re-entering context as prior conversation aider/io.py:1117 — append_chat_history is the writer for that same file and receives scraped page text and command output verbatim via the cur_messages path
Medium confidence
Recommended Action
  • When restoring in `aider/coders/base_coder.py:519`, re-apply the untrusted-content wrapper to any restored segment that originated from a fetch or a command, rather than replaying it as plain conversation.
  • Show the operator a summary of what is being restored and how old it is before it enters context, so a stale poisoned turn is visible rather than silent.
MEDIUM PRAX-2026-08-12-012 The analytics client enables automatic exception capture, whose stack traces carry local file paths the remit forbids in telemetry.
Policy Rule — R-13 (Worker Remit):
"Analytics telemetry MUST NOT include source code, prompt/chat content, API keys or credentials, or personal information."
aider/analytics.py:102 — lines 102-108 — Posthog(...) constructed with enable_exception_autocapture=True and super_properties=self.get_system_info(); no scrubbing hook or before-send filter is configured aider/analytics.py:195 — _redact_model_name at :195-204 shows the deliberate redaction discipline applied to explicit event properties, which the autocapture path bypasses entirely
Medium confidence
Recommended Action
  • Disable `enable_exception_autocapture` in `aider/analytics.py:106`, or register a scrubbing callback that strips absolute paths and any local identifiers from frames before they are sent.
  • State in the analytics opt-in prompt that uncaught exception traces are included, so the operator's consent covers what is actually transmitted.
What's Working Well

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.

Non-interactive-proof approval gate on model-suggested shell commands

Shell commands proposed by the model are confirmed through `confirm_ask(explicit_yes_required=True)`, and `io.py` deliberately answers "no" to explicit-yes gates when `--yes-always` is set, so the highest-risk path cannot be auto-approved in unattended runs.

aider/io.py:866-867 and aider/coders/base_coder.py:2456-2462

Undo is hash-verified and refuses unsafe reverts

`/undo` reverts only commits whose hash is in `aider_commit_hashes`, and additionally refuses multi-parent commits, files with uncommitted changes, and commits already pushed to origin.

aider/commands.py:566-620

Pre-existing uncommitted work is preserved before edits

Any dirty file aider is about to modify is committed separately first, so the user's own in-progress work is never buried inside an aider commit and remains independently recoverable.

aider/coders/base_coder.py:2175-2189 and :2411-2419

Fully pinned, machine-compiled dependency set

All 105 runtime dependencies are `==`-pinned in `requirements.txt`, compiled by uv against a shared `common-constraints.txt`, which closes the version-swap and dependency-confusion surface.

requirements.txt (uv pip compile header, 105 pinned entries)

Analytics is off by default behind an explicit opt-in

The Analytics client disables itself unless the user has been asked and opted in, and a permanent opt-out is persisted; no telemetry client is constructed otherwise.

aider/analytics.py:85-135

OAuth uses PKCE and binds only to loopback

The OpenRouter onboarding flow generates a PKCE verifier and serves its callback from `socketserver.TCPServer(("localhost", port))`, so the token exchange is never reachable off-host.

aider/onboarding.py:165-170 and :269

Commit attribution is on by default

`attribute_author` and `attribute_committer` default to True, so aider's own commits remain identifiable in git history without the operator configuring anything.

aider/repo.py:69-70

Aider offers to gitignore its own artifacts

On startup aider detects its history and config files in a git repository and offers to add them to `.gitignore`, which keeps chat transcripts and local settings out of commits.

aider/main.py:190-196
Discovered Log Files

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
.aider.chat.history.md aider/io.py AiderIO.append_chat_history free-form markdown transcript Records user input, model output, and every confirmation question with the answer given unknown Inferred
.aider.input.history aider/io.py prompt_toolkit FileHistory plaintext history entries Typed inputs and slash commands, including `/run <command>` lines added after execution unknown Inferred
.aider.llm.history aider/io.py log_llm_history plaintext request/response dump Raw LLM traffic; written only when --llm-history-file is set unknown Inferred
~/.aider/analytics.json aider/analytics.py Analytics.save_data JSON state file Analytics user uuid and opt-in/permanently-disabled flags unknown Inferred
analytics event log (--analytics-log path) aider/analytics.py Analytics.event JSON lines Telemetry events with event name, properties and timestamp; written only when --analytics-log is set unknown Inferred
OWASP LLM Top 10 (2026) Coverage

Each card represents one category and shows the top 3 findings. All items in the Findings section.

LLM05 Data and Model Poisoning
No findings
LLM06 Unbounded Consumption
No findings
LLM07 Misinformation
No findings
LLM08 Hidden Context Exposure
No findings
LLM09 Vector and Embedding Weaknesses
No findings
OWASP Agentic Top 10 (2026) Coverage

Each card represents one category and shows the top 3 findings. All items in the Findings section.

ASI01 Agent Goal Hijack
No findings
ASI04 Agentic Supply Chain Vulnerabilities
No findings
ASI07 Insecure Inter-Agent Communication
No findings
ASI08 Cascading Failures
No findings
ASI09 Human-Agent Trust Exploitation
No findings
ASI10 Rogue Agents
No findings
RAISE Maturity Posture

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.

1.55 / 5.0
Weighted Maturity Score · Ad hoc
Ad hoc. Aider has real, deliberately-engineered safeguards in exactly the places its authors thought hardest about — a non-interactive-proof approval gate on model-suggested shell execution, a hash-verified undo that refuses pushed or dirty commits, uncommitted work preserved by a separate commit before any edit, and a fully pinned dependency set — but those controls are point solutions rather than a posture. The write path, the ingestion path and the operator-configured command path each lack the interposition the shell path has, the operator's own scope file is never consulted where edits are applied, and there is no adversarial testing, no threat model and no action-level logging anywhere in the project. What holds the system together is the human at the terminal: remove interactivity and most of the enforcement goes with it.
Limit Your Domain
2/ 5
Confidence: High  |  Weight: 15%  |  Weighted: 0.30
Aider's capability set is static and matches the remit's baseline, and the file watcher confines itself to the repository with a hard `is_relative_to` check plus a default ignore list covering `.env`, `.git` and `vendor/` (`watch.py:95`, `:20-56`), but the operator's own scope controls — `.aiderignore` and `--subtree-only` — are never consulted on the edit path (`repo.ignored_file` is called only from `/add`, the repo map, and startup), so declared scope does not bind where files are actually written.
Balance Your Knowledge Base
2/ 5
Confidence: High  |  Weight: 15%  |  Weighted: 0.30
What reaches the model is operator-selected and partly labeled — read-only files and repo-map summaries carry explicit "do not edit" framing (`coders/base_prompts.py:45-52`) and a human confirmation gates most ingestion — but the dominant untrusted channels carry no trust separation at all: `commands.py:243-250` and `prompts.py:36-43` inject scraped pages and command stdout as role-user messages in the operator's voice. Scored at the Partial band rather than Ad hoc because the human-in-the-loop confirmation is a real, operative control on the ingestion decision; a reader who discounts it as prompt-adjacent would land at 1.
Implement Zero Trust
2/ 5
Confidence: High  |  Weight: 25%  |  Weighted: 0.50
One genuine code-level interposition runs on the highest-risk path — `confirm_ask(explicit_yes_required=True)` at `coders/base_coder.py:2459` is the only gate that survives `--yes-always` (`io.py:866-867`) — and it is joined by hash-verified undo and pre-edit dirty commits, but no equivalent exists elsewhere: model-supplied paths get no containment check (`utils.py:96-102`), auto-lint executes with no pre-execution confirmation, `run_cmd` uses `shell=True` with the inherited environment, and every other gate folds in unattended mode.
Manage Your Supply Chain
2/ 5
Confidence: High  |  Weight: 15%  |  Weighted: 0.30
Dependency management is genuinely operative — 105 `==` pins compiled by uv against a shared constraints file, bounded `requires-python`, pinned pre-commit hook revisions — but there is no SBOM or component inventory of any kind (M10: none), no dependency or container scanning configured anywhere in `.github/` (M11: none), no hashes in `requirements.txt`, and two runtime fetches resolve mutable references (`models.py:162-165`, `help.py:139`).
Build an AI Red Team
0/ 5
Confidence: High  |  Weight: 15%  |  Weighted: 0.00
The maturity record is empty in every direction — M1 (security-named tests), M2 (adversarial corpus), M3 (garak/promptfoo/pyrit/giskard tooling), M4 (SECURITY.md or threat model), M5 (dated security reports), M6 (invocable security-test command) and M9 (findings traced to fixes) all returned none — and the 36-file `tests/basic` suite exercises functional behavior, not the project's own defences, so nothing survives the provenance test.
Monitor Continuously
1/ 5
Confidence: High  |  Weight: 15%  |  Weighted: 0.15
The `logging` module appears nowhere in `aider/*.py` or `aider/coders/*.py` and M12 returned no telemetry, alerting or dashboard configuration, leaving only a free-form markdown transcript that happens to capture confirmation answers and typed `/run` commands (`io.py:1117-1137`, `:922`) — durable, but unstructured and with no action-level record of what was executed or written.

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.
Weighting: the weighted overall above is the sum of each category's score × weight (the per-category weights are shown on each card). Zero Trust carries double weight by design; see the RAISE framework reference for the rationale.