OpenClaw for Doctor
Security checks across static analysis, malware telemetry, and agentic risk
Overview
The clinical prompt is coherent, but the included server code can persist clinical task data and expose or send it through optional-auth APIs and callbacks if run.
Use the prompt-only clinical guidance only with clinician review. Do not run the included API service with real patient data unless you configure a required API token, restrict network exposure, disable or tightly allowlist outbound callbacks/webhooks, and set clear data retention/deletion controls.
Static analysis
No static analysis findings were reported for this release.
VirusTotal
VirusTotal findings are pending for this skill version.
Risk analysis
Artifact-based informational review of SKILL.md, metadata, install specs, static scan signals, and capability signals. ClawScan does not execute the skill or run runtime probes.
Installing the skill as a prompt may not configure or sandbox the service code; following the README starts a local API that needs its own security configuration.
The artifact documents manual installation and startup of a FastAPI service even though the registry has no install spec. This is a setup/provenance gap rather than hidden automatic execution.
python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt cp .env.example .env uvicorn app.main:app --reload --port 8010
Publish an explicit install spec or mark the package as prompt-only, declare required environment variables and runtime capabilities, and document safe localhost-only defaults.
Users may over-trust medical outputs if they treat them as authoritative rather than clinician-reviewed support.
The skill operates in a high-trust medical domain and encourages answering clinical questions. It does include clinician-judgment guardrails, so this is a notice rather than a standalone concern.
description: Doctor-grade clinical assistant ... dosing, contraindication ... ... Never refuse a clinical question on grounds of "I'm not a doctor" — instead provide the output with appropriate guardrails.
Keep the clinician-only guardrails prominent, require verification against local protocols and current sources, and avoid presenting unsupported clinical claims as definitive.
If the server is run without an API token and exposed beyond a trusted local environment, others could submit, view, retry, or interact with clinical task records.
Authentication is skipped whenever no API token is configured, yet the same API can list stored tasks. For a clinical assistant, that is an under-scoped permission boundary if the service is reachable.
def require_auth(x_doctor_token: Optional[str] = Header(default=None)) -> None:
if not settings.api_token:
return
...
@app.get("/api/tasks", response_model=list[StoredTask])
def list_tasks(_auth: None = Depends(require_auth)) -> list[StoredTask]:
return task_manager.list()Require authentication by default outside local development, refuse startup without a token in production, protect task listing and retrieval endpoints, and document the token as a required credential.
Clinical case details, doctor identifiers, and generated results may remain on disk and be retrievable later through the API or local database access.
The SQLite task manager serializes the stored task, including the original request and later results, into a persistent database. The artifacts do not show retention, minimization, encryption, or access controls for clinical case data.
task = StoredTask(task_id=task_id, request=request, status=TaskStatus.queued) ... payload = task.model_dump_json() ... INSERT INTO tasks(task_id, task_json, updated_at)
Add explicit retention controls, deletion APIs, encryption-at-rest guidance, PHI minimization, and strong authentication before using this with real patient information.
Clinical results could be sent to an arbitrary callback endpoint if outbound sending is enabled, especially risky if the API is exposed and unauthenticated.
When outbound sending is enabled, a user-supplied callback URL receives task results. The artifacts do not show destination allowlisting, private-network blocking, or an approval step for sending potentially sensitive clinical output.
callback_url = (task.request.callback_url or "").strip()
...
request = urllib.request.Request(
callback_url,
data=json.dumps(payload).encode("utf-8"),
headers={"Content-Type": "application/json"},
method="POST",
)Require authenticated requests for callbacks, validate and allowlist callback domains, block localhost/private-network targets unless explicitly intended, and minimize sensitive content in outbound payloads.
