Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .githooks/pre-push
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
exec python3 "$ROOT/scripts/check_safe_to_push.py" --public
exec python3 "$ROOT/scripts/check_safe_to_push.py" --public --push
10 changes: 10 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
- package-ecosystem: pip
directory: /
schedule:
interval: weekly
36 changes: 34 additions & 2 deletions .github/workflows/secret-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ on:
branches: [main]
pull_request:

permissions:
contents: read

jobs:
paths-and-secrets:
runs-on: ubuntu-latest
Expand All @@ -20,14 +23,43 @@ jobs:
echo "Patient corpus files must not be in the public repo"
exit 1
fi
for f in bot_config.json .env; do
if git ls-files '**/.env' | grep -v '\.env\.example$'; then
echo "Blocked .env file(s) in repo"
exit 1
fi
if git ls-files '**/bot_config.json' 'bot_config.json' 2>/dev/null | grep -q .; then
echo "bot_config.json must not be committed"
exit 1
fi
for f in sources incoming; do
if git ls-files "$f" 2>/dev/null | grep -q .; then
echo "Blocked file in repo: $f"
echo "Blocked path in repo: $f"
exit 1
fi
done

- name: Scan tracked tree for secrets and PHI
run: python3 scripts/check_safe_to_push.py --public --scan-all

- name: Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
config-path: .gitleaks.toml

dependency-audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Dependency audit
run: |
python -m pip install --upgrade pip
pip install pip-audit
pip install -e .
pip-audit
16 changes: 16 additions & 0 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
title = "biohackbot gitleaks"

[allowlist]
description = "Ignore mock patient tokens in public fixtures"
paths = [
'''tests/fixtures/''',
'''examples/demo-instance/''',
]

[[allowlist.regexes]]
description = "Mock US insurance id in fixtures"
regex = '''US-MOCK-INS-'''

[[allowlist.regexes]]
description = "Mock deploy placeholders"
regex = '''TELEGRAM_BOT_TOKEN=\s*$'''
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ This creates:
Edit `PATIENT_PROFILE.json`:

```json
{"dob": "1985-03-20", "full_name_ru": "Your Name"}
{"dob": "1985-06-15", "full_name_ru": "John Smith", "country": "USA"}
```

## 3. Add documents
Expand Down
2 changes: 1 addition & 1 deletion README.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ medbots init ~/my-health
Отредактируйте `PATIENT_PROFILE.json`:

```json
{"dob": "1985-03-20", "full_name_ru": "Иван Иванов"}
{"dob": "1985-06-15", "full_name_ru": "John Smith", "country": "USA"}
```

## 3. Добавление документов
Expand Down
2 changes: 1 addition & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ medbots init ~/my-health
编辑 `PATIENT_PROFILE.json`:

```json
{"dob": "1985-03-20", "full_name_ru": "Your Name"}
{"dob": "1985-06-15", "full_name_ru": "John Smith", "country": "USA"}
```

## 3. 添加文档
Expand Down
33 changes: 30 additions & 3 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,39 @@
# Security

## Public repository policy

**Never commit to this public repo:**

- API keys, bot tokens, `.env` files
- `bot_config.json` with real paths
- API keys, bot tokens, real `.env` files
- `bot_config.json` with instance-specific paths
- Patient data: labs, genetics, clinical notes, `PATIENT_PROFILE.json`, `pdf_text/`, `doc_text/`
- Raw PDFs in `sources/`
- Raw PDFs in `sources/` or `incoming/`

Keep health data in a local or private instance directory (see README).

## Automated controls

| Control | Purpose |
|---------|---------|
| `scripts/check_safe_to_push.py --public --push` | Pre-push hook: scans outgoing commits (not just staged files) |
| `scripts/check_safe_to_push.py --public --scan-all` | CI: scans all tracked files |
| `.github/workflows/secret-scan.yml` | Gitleaks + path blocks + dependency audit |
| `.gitleaks.toml` | Allowlist for mock fixtures only |
| `deploy/lib/validate-deploy-path.sh` | Blocks shell metacharacter injection in deploy vars |

Install hooks after clone:

```bash
git config core.hooksPath .githooks
```

## Private VPS / Telegram bot

- Store tokens in `~/.config/medbot-openclaw.env` with `chmod 600`
- Set `TELEGRAM_ALLOWED_USER_IDS` — never run the bot open to all Telegram users
- Corpus on VPS: `/opt/medbot-corpus` — restrict SSH and filesystem permissions
- Do not expose corpus directory via HTTP without authentication

## Reporting

Report vulnerabilities via [GitHub Security Advisories](https://github.com/apodobe/biohackbot/security/advisories/new) — without attaching PHI or tokens.
14 changes: 12 additions & 2 deletions deploy/02-rsync-corpus.sh
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# shellcheck source=lib/validate-deploy-path.sh
source "$SCRIPT_DIR/lib/validate-deploy-path.sh"

VPS="${VPS:?Set VPS=root@your-host}"
LOCAL="${CORPUS:?Set CORPUS=/path/to/structured_database}"
REMOTE_DIR="${REMOTE_DIR:-/opt/medbot-corpus/structured_database}"

validate_deploy_value "VPS" "$VPS"
validate_deploy_value "LOCAL" "$LOCAL"
validate_deploy_value "REMOTE_DIR" "$REMOTE_DIR"

echo "Local: $LOCAL"
echo "Remote: $VPS:$REMOTE_DIR"
ssh "$VPS" "mkdir -p '$REMOTE_DIR'"
ssh -- "$VPS" mkdir -p -- "$REMOTE_DIR"
rsync -avz --delete \
--exclude '.pytest_cache' \
--exclude '__pycache__' \
--exclude '*.pdf' \
"$LOCAL/" "$VPS:$REMOTE_DIR/"
ssh "$VPS" "mkdir -p /opt/medbot-corpus && chmod -R a+rX /opt/medbot-corpus"
ssh -- "$VPS" mkdir -p -- /opt/medbot-corpus
ssh -- "$VPS" chmod -R a+rX -- /opt/medbot-corpus
echo "Done."
12 changes: 10 additions & 2 deletions deploy/03-install-skill-on-vps.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# shellcheck source=lib/validate-deploy-path.sh
source "$SCRIPT_DIR/lib/validate-deploy-path.sh"

VPS="${VPS:-n8n-server}"
SKILL_SRC="$(cd "$(dirname "$0")" && pwd)/skills/biohacking-corpus"
REMOTE_SKILLS="${REMOTE_SKILLS:-/root/.openclaw/workspace/skills}"

validate_deploy_value "VPS" "$VPS"
validate_deploy_value "REMOTE_SKILLS" "$REMOTE_SKILLS"

echo "Install skill: $SKILL_SRC -> $VPS:$REMOTE_SKILLS/biohacking-corpus/"
ssh "$VPS" "mkdir -p '$REMOTE_SKILLS/biohacking-corpus'"
ssh -- "$VPS" mkdir -p -- "$REMOTE_SKILLS/biohacking-corpus"
rsync -avz "$SKILL_SRC/" "$VPS:$REMOTE_SKILLS/biohacking-corpus/"
ssh "$VPS" "chmod +x '$REMOTE_SKILLS/biohacking-corpus/'*.sh 2>/dev/null || true"
ssh -- "$VPS" chmod +x -- "$REMOTE_SKILLS/biohacking-corpus/"*.sh 2>/dev/null || true
echo "Done. Restart OpenClaw gateway if needed."
3 changes: 2 additions & 1 deletion deploy/RUNBOOK.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ Copy and fill env template on the server:

```bash
cp deploy/openclaw.env.example ~/.config/medbot-openclaw.env
# set TELEGRAM token and allowed user IDs
chmod 600 ~/.config/medbot-openclaw.env
# set TELEGRAM token and allowed user IDs (never leave ALLOWED_USER_IDS empty in production)
```

Skill reads corpus from `/opt/medbot-corpus/structured_database` (adjust in `02-rsync-corpus.sh` if needed).
Expand Down
22 changes: 22 additions & 0 deletions deploy/lib/validate-deploy-path.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bash
# Reject shell metacharacters in deploy paths/hosts (SSH injection guard).
validate_deploy_value() {
local label="$1"
local value="$2"
if [[ -z "$value" ]]; then
echo "ERROR: $label is empty" >&2
return 1
fi
if [[ "$value" == *$'\n'* ]] || [[ "$value" == *$'\r'* ]]; then
echo "ERROR: $label contains newline" >&2
return 1
fi
if [[ ! "$value" =~ ^[a-zA-Z0-9@._:/-]+$ ]]; then
echo "ERROR: $label contains unsafe characters: $value" >&2
return 1
fi
if [[ "$value" == *".."* ]]; then
echo "ERROR: $label must not contain .." >&2
return 1
fi
}
1 change: 1 addition & 0 deletions deploy/openclaw.env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# /root/.config/medbot-openclaw.env on VPS — do not commit real tokens
# chmod 600 this file after filling values
TELEGRAM_BOT_TOKEN=
TELEGRAM_ALLOWED_USER_IDS=123456789
MEDBOTS_CORPUS_PATH=/opt/medbot-corpus/structured_database
7 changes: 6 additions & 1 deletion deploy/skills/biohacking-corpus/biohacking-corpus-path.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
#!/usr/bin/env bash
# Default corpus path for biohacking-corpus skill
echo "${BIOHACKING_CORPUS_PATH:-/opt/medbot-corpus/structured_database}"
BASE="${BIOHACKING_CORPUS_PATH:-/opt/medbot-corpus/structured_database}"
if [[ "$BASE" == *$'\n'* ]] || [[ ! "$BASE" =~ ^[a-zA-Z0-9/_.-]+$ ]] || [[ "$BASE" == *".."* ]]; then
echo "ERROR: invalid BIOHACKING_CORPUS_PATH" >&2
exit 1
fi
echo "$BASE"
2 changes: 1 addition & 1 deletion docs/PARSERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ medbots validate-apple-health --corpus ~/my-health/structured_database
2. **Set date of birth** in `structured_database/PATIENT_PROFILE.json` — used for age-based reference ranges and Apple Health quality checks:

```json
{"dob": "1985-03-20", "full_name_ru": "Your Name"}
{"dob": "1985-06-15", "full_name_ru": "John Smith", "country": "USA"}
```

3. **Copy source files** into the right folder (see vendor sections below).
Expand Down
2 changes: 1 addition & 1 deletion docs/PARSERS.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ medbots validate-apple-health --corpus ~/my-health/structured_database
2. **Указать дату рождения** в `structured_database/PATIENT_PROFILE.json` — нужна для референсов и проверки Apple Health:

```json
{"dob": "1985-03-20", "full_name_ru": "Иван Иванов"}
{"dob": "1985-06-15", "full_name_ru": "John Smith", "country": "USA"}
```

3. **Положить файлы** в нужную папку `sources/` (см. разделы по вендорам).
Expand Down
6 changes: 4 additions & 2 deletions examples/demo-instance/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Demo instance (synthetic, no PHI)
# Demo instance (synthetic mock patient)

Pre-built manifest + `pdf_text/` for three vendors. **No PDF files required.**

Mock patient: **John Smith**, USA (`PATIENT_PROFILE.json`).

```bash
# from repo root
medbots structure --bot-root examples/demo-instance
Expand All @@ -16,4 +18,4 @@ medbots pipeline --bot-root examples/demo-instance

Medsi entry includes `user_drop_batch: true` (required by the Medsi parser gate in `local_structure_pdfs`).

Text fixtures are copied from `tests/fixtures/pdf_text/` (redacted synthetic extracts).
Text fixtures are copied from `tests/fixtures/pdf_text/` (synthetic extracts with mock PII).
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"dob":"1985-03-20","full_name_ru":"Demo Patient"}
{"dob": "1985-06-15", "full_name_ru": "John Smith", "country": "USA"}
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
Биохимический анализ крови
Тестов
Smith
Фамилия:
№ направления:
268953196
MOCK-REF-90001
Дата: 16.06.2026
Алексей
John
Имя:
ЛПУ:
Карта: 2364501
Юрьевич
Карта: MOCK-CARD-10001
-
Отчество:
Отделение:
10.01. Терапевтическое отделение
Врач: Михайлова Юлия Игоревна
Врач: Robert Miller, MD
Номер заказа:
1011274602
MOCK-ORDER-80001
Наименование исследования
Результат
Ед. изм.
Expand Down Expand Up @@ -169,6 +169,6 @@ Consensus Panel. Eur Heart J.2016;37:1944-1958



Калачева Ольга Сергеевна
Lab Tech Demo
16.06.2026 12:22:13
Врач КДЛ:
Loading
Loading