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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,8 @@ go.work.sum
.githooks/
__pycache__/
hawk_bin

# Logs
*.log
hawk-sec105b.log

8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ GORELEASER := $(GOBIN_DIR)/goreleaser
# ---------------------------------------------------------------------------
# Phony declarations (alphabetical).
# ---------------------------------------------------------------------------
.PHONY: all bench boundaries build ci clean contracts-guard ecosystem-guard eyrie-client-guard eyrie-engine-guard peer-guard internal-layers-guard submodule-release-parity cover cover-new fmt help install lint lint-fix \
.PHONY: all bench boundaries build check-replace ci clean contracts-guard ecosystem-guard eyrie-client-guard eyrie-engine-guard peer-guard internal-layers-guard submodule-release-parity cover cover-new fmt help install lint lint-fix \
release security setup smoke path sync-external test test-10x test-live test-new test-race tidy version vet

# ---------------------------------------------------------------------------
# Default target.
# ---------------------------------------------------------------------------
check-replace: ## Fail if go.mod has local replace directives (run before tagging)
@bash scripts/check-no-replace-directives.sh

all: lint test build ## Default — lint, test, build.

# ---------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ hawk is an AI-powered coding agent that lives in your terminal. It reads your co

**Hawk is in active development.** Contributor source builds are the primary path today while we keep hardening the product in the open. Tagged releases and install assets may exist for validation, but they are not the recommended first path yet.

Follow [GrayCode](https://github.com/GrayCodeAI) for progress. When Hawk is ready to try, we will announce it on [graycodeai.gateandtech.in](https://graycodeai.gateandtech.in/changelog).
Follow [GrayCode](https://github.com/GrayCodeAI) for progress. When Hawk is ready to try, we will announce it on [graycodeai.com](https://graycodeai.com/changelog).

## Quick Start (contributors — from source)

Expand Down
134 changes: 134 additions & 0 deletions docs/DAEMON-PORT-THREAT-MODEL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Hawk Daemon — Port 4590 Threat Model

The Hawk daemon (`hawk daemon`) binds an HTTP server on port **4590** (default)
of the **loopback interface only** (`127.0.0.1:4590`). This document describes
the threat model, attack surface, and mitigation controls.

---

## What the daemon exposes

| Endpoint | Auth required | Notes |
|----------|--------------|-------|
| `GET /v1/ready` | No | Dependency-aware readiness probe |
| `POST /v1/chat` | Configurable | Creates or resumes a session; SSE streaming |
| `GET /v1/sessions` | Configurable | Lists persisted sessions |
| `GET /v1/sessions/:id` | Configurable | Retrieves a session |
| `DELETE /v1/sessions/:id` | Configurable | Deletes a session |
| `GET /v1/stats` | Configurable | Usage/cost statistics |
| `POST /v1/cancel` | Configurable | Cancels the active generation |

---

## Threat model

### In-scope threats

#### T1 — Local network eavesdropping
The daemon binds only to `127.0.0.1`. Traffic never leaves the loopback
interface. An attacker on the same LAN **cannot** reach the daemon.

#### T2 — Local process CSRF
A malicious local process (malware, compromised script) can send HTTP requests
to `127.0.0.1:4590` without any network privilege.

**Mitigation:**
- Set `HAWK_DAEMON_API_KEY` and configure the daemon with `--api-key` to
require `Authorization: Bearer <key>` on all non-readiness endpoints.
- The key is validated per-request; the daemon does not issue tokens.

#### T3 — Port scanning / fingerprinting
Any local process can detect that port 4590 is open and identify hawk.

**Mitigation:** Low severity — this is unavoidable for a local HTTP service.
The daemon does not expose version information on unauthenticated endpoints.

#### T4 — Session data exfiltration
Session data (conversation history, tool outputs) is stored in SQLite at
`~/.hawk/sessions/hawk.db`. A local attacker with filesystem read access can
read this file directly regardless of the daemon's auth.

**Mitigation:**
- SQLite file permissions are `0600` (owner-only read/write).
- Use full-disk encryption (FileVault on macOS, LUKS on Linux) for complete
protection.

#### T5 — Denial of service (resource exhaustion)
A local attacker can flood the daemon with chat requests, consuming LLM API
credits.

**Mitigation:**
- The daemon processes one generation at a time by default.
- `/v1/cancel` allows killing an in-progress request.
- Consider running the daemon behind an OS-level firewall rule if operating
in a shared-machine environment.

### Out-of-scope threats

- **Remote network attackers**: the daemon does not bind to `0.0.0.0`; remote
access is architecturally blocked.
- **Process privilege escalation**: hawk does not run as root and does not use
`setuid`/`setgid`.

---

## Configuring authentication

Set the daemon API key before starting the daemon:

```bash
# Option 1: environment variable (recommended for CI/automation)
export HAWK_DAEMON_API_KEY="your-random-secret-here"
hawk daemon

# Option 2: CLI flag
hawk daemon --api-key "your-random-secret-here"
```

All clients must then pass:
```
Authorization: Bearer your-random-secret-here
```

The SDK reads this from `HAWK_DAEMON_API_KEY` automatically if the env var is
set.

---

## Changing the port

```bash
hawk daemon --port 9000
```

Or in `~/.hawk/settings.json`:
```json
{
"daemon": {
"port": 9000
}
}
```

---

## Shared machine considerations

If hawk is running on a machine shared by multiple OS users (e.g., a dev
server), set the API key **and** use OS firewall rules to restrict which local
users can connect to port 4590:

```bash
# macOS — pf: allow only current user's processes (requires pf.conf editing)
# Linux — iptables: allow only the hawk-owner UID
sudo iptables -A OUTPUT -p tcp --dport 4590 -m owner ! --uid-owner $UID -j REJECT
```

---

## Related

- [`cmd/daemon.go`](../cmd/daemon.go) — daemon entrypoint and auth middleware
- [`internal/daemon/`](../internal/daemon/) — HTTP handlers
- [`SECURITY.md`](../SECURITY.md) — vulnerability reporting
- [`docs/SECURITY-DEVELOPER.md`](SECURITY-DEVELOPER.md) — credential storage model
1 change: 1 addition & 0 deletions docs/SECURITY-DEVELOPER.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,4 @@ Non-secret overrides only (hawk does not load provider API keys from env):
- Hawk: `internal/config/eyrie_engine.go`, `internal/tool/safety.go`,
`internal/storage/paths.go`, `cmd/credentials.go`
- Eyrie public host boundary: `engine/`
- Daemon HTTP surface: [`docs/DAEMON-PORT-THREAT-MODEL.md`](DAEMON-PORT-THREAT-MODEL.md)
2 changes: 1 addition & 1 deletion go.mod

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading