Files
cowork-local/core/agent_security_alert.py
T
f9f6bc01fd
CI / test (push) Canceled after 0s
Feature/delta team/epic r04 (#7)
## Summary

epic r04 - begin refactor

## Change Type

- [x] Cowork feature
- [ ] Bug fix
- [ ] Core AI contribution
- [ ] Test / hardening
- [ ] Performance
- [ ] Documentation

## Related Work

Cowork Task:

Core Repo: http://34.143.229.138/gitea-admin/fsg-ai-core-assets

Core AI Issue:

Core Task:

Related PR:

## Scope

What is intentionally included?

What is intentionally NOT included?

## Validation

- [ ] Unit tests
- [ ] Integration tests
- [ ] Manual verification
- [ ] Regression check

Commands / evidence:

## Security Impact

Permission / credential / network / customer data impact:

## Compatibility

- [ ] No breaking change
- [ ] Breaking change documented

## Reviewer Notes

Anything Cowork reviewers should pay attention to.

---------

Co-authored-by: Anh Tran Nguyen Minh <anhtnm1@fpt.com>
Co-authored-by: Huong Le Thi Thien <huongltt35@fpt.com>
Co-authored-by: Nam Pham Dinh Thanh <nampdt@fpt.com>
Co-authored-by: Vu Dam Tuan <vudt15@fpt.com>
Co-authored-by: Hiep Ha Van <hiephv3@fpt.com>
Co-authored-by: Lam Hoang Van <lamhv7@fpt.com>
Reviewed-on: #7
Co-authored-by: Duy Le Huu <duylh19@fpt.com>
2026-08-31 05:15:13 +00:00

45 lines
2.0 KiB
Python

"""Email alert to the configured admin when an agent-security layer blocks an
action (core/agent_security.py) — reuses the SAME signed-in Microsoft 365
account as every other MS365 feature in the app (core/ms365_auth.py +
core/ms365_graph.send_mail), so no separate SMTP setup is required.
Best-effort only: a failed alert never raises — the block itself has already
happened by the time this is called, so a delivery failure here must not turn
a handled security event into an unhandled crash.
"""
from __future__ import annotations
from typing import Tuple
from . import ms365_graph
from .agent_security_types import SecurityVerdict
from .ms365_auth import Ms365AuthError, get_access_token
def notify_admin(config, verdict: SecurityVerdict, detail: str = "") -> Tuple[bool, str]:
"""Best-effort email to the configured admin address. Returns
``(sent, note)`` — ``note`` explains why nothing was sent when ``sent`` is
False. Never raises."""
sec = config.data.get("agent_security", {})
admin_email = (sec.get("admin_email") or "").strip()
if not admin_email:
return False, "no admin_email configured in Settings"
ms365 = config.ms365
tenant_id, client_id = ms365.get("tenant_id", ""), ms365.get("client_id", "")
try:
token = get_access_token(tenant_id, client_id)
subject = f"[Cowork Local] Cảnh báo bảo mật agent — lớp {verdict.layer}"
body = (
f"Lớp kiểm tra: {verdict.layer}\n"
f"Lý do chặn: {verdict.reason}\n\n"
f"Chi tiết:\n{detail}"
)
ms365_graph.send_mail(token, admin_email, subject, body)
return True, "sent"
except Ms365AuthError as exc:
return False, f"Microsoft 365 chưa đăng nhập: {exc}"
except ms365_graph.Ms365GraphError as exc:
return False, f"Gửi email thất bại: {exc}"
except Exception as exc: # noqa: BLE001 - alerting must never crash the caller
return False, str(exc)