yaah Analysis Report
Completed August 12, 2026 · 48 artifacts examined
13Findings
2Critical
5High
6Medium
RAISE maturity 1.70 / 5.0
Executive Summary
Agent Remit (as declared)
yaah is a Go CLI and runtime that generates coding-agent configuration — hooks, skills, agents, slash commands, MCP and LSP servers — for Claude Code, OpenCode, Codex CLI and GitHub Copilot CLI, and then runs alongside those agents as a hook dispatcher, a stdio MCP server and a per-session audit store. Its authorized surface is exactly seven MCP tools (yaah_scan_secrets, yaah_lint, yaah_check_command, yaah_doctor, yaah_session_info, yaah_planning_status, yaah_planning_init) and five hook handlers (linter, command-guard, secret-scanner, comment-checker, session-logger), talking only over stdio, the local filesystem, and git-over-HTTPS to pinned source repositories. The command guard and the secret scanner are declared fail-closed safety controls that must never be removed or downgraded to advisory mode, credentials must never be embedded in generated configuration, and yaah must never self-trigger its own workflow commands.
Behavior Summary (as observed)
The dominant pattern is a harness that enforces its safety model on the path it was built for and silently drops it everywhere else. The command guard and secret scanner really do block on the Claude Code path — Block becomes exit 2 — but the guard is seven regexes over a shell, the scanner runs at PostToolUse so the credential is already on disk when it fires, and pkg/generator/hookmap.go maps neither event for the Codex target, so yaah generate --agent codex emits a working config with no command guard and no secret scanner at all, offering only model-elective MCP tools in their place. The second theme is capability and credential material flowing outward through generated files: NewNotion() interpolates an API token into an MCP env value that every generator writes verbatim into repository config, and every /yaah:* workflow command — including the one whose own text says it runs "without human intervention" — ships model-invocable because disable-model-invocation is supported by the generator and set by nothing.
Scope of Analysis
A 13,400-line Go 1.25 module with two direct dependencies, built on an Interface to Registry to Generator pattern: pkg/harness wires seven registries and dispatches hook events, pkg/hooks/handlers holds the five built-in handlers, pkg/mcpserver serves the seven tools over stdio, and four generators in pkg/generator emit each target agent's native config. Blocking is real — a handler returning Block makes yaah hook exit 2 — and session state lands in .claude/sessions/<id>.json through an atomic-write store with traversal-safe identifiers. Remote skills and agents are fetched by pkg/gitcache from commit-SHA-pinned GitHub repositories and written into the host agent's .claude/ tree, while the built-in MCP defaults reach outward to an npm-installed Context7 server and Pulumi's hosted endpoint. The divergences from the remit sit at the edges of that structure: the Codex generator has no PreToolUse or PostToolUse mapping, the secret scanner is a PostToolUse handler, and the Notion provider carries an API token in a config field that every generator serializes to disk.
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: 16 Gap: 3 Partial: 12 Vague Policy: 0 Enforcement Not Possible: 0 Total Rules: 31
Rule ID Section Rule (quoted) Status Finding
R-01 Prohibited Behaviors "yaah MUST NEVER treat the content of fetched remote skills or agents, MCP tool descriptions, or scanned/linted file contents as instructions that change its own behavior or safety decisions — such content is untrusted data, never authority over yaah." Verified
R-02 Prohibited Behaviors "yaah MUST NEVER auto-invoke its /yaah:* workflow commands, including the autonomous workflow, without an explicit user invocation; the model must not self-trigger them." Gap PRAX-2026-08-12-002
R-03 Prohibited Behaviors "yaah MUST NEVER run with its command-guard or secret-scanner safety hooks removed, disabled, or downgraded to a non-blocking / advisory mode; these are safety controls, not optional lint." Partial PRAX-2026-08-12-003
R-04 Approved Communication Channels "stdio only; no network bind" Verified
R-05 Approved Communication Channels "Within the target repository and the yaah cache directory" Partial PRAX-2026-08-12-008
R-06 Approved Communication Channels "Fetch and cache only; sources must be pinned (see Authorized Counterparties)" Verified
R-07 Approved Communication Channels "Only servers the operator configured" Partial PRAX-2026-08-12-007
R-08 Approved Communication Channels "Disabled unless the operator has explicitly authorized it" Verified
R-09 Approved Communication Channels "Approved Communication Channels" Verified
R-10 Authorized Counterparties — Trusted Services / Integrations "Any skill, agent, MCP server, plugin, or marketplace wired into generated configuration that falls outside this operator-configured catalog is an unauthorized trust expansion." Verified
R-11 Authorized Counterparties — Trusted Domains "Trusted Domains" Partial PRAX-2026-08-12-007
R-12 Authorized Counterparties — Explicitly Forbidden "Fetching default or shipped remote skills/agents from mutable refs (branches) rather than immutable refs (a commit SHA or version tag)." Verified
R-13 Authorized Counterparties — Explicitly Forbidden "Wiring in any skill, agent, MCP server, marketplace, or plugin outside the operator-configured vetted catalog (see the Closure rule under Trusted Services / Integrations)." Verified
R-14 Tools and Capabilities — Allowed Tools (Known Good Baseline) "Closure rule: any tool the runtime or MCP server exposes, or any hook handler it runs, that is not in this baseline is an undeclared capability." Verified
R-15 Tools and Capabilities — Restricted Tools (Require Approval Before Use) "Restricted Tools (Require Approval Before Use)" Partial PRAX-2026-08-12-001
R-16 Tools and Capabilities — Forbidden Tools "No MCP tool may execute arbitrary shell commands outside the command guard, and no tool may return detected secret values in cleartext." Partial PRAX-2026-08-12-006
R-17 Data Boundaries — Allowed Data Sources "Allowed Data Sources" Partial PRAX-2026-08-12-008
R-18 Data Boundaries — Forbidden Data Movement "Detected secret values MUST NEVER be written into session logs, findings records, generated configuration, or any yaah output in cleartext — secrets are referenced by location and pattern only." Verified
R-19 Data Boundaries — Forbidden Data Movement "Credentials, API tokens, and OAuth secrets MUST NEVER be embedded in generated configuration files." Gap PRAX-2026-08-12-001
R-20 Data Boundaries — Forbidden Data Movement "Credentials, API tokens, and OAuth secrets MUST NEVER be committed to the repository." Partial PRAX-2026-08-12-001
R-21 Data Boundaries — Forbidden Data Movement "Credentials, API tokens, and OAuth secrets MUST be sourced from environment variables or a secrets manager." Gap PRAX-2026-08-12-001
R-22 Data Boundaries — Forbidden Data Movement "Repository contents, scanned file contents, and session audit data MUST NEVER be transmitted to any destination other than the local filesystem or an explicitly-configured trusted integration." Verified
R-23 Action Boundaries — Allowed Without Approval "Allowed Without Approval" Verified
R-24 Action Boundaries — Requires Human Approval Before Execution "Enabling any feature that makes outbound network calls or spawns an autonomous subagent (e.g. the experimental fact-checker): such features MUST be off by default and enabled only by explicit operator opt-in." Partial PRAX-2026-08-12-007
R-25 Action Boundaries — Never Allowed "A file edit that introduces a hardcoded credential MUST NEVER be written — the secret scanner blocks it (fail closed)." Partial PRAX-2026-08-12-005
R-26 Action Boundaries — Never Allowed "A shell command matching the dangerous-command denylist (e.g. rm -rf /, force-push to a protected branch, git reset --hard, destructive SQL) MUST NEVER be allowed to execute — the command guard blocks it (fail closed)." Partial PRAX-2026-08-12-004
R-27 Action Boundaries — Never Allowed "Session files MUST NEVER be read or written at paths derived from unvalidated session identifiers; identifiers containing path separators or the special values . / .. are rejected (path-traversal prevention)." Verified
R-28 Action Boundaries — Never Allowed "Generated configuration MUST NEVER weaken the host coding agent's permission/sandbox posture: it may not place the host into a permission-bypassing (bypassPermissions / dontAsk) or sandbox-disabled mode by default, nor drop the host below its stated minimum permission/sandbox posture." Verified
R-29 Escalation Rules — Halt Agent and Alert Operator "When the command guard matches a dangerous command, or the secret scanner detects a credential in an edit, the hook must block the operation and record the block (with its reason) to the session audit log." Verified
R-30 Escalation Rules — Alert Operator (Do Not Halt) "yaah doctor reports missing dependencies or misconfiguration for the operator to resolve; this surfaces a warning without blocking generation." Verified
R-31 Escalation Rules — Log Only "Session lifecycle events, tool calls (including MCP-server tool invocations served via yaah serve), blocked commands, and file modifications are recorded to .claude/sessions/<id>.json as a durable, structured audit trail." Partial PRAX-2026-08-12-010
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 The Notion MCP provider interpolates the operator's API token into a config value that every generator writes verbatim into repository files.
Policy Rule — R-15, R-19, R-20, R-21 (Worker Remit):
"Restricted Tools (Require Approval Before Use) / Credentials, API tokens, and OAuth secrets MUST NEVER be embedded in generated configuration files. / Credentials, API tokens, and OAuth secrets MUST NEVER be committed to the repository. / Credentials, API tokens, and OAuth secrets MUST be sourced from environment variables or a secrets manager."
pkg/mcp/providers/notion.go:28 — The apiToken field is concatenated into the OPENAPI_MCP_HEADERS JSON string as a literal Bearer value inside the Env map at lines 27-29, with no env-var placeholder pkg/generator/settings.go:220 — GenerateClaudeSettings copies srv.Env into claudeMCPServer.Env unchanged before MarshalIndent writes the file; codex.go:47, copilot.go:46 and opencode.go:36 do the same for their targets
High confidence
Recommended Action
  • Change Notion.Server() to emit an environment-variable reference (e.g. NOTION_TOKEN) rather than the literal value, and have the generators resolve credentials at agent start-up instead of at generation time.
  • Add a generator-side guard that refuses to serialize any Env or Headers value matching a credential pattern, so a future provider cannot reintroduce the same path.
CRITICAL PRAX-2026-08-12-002 Every generated /yaah:* command, including the autonomous phase runner, is model-invocable because disable-model-invocation is never set.
Policy Rule — R-02 (Worker Remit):
"yaah MUST NEVER auto-invoke its /yaah:* workflow commands, including the autonomous workflow, without an explicit user invocation; the model must not self-trigger them."
pkg/commands/builtins/autonomous.go:18 — Advanced() returns commands.CommandAdvanced{Context: "fork"} only — DisableModelInvocation is left false, and the command body at lines 27-50 runs the phase lifecycle "without pausing for user input" pkg/harness/harness.go:602 — buildCommandMarkdown writes disable-model-invocation into the generated markdown when opts.DisableModelInvocation is set — the emitter exists and no caller ever sets the flag
High confidence
Recommended Action
  • Set DisableModelInvocation: true in AutonomousCommand.Advanced() and in every other /yaah:* command whose body performs writes, so the generated frontmatter blocks model invocation.
  • Add a test in pkg/commands/builtins asserting that every registered built-in command reports DisableModelInvocation true, so a new command cannot ship without it.
HIGH PRAX-2026-08-12-003 Codex-target generation silently emits a config in which neither the command guard nor the secret scanner ever runs.
Policy Rule — R-03 (Worker Remit):
"yaah MUST NEVER run with its command-guard or secret-scanner safety hooks removed, disabled, or downgraded to a non-blocking / advisory mode; these are safety controls, not optional lint."
pkg/generator/hookmap.go:30 — hookMappings entries for HookPreToolUse (lines 30-34) and HookPostToolUse (lines 35-39) define Claude, OpenCode and Copilot names but no Codex field, so CodexEventName returns the empty string for both pkg/generator/codex.go:88 — GenerateHooks loop, lines 88-94 — "if codexEvent == \"\" ... continue" drops both events without emitting a warning or a degraded-mode notice
High confidence
Recommended Action
  • Map PreToolUse and PostToolUse to their Codex equivalents in hookmap.go, or, if Codex genuinely has no equivalent event, make CodexGenerator.GenerateHooks fail loudly when a safety-control handler cannot be wired.
  • Add a generator test asserting that for every target, the emitted hook set includes an event that dispatches the command guard and the secret scanner.
HIGH PRAX-2026-08-12-004 The fail-closed command guard is seven regexes over a shell, so trivial rewrites of every listed danger pass.
Policy Rule — R-26 (Worker Remit):
"A shell command matching the dangerous-command denylist (e.g. rm -rf /, force-push to a protected branch, git reset --hard, destructive SQL) MUST NEVER be allowed to execute — the command guard blocks it (fail closed)."
pkg/hooks/handlers/guard.go:29 — NewCommandGuard, lines 29-36 — the complete denylist is seven patterns; the delete rule requires the exact -rf token and the push rule the --force long form, both re-run against the bypass forms named above pkg/hooks/handlers/guard.go:86 — Execute matches only the flat string returned by input.BashCommand(); there is no argv parsing, no allowlist, and no default-deny path for unrecognised commands
High confidence
Recommended Action
  • Replace the free-text denylist with argv-level parsing plus an allowlist of permitted binaries and flags for the destructive verbs (rm, git push, dd, mkfs), so unrecognised forms are denied rather than allowed.
  • Add table-driven tests in pkg/hooks/handlers covering the known bypass forms of each listed rule, so a pattern change cannot silently reopen one.
HIGH PRAX-2026-08-12-005 The secret scanner is a PostToolUse handler, so a credential-bearing edit is already on disk before the block fires.
Policy Rule — R-25 (Worker Remit):
"A file edit that introduces a hardcoded credential MUST NEVER be written — the secret scanner blocks it (fail closed)."
pkg/hooks/handlers/secretscan.go:68 — Events() returns only schema.HookPostToolUse, and ScanFile at line 96 opens the path from disk — the edit has already been applied when detection runs pkg/hooks/handlers/secretscan.go:140 — On a hit the handler returns Result{Error: ..., Block: true} with advice text; there is no revert, quarantine, or restore of the pre-edit content
High confidence
Recommended Action
  • Move credential detection to a PreToolUse handler that scans the proposed tool_input content for Edit/Write/MultiEdit, keeping the PostToolUse pass as a backstop for out-of-band writes.
  • If the pre-write scan cannot be added, have the PostToolUse handler restore the file's prior content (or write it to a quarantine path) when it blocks, so the block is fail-closed in effect and not only in message.
HIGH PRAX-2026-08-12-006 The yaah_lint MCP tool spawns external binaries on a model-supplied path without consulting the command guard.
Policy Rule — R-16 (Worker Remit):
"No MCP tool may execute arbitrary shell commands outside the command guard, and no tool may return detected secret values in cleartext."
pkg/mcpserver/tools.go:85 — addLintTool handler, lines 85-95 — args.FilePath and args.Profile come straight from the MCP caller and cwd is set to filepath.Dir(args.FilePath) before LintFile is invoked pkg/hooks/handlers/linter.go:228 — exec.CommandContext(ctx, args[0], args[1:]...) runs each profile step, where the Biome, Prettier and TypeScript profiles have "npx" as args[0]
High confidence
Recommended Action
  • Route every profile step through CommandGuard.CheckCommand before exec.CommandContext, and refuse to run when the guard reports unsafe.
  • Constrain yaah_lint to paths inside the invoking project root and drop npx-based profiles in favour of resolved local binaries, so a tool call cannot trigger a package install.
HIGH PRAX-2026-08-12-007 Default generation wires outbound MCP servers that install unpinned npm packages at every launch, with no operator opt-in.
Policy Rule — R-07, R-11, R-24 (Worker Remit):
"Only servers the operator configured / Trusted Domains / Enabling any feature that makes outbound network calls or spawns an autonomous subagent (e.g. the experimental fact-checker): such features MUST be off by default and enabled only by explicit operator opt-in."
pkg/mcp/providers/context7.go:22 — Server() returns Command "npx" with Args {"-y", "@context7/mcp"} — no version specifier, and -y suppresses the install prompt; notion.go:25 uses the same unpinned form pkg/harness/defaults.go:192 — AllDefaults sets EnableContext7 and EnablePulumiMCP true (lines 192-193), so both outbound servers appear in generated config without any operator action
High confidence
Recommended Action
  • Pin the npm package to an exact version or digest in context7.go and notion.go (for example @context7/mcp@1.2.3) so the launched code matches what was reviewed.
  • Default EnableContext7, EnablePulumiMCP and any future outbound provider to false in AllDefaults, requiring the same explicit opt-in the fact-check hooks already use.
MEDIUM PRAX-2026-08-12-008 MCP tool arguments reach the filesystem with no containment check, so reads and directory creation escape the declared data boundary.
Policy Rule — R-05, R-17 (Worker Remit):
"Within the target repository and the yaah cache directory / Allowed Data Sources"
pkg/mcpserver/tools.go:66 — scanner.ScanFile(args.FilePath) is called on the raw caller-supplied path with no root check; the returned findings expose file, line and pattern label for any readable file pkg/mcpserver/tools.go:377 — addPlanningInitTool, lines 377-393 — planningDir is filepath.Join(args.ProjectDir, ".planning") and os.MkdirAll creates the tree wherever that resolves
High confidence
Recommended Action
  • Resolve every caller-supplied path with filepath.Abs plus filepath.Rel against the server's project root and reject anything that escapes it, mirroring session.sanitizeID.
  • Default project_dir to the server's working directory and reject the argument entirely when it names a path outside that root.
MEDIUM PRAX-2026-08-12-009 Remote skill markdown and its third-party frontmatter are written into the host agent's context verbatim, while remote agents get theirs stripped.
pkg/skills/remote.go:100 — resolve assigns r.content = content from gitcache with no frontmatter handling, unlike agents/remote.go:104 which calls stripFrontmatter on the same kind of payload pkg/harness/harness.go:501 — contentHasFrontmatter check, lines 501-503 — when the remote body starts with "---" the generator emits no frontmatter of its own and writes the third-party block through unchanged
High confidence
Recommended Action
  • Apply stripFrontmatter to remote skill content in RemoteSkill.resolve and rebuild the frontmatter from yaah's own metadata, matching the remote-agent path.
  • If remote frontmatter must be preserved, parse it and allow only a fixed key set, dropping allowed-tools, agent and model unless the local catalog entry declares them.
MEDIUM PRAX-2026-08-12-010 The session audit trail never records MCP-server tool invocations and never populates its own declared Findings channel.
Policy Rule — R-31 (Worker Remit):
"Session lifecycle events, tool calls (including MCP-server tool invocations served via yaah serve), blocked commands, and file modifications are recorded to .claude/sessions/<id>.json as a durable, structured audit trail."
pkg/mcpserver/tools.go:226 — addSessionInfoTool is the only tool that touches the store and calls store.Load; no tool handler in this file calls SessionStore().Save, so seven MCP tools execute with no audit record pkg/session/session.go:14 — Findings []Finding is declared on Session and rendered by cmd/yaah/main.go:521-527, but no handler or harness path ever appends a Finding
High confidence
Recommended Action
  • Wrap the MCP tool handlers in a helper that loads the session, appends a ToolCallRecord naming the tool and its arguments summary, and saves — the same shape HandleHookEvent already uses.
  • Populate Session.Findings from the secret-scanner and linter results so detected issues are queryable structured records rather than block-message text.
MEDIUM PRAX-2026-08-12-011 Generated settings leave every host hardening field unset even though the schema and generator fully support them.
pkg/harness/defaults.go:294 — AllDefaults Settings block, lines 294-299 — only Model, AlwaysThinkingEnabled, EffortLevel and AutoUpdatesChannel are populated pkg/schema/settings.go:40 — Permissions, Sandbox and AllowManagedPermissionRulesOnly are declared at lines 40-42 and the MCP allowlist fields at lines 79-81; no default constructs any of them
High confidence
Recommended Action
  • Populate a conservative default Permissions block and an AllowedMcpServers allowlist naming exactly the providers the harness registered, in AllDefaults.
  • Emit sandbox and allowManagedMcpServersOnly as explicit defaults so the generated config states the intended posture rather than inheriting whatever the host happens to default to.
MEDIUM PRAX-2026-08-12-012 Session records capture raw Bash command text with no redaction, so credentials typed on a command line persist in the audit file.
pkg/harness/harness.go:182 — summarizeToolInput, lines 182-187 — the Bash command is truncated to 120 characters and returned as-is, with no pattern masking, then stored as ToolCallRecord.Input at line 116 and carried into BlockedCalls at line 138 pkg/hooks/handlers/secretscan.go:72 — editWriteMatch limits the scanner to Edit, Write and MultiEdit, so command text never passes through the redaction-capable pattern set
Medium confidence
Recommended Action
  • Run the SecretScanner pattern set over the summarised command string in summarizeToolInput and replace any match with a location-and-pattern marker before the record is stored.
  • Apply the same masking to ToolCallRecord.Reason, which currently copies the combined handler error text verbatim.
MEDIUM PRAX-2026-08-12-013 The two load-bearing safety controls have no tests of any kind, while fourteen test files cover the rest of the codebase.
pkg/hooks/handlers — Directory holds guard.go, secretscan.go, linter.go, commentcheck.go and sessionlog.go and no test file; the 14 _test.go files in the repo live in pkg/agents, catalog, commands/builtins, generator, gitcache, harness, hooks, lsp and skills .github/workflows/ci.yaml:32 — The build job's only check is "go test ./...", so a suite that never exercises the guard or the scanner is the entire pre-release signal
High confidence
Recommended Action
  • Add table-driven tests for CommandGuard.CheckCommand and SecretScanner.ScanFile covering each shipped pattern plus its known near-miss forms.
  • Wire those tests into a named CI step so a failure is attributable, rather than folded into the general go test ./... run.
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.

Traversal-safe session identifiers

Every session path goes through sanitizeID, which rejects empty ids, the special values . and .., and any identifier containing a path separator or a non-base name — closing the path-traversal surface on both the CLI and the yaah_session_info MCP tool.

pkg/session/store.go:153-172

Immutable commit-SHA pinning across every remote source

All roughly fifty remote skill and agent references are pinned to 40-hex commit SHAs rather than branches or tags, and every GitHub Action in CI is SHA-pinned with a version comment.

pkg/harness/defaults.go:492-1180

Remote agent frontmatter is stripped before generation

RemoteAgent.resolve runs stripFrontmatter over fetched agent markdown, so a third-party repository cannot smuggle permissionMode, tools or other capability fields into a generated sub-agent definition.

pkg/agents/remote.go:104-131

Fail-closed hook dispatch

A handler returning Block propagates through CombineResults to ErrHookBlocked, and the hook command exits 2 — the status Claude Code and the generated OpenCode plugin both treat as a hard block.

cmd/yaah/main.go:184-188

Autonomous subagent feature is off by default

The experimental fact-check hooks, which spawn a Sonnet subagent with WebFetch, are installed only when YAAH_EXPERIMENTAL_FACT_CHECK is set in the environment, matching the remit's opt-in requirement for outbound or autonomous features.

cmd/yaah/main.go:47-49

Detected secrets are never echoed in cleartext

SecretFinding carries only file path, line number and a pattern label, and the block message reports location and pattern rather than the matched value, so neither the MCP tool response nor the session record can republish a credential.

pkg/hooks/handlers/secretscan.go:82-87

Signed releases with an SBOM

The release pipeline runs cosign sign-blob over the artifacts and generates an SBOM with syft, both invoked from SHA-pinned actions.

.goreleaser.yaml:34-44
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
.claude/sessions/<id>.json pkg/session/store.go via harness.HandleHookEvent structured JSON session record Per-session audit trail — tool calls with timestamps and input summaries, blocked calls with reasons, files modified, and a Findings array that is never populated unknown Inferred
.claude/logs/sessions.log pkg/hooks/handlers/sessionlog.go plaintext append-only lines Session lifecycle only — one line per SessionStart, SessionEnd and Stop event with timestamp, event name, session id and cwd 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.

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.70 / 5.0
Weighted Maturity Score · Ad hoc
Ad hoc overall. yaah has genuine, operative code controls in three places — a fail-closed hook dispatch on the Claude path, commit-SHA pinning across roughly fifty remote sources and every CI action, and a structured durable session audit trail — which is why no category collapses to zero on the strength of its own machinery. What holds the number down is that each of those controls stops short of its own declared standard: the guard is a short denylist, the scanner fires after the write, one of four supported targets gets neither, the shipped MCP defaults install unpinned npm packages at every launch, and the audit trail omits a whole tool channel. Build an AI Red Team is the outlier at zero — the security material in the tree is product shipped to users, and nothing in the workspace shows the project ever testing its own defences.
Limit Your Domain
2/ 5
Confidence: High  |  Weight: 15%  |  Weighted: 0.30
yaah enforces a real code-level closure on its own surface — exactly the seven declared MCP tools registered in mcpserver/server.go and the five declared handlers in defaults.go, with no extras — but the far larger surface it generates is scoped only by prompt text, and the thirty-plus /yaah:* commands including the explicitly autonomous one ship model-invocable because disable-model-invocation is never set, which caps this category at the prompt-only rung.
Balance Your Knowledge Base
2/ 5
Confidence: High  |  Weight: 15%  |  Weighted: 0.30
Declared data sources are narrow and two ingest controls are genuinely operative — every remote source is pinned to an immutable commit SHA and remote agent frontmatter is stripped in agents/remote.go before generation — but remote skill markdown and its third-party frontmatter are written into the host's context verbatim with no provenance label or content check, and the MCP tools read arbitrary absolute paths outside the declared sources.
Implement Zero Trust
2/ 5
Confidence: High  |  Weight: 25%  |  Weighted: 0.50
An operative code control does run on the dominant path — CommandGuard blocks at PreToolUse and the dispatcher turns Block into exit 2 — so the category is scored on merit rather than capped, and both 3 and 2 are arguable; 2 is the defensible call because the controls are not consistently applied (no hooks at all for the Codex target), the scanner fires after the write, the guard is seven regexes over a shell, and yaah_lint execs binaries on a model-chosen path without consulting the guard.
Manage Your Supply Chain
2/ 5
Confidence: High  |  Weight: 15%  |  Weighted: 0.30
The pinning discipline is real and broad — roughly fifty remote skill and agent sources at 40-hex commit SHAs, every GitHub Action SHA-pinned with a version comment, go.sum committed against two direct dependencies, cosign signing and a syft SBOM at release — which makes 3 arguable, but 2 is the defensible band because the same discipline lapses in the shipped default config (npx -y installs Context7 and Notion servers unpinned at every launch), M11 records no dependency or vulnerability scanning in-repo, and M10's SBOM is a release artifact that nothing checks for drift.
Build an AI Red Team
0/ 5
Confidence: High  |  Weight: 15%  |  Weighted: 0.00
The maturity record is empty in every direction — M1 no security-named tests (and pkg/hooks/handlers, home of both safety controls, has no test file at all), M2 no adversarial corpus, M3 no adversarial tooling, M4 no SECURITY.md or threat model, M5 no dated results, M6 no security-test command, M9 no findings-to-fix ledger — and the security-flavoured material that does exist (the /yaah:secure STRIDE template, /yaah:scan --security, the third-party security-audit skill, the agency-security-engineer agent) is content shipped to users to audit their own code, which the provenance test treats as absent.
Monitor Continuously
2/ 5
Confidence: High  |  Weight: 15%  |  Weighted: 0.30
A durable structured action-level record is operative — .claude/sessions/<id>.json captures per-tool-call timestamps, tool names, input summaries, block reasons and files modified via an atomic-write store, well past the print-statement bar — but coverage is incomplete: MCP-server tool invocations are never recorded, the declared Findings channel is rendered by session show and populated by nothing, recorded command text is unredacted, and M12 confirms no telemetry, alerting or aggregation of any kind.

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.