Stoa found 12 agent candidates — 9 at elevated exposure or above, with agents that can execute shell commands and send messages running on autonomy their declarations may not grant.
Top risk: AI002 · agents/payments.py:23 · LLM05 — Model output observed reaching a dangerous execution or injection sink. 5 fixes clear every critical finding.
Exposure = what the code makes possible, not what has happened. Fix first clears the criticals; Contradictions shows where your declarations don't match the code.
Scoreboard
how much risk, and where it sits · severity: critical high medium low
Fix first
what to repair, in order
Model output is executed or rendered without an interposed validation step.
Fix: Dispatch through a static mapping of permitted actions; never execute or render model output directly.
Why this fired
The value from `reply = llm.invoke(prompt).content # model output` (line 22) reaches a exec-class sink at line 23 with no interposed allowlist observed on the flow. Model output is attacker-influenceable whenever any untrusted content reaches the model (OWASP LLM02). This finding is gate-eligible. Analysis is intra-file; flows through other files are not visible.
A declared-vs-observed contradiction — full detail in Contradictions.
A credential is embedded in source where anyone with repo access can read it. OPENAI_FALLBACK = "sk-pro…[REDACTED:00d59b41db00]" # SEC001
Fix: Load the credential from a secret manager or environment variable.
Why this fired
Possible hardcoded API credential (agents/payments.py:8). Load the credential from a secret manager or environment variable.
A password is embedded in source rather than held in a secret store. DB_PASSWORD = "Sup3rS…[REDACTED:92179e7ad06e]" # SEC002
Fix: Load the password from a secret manager or environment variable.
Why this fired
Possible hardcoded password (agents/devops.py:6). Load the password from a secret manager or environment variable.
Sensitive identifiers are placed into prompts that leave the trust boundary.
Fix: Pseudonymize sensitive fields before the model call and rejoin identifiers afterward.
Why this fired
An identifier suggesting a credential (`llm = ChatOpenAI(model="gpt-4o", api_key=os.getenv("OPENAI_API_KEY", OPENAI_FALLBACK)) # AI005 floating-alias`, line 9) is interpolated into a prompt passed to a model call at line 22. Identifier names suggest — but do not prove — sensitive data (OWASP LLM06). Values are never read or transmitted by Stoa; this finding is based on identifier names and flow shape only. Analysis is intra-file; flows through other files are not visible.
Contradictions
where declarations don't match the code — what a self-attested questionnaire can't catch
Declared autonomy contradicts inferred autonomy
code: agents/payments.py:23
declared: stoa-declared.toml agents."a09ff38687e9".autonomy_intent
Declared autonomy contradicts inferred autonomy
code: web/support_bot.ts:12
declared: stoa-declared.toml agents."2e0ab9a50e4e".autonomy_intent
Scanned data class not present in declared data classes
code: agents/payments.py:8
declared: stoa-declared.toml agents."a09ff38687e9".data_classes
DECL006 medium — 10 agents: Scanned agent has no declaration entry
agents/compliance.py:16agents/devops.py:3agents/fraud.py:9agents/fraud.py:9agents/legacy.py:10agents/marketing.py:6agents/payments.py:12agents/research.py:3agents/triage.py:2mcp/script_tools.py:8Agents
which agents carry the risk
Risk dimensions
what kinds of risk, and which rules they map to
Sensitive data leaving the trust boundary via model calls or network egress
9 evidence items
Agent reach exceeding its declared operating scope
7 evidence items
High-impact actions reachable without an observed authorization or approval control
7 evidence items
Incorrect or unsafe model output causing downstream harm; correctness itself is a runtime property
6 evidence items
Absence of observed operating controls: auth, validation, rate limits, observability
27 evidence items
Susceptibility surface for prompt injection, poisoning, or supply-chain tampering
3 evidence items
Standards
which risk classes were assessed — gaps kept visible
Appendix — full agent detail, all findings, standards alignment, and architecture
All agents
Unrestricted-autonomous
- database_write
- payment_access
- shell_execution
- +1 more
Details & evidence
Detected because
- LangChain agent construct at line 12
- Tool or function schema at line 11
- LLM provider import or reference at line 9
- Multiple model call sites (2) — orchestration at line 1
Detection score: 10 · symbol: agent
Stack
Frameworks: langchain · Providers: openai
Capabilities (static evidence)
- database_write
- payment_access
- shell_execution
- tool_calling
Integrations · call sites
- postgres × 3
- stripe × 1
Attribution
Codeowners: @payments-team, @security · Last touched by: unknown
Findings in this file
| Severity | Rule | Line | Finding |
|---|---|---|---|
| high | DECL004 | 8 | Scanned data class not present in declared data classescredential evidence for `agent`, 'authentication' not declaredThe scanner found evidence of a data class this agent touches that isn't in its declared data_classes. Update the declaration or confirm the finding is a false positive. |
| critical | SEC001 | 8 | Possible hardcoded API credentialOPENAI_FALLBACK = "sk-pro…[REDACTED:00d59b41db00]" # SEC001Load the credential from a secret manager or environment variable. |
| low | AI005 | 9 | Model, endpoint, or artifact dependency observed without a pin or integrity controlChatOpenAI(model="gpt-4o"Pin a reviewed model revision or dated snapshot and use a TLS endpoint from an allowlist. |
| info | AI003 | 12 | Approval control not observed for high-impact tool capabilityhigh-impact capability for candidate agentConfirm an approval or human-in-the-loop control gates this capability; none was observed in this file. |
| info | AI007 | 12 | Deterministic sampling not observed on high-impact-adjacent call sitessampling config for candidate agentPin deterministic sampling (temperature=0) on consequential model call sites, or confirm variability is intended. |
| low | CTRL006 | 12 | Sandboxing not observed on an exec pathSandboxing not observed on an exec path for candidate agentConfirm this execution path runs in a restricted environment (restricted env, container, sandboxed interpreter); none was observed near it. |
| info | CTRL007 | 12 | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate agentConsider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| high | SEC003 | 18 | Interpolated SQL statementconn.cursor().execute(f"UPDATE ledger SET refunded=1 WHERE id={customer['id']}") # db_writeUse parameterized queries instead of string interpolation. |
| high | AI004 | 22 | Identifier suggesting sensitive data observed in an external model callreply = llm.invoke(prompt).content # model outputPseudonymize sensitive fields before the model call and rejoin identifiers afterward. |
| critical | AI002 | 23 | Model output observed reaching a dangerous execution or injection sinksubprocess.run(reply, shell=True) # AI002 exec -> critical, GATEDispatch through a static mapping of permitted actions; never execute or render model output directly. |
| critical | DECL001 | 23 | Declared autonomy contradicts inferred autonomyautonomy_intent='human_approved' vs inferred='unrestricted_autonomous'This agent was declared recommend-only or human-approved, but the scanner found a side-effecting path with no correlated approval gate. Either add the missing approval control, or correct the declaration. |
| high | AI004 | 27 | Identifier suggesting sensitive data observed in an external model callreply = llm.invoke("summarize action").content # model outputPseudonymize sensitive fields before the model call and rejoin identifiers afterward. |
| critical | AI002 | 29 | Model output observed reaching a dangerous execution or injection sinkcursor.execute(f"INSERT INTO audit(note) VALUES ('{reply}')") # AI002/sql ⊃ SEC003Dispatch through a static mapping of permitted actions; never execute or render model output directly. |
Unrestricted-autonomous
- database_write
- payment_access
- shell_execution
- +1 more
Details & evidence
Detected because
- LangChain agent construct at line 12
- Tool or function schema at line 11
- LLM provider import or reference at line 9
- Multiple model call sites (2) — orchestration at line 1
Detection score: 10 · symbol: executor
Stack
Frameworks: langchain · Providers: openai
Capabilities (static evidence)
- database_write
- payment_access
- shell_execution
- tool_calling
Integrations · call sites
- postgres × 3
- stripe × 1
Attribution
Codeowners: @payments-team, @security · Last touched by: unknown
Findings in this file
| Severity | Rule | Line | Finding |
|---|---|---|---|
| critical | SEC001 | 8 | Possible hardcoded API credentialOPENAI_FALLBACK = "sk-pro…[REDACTED:00d59b41db00]" # SEC001Load the credential from a secret manager or environment variable. |
| low | AI005 | 9 | Model, endpoint, or artifact dependency observed without a pin or integrity controlChatOpenAI(model="gpt-4o"Pin a reviewed model revision or dated snapshot and use a TLS endpoint from an allowlist. |
| info | AI003 | 12 | Approval control not observed for high-impact tool capabilityhigh-impact capability for candidate executorConfirm an approval or human-in-the-loop control gates this capability; none was observed in this file. |
| info | AI007 | 12 | Deterministic sampling not observed on high-impact-adjacent call sitessampling config for candidate executorPin deterministic sampling (temperature=0) on consequential model call sites, or confirm variability is intended. |
| low | CTRL006 | 12 | Sandboxing not observed on an exec pathSandboxing not observed on an exec path for candidate executorConfirm this execution path runs in a restricted environment (restricted env, container, sandboxed interpreter); none was observed near it. |
| info | CTRL007 | 12 | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate executorConsider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| medium | DECL006 | 12 | Scanned agent has no declaration entryno declaration entry for `executor`stoa-declared.toml exists but doesn't mention this agent. Add an [agents."<id>"] entry, even a partial one. |
| high | SEC003 | 18 | Interpolated SQL statementconn.cursor().execute(f"UPDATE ledger SET refunded=1 WHERE id={customer['id']}") # db_writeUse parameterized queries instead of string interpolation. |
| high | AI004 | 22 | Identifier suggesting sensitive data observed in an external model callreply = llm.invoke(prompt).content # model outputPseudonymize sensitive fields before the model call and rejoin identifiers afterward. |
| critical | AI002 | 23 | Model output observed reaching a dangerous execution or injection sinksubprocess.run(reply, shell=True) # AI002 exec -> critical, GATEDispatch through a static mapping of permitted actions; never execute or render model output directly. |
| high | AI004 | 27 | Identifier suggesting sensitive data observed in an external model callreply = llm.invoke("summarize action").content # model outputPseudonymize sensitive fields before the model call and rejoin identifiers afterward. |
| critical | AI002 | 29 | Model output observed reaching a dangerous execution or injection sinkcursor.execute(f"INSERT INTO audit(note) VALUES ('{reply}')") # AI002/sql ⊃ SEC003Dispatch through a static mapping of permitted actions; never execute or render model output directly. |
Recommend-only
- cloud_resource_access
- shell_execution
- +1 more
Details & evidence
Detected because
- Agno agent construct at line 3
- Tool or function schema at line 8
- LLM provider import or reference at line 7
Detection score: 8 · symbol: agent
Stack
Frameworks: agno · Providers: openai
Capabilities (static evidence)
- cloud_resource_access
- shell_execution
- tool_calling
Integrations · call sites
- aws × 2
Attribution
Codeowners: @sre-team · Last touched by: unknown
Findings in this file
| Severity | Rule | Line | Finding |
|---|---|---|---|
| info | AI003 | 3 | Approval control not observed for high-impact tool capabilityhigh-impact capability for candidate agentConfirm an approval or human-in-the-loop control gates this capability; none was observed in this file. |
| info | CTRL007 | 3 | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate agentConsider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| medium | DECL006 | 3 | Scanned agent has no declaration entryno declaration entry for `agent`stoa-declared.toml exists but doesn't mention this agent. Add an [agents."<id>"] entry, even a partial one. |
| critical | SEC002 | 6 | Possible hardcoded passwordDB_PASSWORD = "Sup3rS…[REDACTED:92179e7ad06e]" # SEC002Load the password from a secret manager or environment variable. |
| medium | AI005 | 7 | Model, endpoint, or artifact dependency observed without a pin or integrity controlbase_url="http://mlgw.internal-x.io/v1")Pin a reviewed model revision or dated snapshot and use a TLS endpoint from an allowlist. |
Unrestricted-autonomous
- messaging
- +3 more
Details & evidence
Detected because
- LLM provider invocation at line 10
- Tool or function schema at line 8
- LLM provider import or reference at line 3
Detection score: 5 · symbol: support_bot
Stack
Frameworks: — · Providers: openai
Capabilities (static evidence)
- customer_support
- external_http
- messaging
- tool_calling
Integrations · call sites
- slack × 1
- zendesk × 1
Attribution
Codeowners: @platform-team · Last touched by: unknown
Findings in this file
| Severity | Rule | Line | Finding |
|---|---|---|---|
| info | AI003 | 10 | Approval control not observed for high-impact tool capabilityhigh-impact capability for candidate support_botConfirm an approval or human-in-the-loop control gates this capability; none was observed in this file. |
| low | AI005 | 10 | Model, endpoint, or artifact dependency observed without a pin or integrity controlopenai('gpt-4o'Pin a reviewed model revision or dated snapshot and use a TLS endpoint from an allowlist. |
| info | AI007 | 10 | Deterministic sampling not observed on high-impact-adjacent call sitessampling config for candidate support_botPin deterministic sampling (temperature=0) on consequential model call sites, or confirm variability is intended. |
| info | CTRL007 | 10 | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate support_botConsider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| high | AI002 | 11 | Model output observed reaching a dangerous execution or injection sinkcontainer.innerHTML = out.text; // AI002 markup (model output -> innerHTML)Dispatch through a static mapping of permitted actions; never execute or render model output directly. |
| high | AI002 | 12 | Model output observed reaching a dangerous execution or injection sinkawait fetch("https://acme.zendesk.com/api/v2/tickets.json", { method: "POST", body: out.text });Dispatch through a static mapping of permitted actions; never execute or render model output directly. |
| medium | AI006 | 12 | Identifier suggesting sensitive data observed flowing to a network egress sinkawait fetch("https://acme.zendesk.com/api/v2/tickets.json", { method: "POST", body: out.text });Strip sensitive fields before egress, or add the destination to [rules.AI006].allowed_hosts if org-approved. |
| critical | DECL001 | 12 | Declared autonomy contradicts inferred autonomyautonomy_intent='recommend_only' vs inferred='unrestricted_autonomous'This agent was declared recommend-only or human-approved, but the scanner found a side-effecting path with no correlated approval gate. Either add the missing approval control, or correct the declaration. |
Recommend-only
- messaging
- +2 more
Details & evidence
Detected because
- CrewAI agent construct at line 9
- LLM provider invocation at line 15
- LLM provider import or reference at line 4
Detection score: 8 · symbol: analyst
Stack
Frameworks: crewai · Providers: anthropic
Capabilities (static evidence)
- external_http
- messaging
- vector_search
Integrations · call sites
- pinecone × 4
Attribution
Codeowners: @platform-team · Last touched by: unknown
Findings in this file
| Severity | Rule | Line | Finding |
|---|---|---|---|
| info | AI007 | 9 | Deterministic sampling not observed on high-impact-adjacent call sitessampling config for candidate analystPin deterministic sampling (temperature=0) on consequential model call sites, or confirm variability is intended. |
| info | CTRL007 | 9 | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate analystConsider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| medium | DECL006 | 9 | Scanned agent has no declaration entryno declaration entry for `analyst`stoa-declared.toml exists but doesn't mention this agent. Add an [agents."<id>"] entry, even a partial one. |
| high | AI001 | 15 | Untrusted input observed flowing into prompt constructionverdict = client.messages.create(model="claude-3-5-sonnet", # default sampling -> AI007Move untrusted content into a delimited user-role message and keep instruction text static. |
| medium | AI004 | 15 | Identifier suggesting sensitive data observed in an external model callverdict = client.messages.create(model="claude-3-5-sonnet", # default sampling -> AI007Pseudonymize sensitive fields before the model call and rejoin identifiers afterward. |
| low | AI005 | 15 | Model, endpoint, or artifact dependency observed without a pin or integrity controlmodel="claude-3-5-sonnet"Pin a reviewed model revision or dated snapshot and use a TLS endpoint from an allowlist. |
| high | AI006 | 19 | Identifier suggesting sensitive data observed flowing to a network egress sinkrequests.post("https://siem.thirdparty-x.io/ingest", json=payload) # AI006 secret->egressStrip sensitive fields before egress, or add the destination to [rules.AI006].allowed_hosts if org-approved. |
| info | NET002 | 19 | Request timeout not observedrequests.post("https://siem.thirdparty-x.io/ingest", json=payload) # AI006 secret->egressPass an explicit timeout so a hung upstream cannot stall the agent. |
Recommend-only
- messaging
- +2 more
Details & evidence
Detected because
- CrewAI agent construct at line 9
- LLM provider invocation at line 15
- LLM provider import or reference at line 4
Detection score: 8 · symbol: crew
Stack
Frameworks: crewai · Providers: anthropic
Capabilities (static evidence)
- external_http
- messaging
- vector_search
Integrations · call sites
- pinecone × 4
Attribution
Codeowners: @platform-team · Last touched by: unknown
Findings in this file
| Severity | Rule | Line | Finding |
|---|---|---|---|
| info | AI007 | 9 | Deterministic sampling not observed on high-impact-adjacent call sitessampling config for candidate crewPin deterministic sampling (temperature=0) on consequential model call sites, or confirm variability is intended. |
| info | CTRL007 | 9 | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate crewConsider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| medium | DECL006 | 9 | Scanned agent has no declaration entryno declaration entry for `crew`stoa-declared.toml exists but doesn't mention this agent. Add an [agents."<id>"] entry, even a partial one. |
| high | AI001 | 15 | Untrusted input observed flowing into prompt constructionverdict = client.messages.create(model="claude-3-5-sonnet", # default sampling -> AI007Move untrusted content into a delimited user-role message and keep instruction text static. |
| medium | AI004 | 15 | Identifier suggesting sensitive data observed in an external model callverdict = client.messages.create(model="claude-3-5-sonnet", # default sampling -> AI007Pseudonymize sensitive fields before the model call and rejoin identifiers afterward. |
| low | AI005 | 15 | Model, endpoint, or artifact dependency observed without a pin or integrity controlmodel="claude-3-5-sonnet"Pin a reviewed model revision or dated snapshot and use a TLS endpoint from an allowlist. |
| high | AI006 | 19 | Identifier suggesting sensitive data observed flowing to a network egress sinkrequests.post("https://siem.thirdparty-x.io/ingest", json=payload) # AI006 secret->egressStrip sensitive fields before egress, or add the destination to [rules.AI006].allowed_hosts if org-approved. |
| info | NET002 | 19 | Request timeout not observedrequests.post("https://siem.thirdparty-x.io/ingest", json=payload) # AI006 secret->egressPass an explicit timeout so a hung upstream cannot stall the agent. |
Recommend-only
- email_send
Details & evidence
Detected because
- AutoGen agent construct at line 6
Detection score: 5 · symbol: campaigner
Stack
Frameworks: autogen · Providers: —
Capabilities (static evidence)
- email_send
Integrations · call sites
- sendgrid × 3
Attribution
Codeowners: @platform-team · Last touched by: unknown
Findings in this file
| Severity | Rule | Line | Finding |
|---|---|---|---|
| info | CTRL007 | 6 | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate campaignerConsider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| medium | DECL006 | 6 | Scanned agent has no declaration entryno declaration entry for `campaigner`stoa-declared.toml exists but doesn't mention this agent. Add an [agents."<id>"] entry, even a partial one. |
Recommend-only
- +1 more
Details & evidence
Detected because
- OpenAI Agents SDK agent construct at line 3
- Agent execution or orchestration call at line 15
Detection score: 8 · symbol: research_agent
Stack
Frameworks: openai_agents_sdk · Providers: —
Capabilities (static evidence)
- web_search
Integrations · call sites
None observed.
Attribution
Codeowners: @platform-team · Last touched by: unknown
Findings in this file
| Severity | Rule | Line | Finding |
|---|---|---|---|
| info | CTRL007 | 3 | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate research_agentConsider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| medium | DECL006 | 3 | Scanned agent has no declaration entryno declaration entry for `research_agent`stoa-declared.toml exists but doesn't mention this agent. Add an [agents."<id>"] entry, even a partial one. |
| high | AI005 | 7 | `trust_remote_code=True` observed on a model artifact loadreranker = AutoModel.from_pretrained("someorg/reranker", trust_remote_code=True) # AI005 trust-remote-codePin a reviewed model revision or dated snapshot and use a TLS endpoint from an allowlist. |
| medium | AI005 | 9 | Model, endpoint, or artifact dependency observed without a pin or integrity controlfrom_pretrained("sentence-transformers/all-MiniLM")Pin a reviewed model revision or dated snapshot and use a TLS endpoint from an allowlist. |
Recommend-only
- shell_execution
- +1 more
Details & evidence
Detected because
- MCP server agent construct at line 8
- LLM provider invocation at line 17
- LLM provider import or reference at line 9
Detection score: 8 · symbol: script_tools
Stack
Frameworks: mcp · Providers: openai
Capabilities (static evidence)
- mcp_tools
- shell_execution
Integrations · call sites
None observed.
Attribution
Codeowners: @platform-team · Last touched by: unknown
Findings in this file
| Severity | Rule | Line | Finding |
|---|---|---|---|
| info | AI007 | 8 | Deterministic sampling not observed on high-impact-adjacent call sitessampling config for candidate script_toolsPin deterministic sampling (temperature=0) on consequential model call sites, or confirm variability is intended. |
| info | CTRL007 | 8 | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate script_toolsConsider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| medium | DECL006 | 8 | Scanned agent has no declaration entryno declaration entry for `script_tools`stoa-declared.toml exists but doesn't mention this agent. Add an [agents."<id>"] entry, even a partial one. |
| low | AI005 | 17 | Model, endpoint, or artifact dependency observed without a pin or integrity controlmodel="gpt-4o"Pin a reviewed model revision or dated snapshot and use a TLS endpoint from an allowlist. |
Recommend-only
- +1 more
Details & evidence
Detected because
- LangChain agent construct at line 16
- LangGraph agent construct at line 16
- Tool or function schema at line 16
- LLM provider import or reference at line 10
Detection score: 13 · symbol: compliance_agent
Stack
Frameworks: langchain, langgraph · Providers: anthropic
Capabilities (static evidence)
- tool_calling
Integrations · call sites
None observed.
Attribution
Codeowners: @compliance-team · Last touched by: unknown
Findings in this file
| Severity | Rule | Line | Finding |
|---|---|---|---|
| info | CTRL007 | 16 | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate compliance_agentConsider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| medium | DECL006 | 16 | Scanned agent has no declaration entryno declaration entry for `compliance_agent`stoa-declared.toml exists but doesn't mention this agent. Add an [agents."<id>"] entry, even a partial one. |
Recommend-only
- +1 more
Details & evidence
Detected because
- LLM provider invocation at line 10
- Tool or function schema at line 6
- LLM provider import or reference at line 4
Detection score: 5 · symbol: legacy
Stack
Frameworks: — · Providers: openai
Capabilities (static evidence)
- tool_calling
Integrations · call sites
None observed.
Attribution
Codeowners: @platform-team · Last touched by: unknown
Findings in this file
| Severity | Rule | Line | Finding |
|---|---|---|---|
| info | CTRL007 | 10 | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate legacyConsider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| medium | DECL006 | 10 | Scanned agent has no declaration entryno declaration entry for `legacy`stoa-declared.toml exists but doesn't mention this agent. Add an [agents."<id>"] entry, even a partial one. |
| low | AI005 | 11 | Model, endpoint, or artifact dependency observed without a pin or integrity controlmodel="gpt-4o"Pin a reviewed model revision or dated snapshot and use a TLS endpoint from an allowlist. |
Recommend-only
Details & evidence
Detected because
- PydanticAI agent construct at line 2
Detection score: 5 · symbol: triage_agent
Stack
Frameworks: pydantic_ai · Providers: —
Capabilities (static evidence)
None observed.
Integrations · call sites
None observed.
Attribution
Codeowners: @platform-team · Last touched by: unknown
Findings in this file
| Severity | Rule | Line | Finding |
|---|---|---|---|
| info | CTRL007 | 2 | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate triage_agentConsider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| medium | DECL006 | 2 | Scanned agent has no declaration entryno declaration entry for `triage_agent`stoa-declared.toml exists but doesn't mention this agent. Add an [agents."<id>"] entry, even a partial one. |
NIST AI RMF alignment
stoa diff gating and the assurance export carry that evidence into change control and external review. This is an alignment aid, not a certification claim; GOVERN is an organizational function outside a static scan's view.All findings
every finding, grouped — nothing omitted
Security findings (22)
| Severity | Rule | Location | Confidence | Finding | Remediation |
|---|---|---|---|---|---|
| critical | SEC002 | agents/devops.py:6 | High | Possible hardcoded passwordDB_PASSWORD = "Sup3rS…[REDACTED:92179e7ad06e]" # SEC002 | Load the password from a secret manager or environment variable. |
| critical | SEC001 | agents/payments.py:8 | High | Possible hardcoded API credentialOPENAI_FALLBACK = "sk-pro…[REDACTED:00d59b41db00]" # SEC001 | Load the credential from a secret manager or environment variable. |
| critical | AI002 | agents/payments.py:23 | High | Model output observed reaching a dangerous execution or injection sinksubprocess.run(reply, shell=True) # AI002 exec -> critical, GATE | Dispatch through a static mapping of permitted actions; never execute or render model output directly. |
| critical | AI002 | agents/payments.py:29 | High | Model output observed reaching a dangerous execution or injection sinkcursor.execute(f"INSERT INTO audit(note) VALUES ('{reply}')") # AI002/sql ⊃ SEC003 | Dispatch through a static mapping of permitted actions; never execute or render model output directly. |
| critical | SEC001 | tests/test_payments.py:1 | Low | Possible hardcoded API credentialFAKE = "sk-pro…[REDACTED:b559fd13432a]" # placeholder -> low confidence, never gates | Load the credential from a secret manager or environment variable. |
| high | AI001 | agents/fraud.py:15 | High | Untrusted input observed flowing into prompt constructionverdict = client.messages.create(model="claude-3-5-sonnet", # default sampling -> AI007 | Move untrusted content into a delimited user-role message and keep instruction text static. |
| high | AI006 | agents/fraud.py:19 | High | Identifier suggesting sensitive data observed flowing to a network egress sinkrequests.post("https://siem.thirdparty-x.io/ingest", json=payload) # AI006 secret->egress | Strip sensitive fields before egress, or add the destination to [rules.AI006].allowed_hosts if org-approved. |
| high | SEC003 | agents/payments.py:18 | Medium | Interpolated SQL statementconn.cursor().execute(f"UPDATE ledger SET refunded=1 WHERE id={customer['id']}") # db_write | Use parameterized queries instead of string interpolation. |
| high | AI004 | agents/payments.py:22 | High | Identifier suggesting sensitive data observed in an external model callreply = llm.invoke(prompt).content # model output | Pseudonymize sensitive fields before the model call and rejoin identifiers afterward. |
| high | AI004 | agents/payments.py:27 | High | Identifier suggesting sensitive data observed in an external model callreply = llm.invoke("summarize action").content # model output | Pseudonymize sensitive fields before the model call and rejoin identifiers afterward. |
| high | AI005 | agents/research.py:7 | High | `trust_remote_code=True` observed on a model artifact loadreranker = AutoModel.from_pretrained("someorg/reranker", trust_remote_code=True) # AI005 trust-remote-code | Pin a reviewed model revision or dated snapshot and use a TLS endpoint from an allowlist. |
| high | AI002 | web/support_bot.ts:11 | High | Model output observed reaching a dangerous execution or injection sinkcontainer.innerHTML = out.text; // AI002 markup (model output -> innerHTML) | Dispatch through a static mapping of permitted actions; never execute or render model output directly. |
| high | AI002 | web/support_bot.ts:12 | High | Model output observed reaching a dangerous execution or injection sinkawait fetch("https://acme.zendesk.com/api/v2/tickets.json", { method: "POST", body: out.text }); | Dispatch through a static mapping of permitted actions; never execute or render model output directly. |
| medium | AI005 | agents/devops.py:7 | High | Model, endpoint, or artifact dependency observed without a pin or integrity controlbase_url="http://mlgw.internal-x.io/v1") | Pin a reviewed model revision or dated snapshot and use a TLS endpoint from an allowlist. |
| medium | AI004 | agents/fraud.py:15 | High | Identifier suggesting sensitive data observed in an external model callverdict = client.messages.create(model="claude-3-5-sonnet", # default sampling -> AI007 | Pseudonymize sensitive fields before the model call and rejoin identifiers afterward. |
| medium | AI005 | agents/research.py:9 | Medium | Model, endpoint, or artifact dependency observed without a pin or integrity controlfrom_pretrained("sentence-transformers/all-MiniLM") | Pin a reviewed model revision or dated snapshot and use a TLS endpoint from an allowlist. |
| medium | AI006 | web/support_bot.ts:12 | High | Identifier suggesting sensitive data observed flowing to a network egress sinkawait fetch("https://acme.zendesk.com/api/v2/tickets.json", { method: "POST", body: out.text }); | Strip sensitive fields before egress, or add the destination to [rules.AI006].allowed_hosts if org-approved. |
| low | AI005 | agents/fraud.py:15 | Low | Model, endpoint, or artifact dependency observed without a pin or integrity controlmodel="claude-3-5-sonnet" | Pin a reviewed model revision or dated snapshot and use a TLS endpoint from an allowlist. |
| low | AI005 | agents/legacy.py:11 | Low | Model, endpoint, or artifact dependency observed without a pin or integrity controlmodel="gpt-4o" | Pin a reviewed model revision or dated snapshot and use a TLS endpoint from an allowlist. |
| low | AI005 | agents/payments.py:9 | Low | Model, endpoint, or artifact dependency observed without a pin or integrity controlChatOpenAI(model="gpt-4o" | Pin a reviewed model revision or dated snapshot and use a TLS endpoint from an allowlist. |
| low | AI005 | mcp/script_tools.py:17 | Low | Model, endpoint, or artifact dependency observed without a pin or integrity controlmodel="gpt-4o" | Pin a reviewed model revision or dated snapshot and use a TLS endpoint from an allowlist. |
| low | AI005 | web/support_bot.ts:10 | Low | Model, endpoint, or artifact dependency observed without a pin or integrity controlopenai('gpt-4o' | Pin a reviewed model revision or dated snapshot and use a TLS endpoint from an allowlist. |
Reliability findings (1)
| Severity | Rule | Location | Confidence | Finding | Remediation |
|---|---|---|---|---|---|
| info | NET002 | agents/fraud.py:19 | Low | Request timeout not observedrequests.post("https://siem.thirdparty-x.io/ingest", json=payload) # AI006 secret->egress | Pass an explicit timeout so a hung upstream cannot stall the agent. |
Review prompts (24)
Review prompts are observations, not confirmed vulnerabilities: a control was not observed in the scanned file, but may exist elsewhere.
| Severity | Rule | Location | Confidence | Finding | Remediation |
|---|---|---|---|---|---|
| low | CTRL006 | agents/payments.py:12 | Low | Sandboxing not observed on an exec pathSandboxing not observed on an exec path for candidate agent | Confirm this execution path runs in a restricted environment (restricted env, container, sandboxed interpreter); none was observed near it. |
| low | CTRL006 | agents/payments.py:12 | Low | Sandboxing not observed on an exec pathSandboxing not observed on an exec path for candidate executor | Confirm this execution path runs in a restricted environment (restricted env, container, sandboxed interpreter); none was observed near it. |
| info | CTRL007 | agents/compliance.py:16 | Low | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate compliance_agent | Consider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| info | AI003 | agents/devops.py:3 | Low | Approval control not observed for high-impact tool capabilityhigh-impact capability for candidate agent | Confirm an approval or human-in-the-loop control gates this capability; none was observed in this file. |
| info | CTRL007 | agents/devops.py:3 | Low | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate agent | Consider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| info | AI007 | agents/fraud.py:9 | Low | Deterministic sampling not observed on high-impact-adjacent call sitessampling config for candidate crew | Pin deterministic sampling (temperature=0) on consequential model call sites, or confirm variability is intended. |
| info | AI007 | agents/fraud.py:9 | Low | Deterministic sampling not observed on high-impact-adjacent call sitessampling config for candidate analyst | Pin deterministic sampling (temperature=0) on consequential model call sites, or confirm variability is intended. |
| info | CTRL007 | agents/fraud.py:9 | Low | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate analyst | Consider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| info | CTRL007 | agents/fraud.py:9 | Low | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate crew | Consider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| info | CTRL007 | agents/legacy.py:10 | Low | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate legacy | Consider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| info | CTRL007 | agents/marketing.py:6 | Low | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate campaigner | Consider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| info | AI003 | agents/payments.py:12 | Low | Approval control not observed for high-impact tool capabilityhigh-impact capability for candidate agent | Confirm an approval or human-in-the-loop control gates this capability; none was observed in this file. |
| info | AI003 | agents/payments.py:12 | Low | Approval control not observed for high-impact tool capabilityhigh-impact capability for candidate executor | Confirm an approval or human-in-the-loop control gates this capability; none was observed in this file. |
| info | AI007 | agents/payments.py:12 | Low | Deterministic sampling not observed on high-impact-adjacent call sitessampling config for candidate executor | Pin deterministic sampling (temperature=0) on consequential model call sites, or confirm variability is intended. |
| info | AI007 | agents/payments.py:12 | Low | Deterministic sampling not observed on high-impact-adjacent call sitessampling config for candidate agent | Pin deterministic sampling (temperature=0) on consequential model call sites, or confirm variability is intended. |
| info | CTRL007 | agents/payments.py:12 | Low | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate executor | Consider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| info | CTRL007 | agents/payments.py:12 | Low | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate agent | Consider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| info | CTRL007 | agents/research.py:3 | Low | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate research_agent | Consider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| info | CTRL007 | agents/triage.py:2 | Low | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate triage_agent | Consider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| info | AI007 | mcp/script_tools.py:8 | Low | Deterministic sampling not observed on high-impact-adjacent call sitessampling config for candidate script_tools | Pin deterministic sampling (temperature=0) on consequential model call sites, or confirm variability is intended. |
| info | CTRL007 | mcp/script_tools.py:8 | Low | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate script_tools | Consider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
| info | AI003 | web/support_bot.ts:10 | Low | Approval control not observed for high-impact tool capabilityhigh-impact capability for candidate support_bot | Confirm an approval or human-in-the-loop control gates this capability; none was observed in this file. |
| info | AI007 | web/support_bot.ts:10 | Low | Deterministic sampling not observed on high-impact-adjacent call sitessampling config for candidate support_bot | Pin deterministic sampling (temperature=0) on consequential model call sites, or confirm variability is intended. |
| info | CTRL007 | web/support_bot.ts:10 | Low | No kill-switch signal observed on the agent's entry pathNo kill-switch signal observed on the agent's entry path for candidate support_bot | Consider a feature-flag or env-var gate that can disable this agent without a deploy; none was observed. This is the weakest signal in the control set -- informational only. |
Suppressed findings (3)
| Rule | Location | Finding | Reason |
|---|---|---|---|
REL001 | agents/fraud.py:20 | Swallowed exception | fire-and-forget telemetry |
REL001 | agents/legacy.py:12 | Swallowed exception | — |
SEC003 | lib/db.py:12 | Interpolated SQL statement | table name comes from the REPORTS enum above |
Architecture graph
Agents, tools, providers, and capability-sinks this scan observed, with the findings that explain each connection. Every edge is declared (statically detected) — click any node or edge for evidence.
Click a node or edge to see its detail.