[agent] Add LLM risk analyzer (#9349)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Graham Neubig <neubig@gmail.com>
Co-authored-by: llamantino <213239228+llamantino@users.noreply.github.com>
Co-authored-by: mamoodi <mamoodiha@gmail.com>
Co-authored-by: Tim O'Farrell <tofarr@gmail.com>
Co-authored-by: Hiep Le <69354317+hieptl@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ryan H. Tran <descience.thh10@gmail.com>
Co-authored-by: Neeraj Panwar <49247372+npneeraj@users.noreply.github.com>
Co-authored-by: sp.wack <83104063+amanape@users.noreply.github.com>
Co-authored-by: Insop <1240382+insop@users.noreply.github.com>
Co-authored-by: test <test@test.com>
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
Co-authored-by: Zhonghao Jiang <zhonghao.J@outlook.com>
Co-authored-by: Ray Myers <ray.myers@gmail.com>
This commit is contained in:
Xingyao Wang
2025-08-22 10:02:36 -04:00
committed by GitHub
parent 4507a25b85
commit ca424ec15d
53 changed files with 729 additions and 563 deletions

View File

@@ -29,7 +29,6 @@ from openhands.runtime import get_runtime_cls
from openhands.runtime.base import Runtime
from openhands.runtime.impl.remote.remote_runtime import RemoteRuntime
from openhands.runtime.runtime_status import RuntimeStatus
from openhands.security import SecurityAnalyzer, options
from openhands.server.services.conversation_stats import ConversationStats
from openhands.storage.data_models.user_secrets import UserSecrets
from openhands.storage.files import FileStore
@@ -54,7 +53,7 @@ class AgentSession:
file_store: FileStore
controller: AgentController | None = None
runtime: Runtime | None = None
security_analyzer: SecurityAnalyzer | None = None
memory: Memory | None = None
_starting: bool = False
_started_at: float = 0
@@ -133,7 +132,6 @@ class AgentSession:
custom_secrets=custom_secrets if custom_secrets else {} # type: ignore[arg-type]
)
try:
self._create_security_analyzer(config.security.security_analyzer)
runtime_connected = await self._create_runtime(
runtime_name=runtime_name,
config=config,
@@ -245,8 +243,6 @@ class AgentSession:
await self.controller.close()
if self.runtime is not None:
EXECUTOR.submit(self.runtime.close)
if self.security_analyzer is not None:
await self.security_analyzer.close()
def _run_replay(
self,
@@ -278,18 +274,6 @@ class AgentSession:
assert isinstance(replay_events[0], MessageAction)
return replay_events[0]
def _create_security_analyzer(self, security_analyzer: str | None) -> None:
"""Creates a SecurityAnalyzer instance that will be used to analyze the agent actions
Parameters:
- security_analyzer: The name of the security analyzer to use
"""
if security_analyzer:
self.logger.debug(f'Using security analyzer: {security_analyzer}')
self.security_analyzer = options.SecurityAnalyzers.get(
security_analyzer, SecurityAnalyzer
)(self.event_stream)
def override_provider_tokens_with_custom_secret(
self,
git_provider_tokens: PROVIDER_TOKEN_TYPE | None,
@@ -461,6 +445,7 @@ class AgentSession:
status_callback=self._status_callback,
initial_state=initial_state,
replay_events=replay_events,
security_analyzer=self.runtime.security_analyzer if self.runtime else None,
)
return (controller, initial_state is not None)

View File

@@ -5,7 +5,6 @@ from openhands.events.stream import EventStream
from openhands.llm.llm_registry import LLMRegistry
from openhands.runtime import get_runtime_cls
from openhands.runtime.base import Runtime
from openhands.security import SecurityAnalyzer, options
from openhands.storage.files import FileStore
from openhands.utils.async_utils import call_sync_from_async
@@ -36,11 +35,6 @@ class ServerConversation:
event_stream = EventStream(sid, file_store, user_id)
self.event_stream = event_stream
if config.security.security_analyzer:
self.security_analyzer = options.SecurityAnalyzers.get(
config.security.security_analyzer, SecurityAnalyzer
)(self.event_stream)
if runtime:
self._attach_to_existing = True
else:
@@ -55,6 +49,11 @@ class ServerConversation:
)
self.runtime = runtime
@property
def security_analyzer(self):
"""Access security analyzer through runtime."""
return self.runtime.security_analyzer
async def connect(self) -> None:
if not self._attach_to_existing:
await self.runtime.connect()

View File

@@ -118,7 +118,9 @@ class Session:
else settings.confirmation_mode
)
self.config.security.security_analyzer = (
settings.security_analyzer or self.config.security.security_analyzer
self.config.security.security_analyzer
if settings.security_analyzer is None
else settings.security_analyzer
)
self.config.sandbox.base_container_image = (
settings.sandbox_base_container_image