The Problem
Home‑Assistant‑core is a 24 k‑file Python‑centric home‑automation platform, but two reproducible‑build and CI‑security gaps let a malicious patch or a wedged CI step slip past the project’s own quality gates. The static analysis flagged no lockfile beside pyproject.toml and GitHub Actions pinned only to branch tags, meaning the exact dependency set and action versions that passed tests can differ from what ships to users.
What This Does
Home Assistant provides local‑first home automation, exposing a modular component model under homeassistant/components/. Core runtime lives in homeassistant/__main__.py (entry point main) and orchestrates services, config flows, and integrations through a central Hass instance. The framework is exercised by 11 350 test files and 12976 source files, predominantly Python (16 516) with JSON configs (5 450) and YAML manifests (794).
Key structural facts:
- Internal call graph – 1 850 resolved self‑call edges; the most‑called functions are
response(43 callers),_is_feature_available(16),add_context_property(15), and_async_schedule_save(14). - Entry points –
maininhomeassistant/__main__.py:168reaches 14 functions;executeinhomeassistant/components/assist_pipeline/pipeline.py:1684reaches 32 functions and is invoked by nothing else in the repo. - What the code touches outside itself – 15 functions read/write files, 7 perform crypto/secrets ops, 14 make outbound network calls, 7 call a model for inference, 1 reads/writes a database. Traced paths:
main → restore_backup [filesystem via backup_file_path.unlink]andensure_config_path [filesystem via os.mkdir]. - Files with most route traffic –
homeassistant/components/alexa/capabilities.py(153 functions, 30 types, called from 3 files);homeassistant/auth/__init__.py(45 functions, 4 classes, performs crypto, reads/writes files, makes network calls);homeassistant/components/assist_pipeline/pipeline.py(69 functions, 21 classes, reads/writes files).
How It Is Wired
Execution starts at homeassistant/__main__.py:168 (main). From there the flow reaches ensure_config_path (mkdirs config dir), then proceeds to component set‑up via async_setup_entry across many integrations. The assist pipeline (pipeline.py) executes execute (line 1684) which resolves language models and runs intent pipelines, touching the filesystem for language data and making outbound calls to speech‑to‑text services.
A concrete leak path: main → restore_backup [filesystem via backup_file_path.unlink] demonstrates that a backup‑restore routine can delete arbitrary files if the backup path is controllable. Another path: ensure_config_path [filesystem via os.mkdir] shows that missing config directories are auto‑created, which can be abused to plant files under the Home Assistant user’s home.
The call graph reveals cycles through interfaces → Alexa → AlexaEndpointHealth and capability_resources → serialize_capability_resources, meaning changes to the Alexa capability definition ripple across 23 downstream edges, inflating the blast radius of any breaking change.
How To Use It
Setup
# Clone the exact repo the brief references
git clone https://github.com/moses-y/Home-Assistant-core.git
# Install into a virtualenv (pip is the declared package manager)
python -m venv .venv && source .venv/bin/activate
pip install -e .[all] # installs with optional extras
Configuration The single config file is configuration.yaml (created under $HOME/.homeassistant/ on first run). Secrets are stored in secrets.yaml – the code‑health audit flagged tests/components/elmax/fixtures/direct/cert.pem and tests/util/yaml/test_secrets.py as secret‑shaped paths; ensure any real keys live there and are not committed to version control.
Running it
# Start the Home Assistant server (Docker alternative also available)
ha core start
# or, via the entry point
python -m homeassistant --config $HOME/.homeassistant
The CLI entry point is homeassistant/__main__.py:168 (main). Docker users can build from Dockerfile; the image tags are not pinned to a commit SHA (see Code Health below).
Real‑World Use
A developer adding a new Z‑Wave lock creates a component under homeassistant/components/zwave/. The component’s async_setup_entry registers a Lock entity, which the assist pipeline can expose via Alexa through homeassistant/components/alexa/capabilities.py. The pipeline’s execute function resolves the lock state, calls the model for natural‑language intent, and writes the resulting state to the Home Assistant state store (SQLite by default). If the lock’s firmware update API is reachable, the same flow makes an outbound network call – the analyst should verify TLS certs and restrict outbound hosts in configuration.yaml.
Code Health & Issues
The static analysis produced three findings (0 critical, 2 high, 0 medium, 1 low):
- HIGH – Pin third‑party GitHub Actions to a commit SHA Evidence:
.github/workflows/*referencehome-assistant/actions/helpers/info@master,…/version@master,…/verify-version@master,…/git-init@master. A tag can move, so the action running with repository secrets may change without a code change. Fix: Replace each@vNwith the 40‑character commit SHA (keep the version comment) and let Dependabot bump the SHAs.
- HIGH – Commit a lockfile beside the manifest Evidence:
pyproject.tomlhas no lockfile in scope. Without a locked set of transitive dependencies, the artifact tested can differ from the artifact shipped. Fix: Runpip lock(oruv lock) once and commit the generatedrequirements.txt/uv.lockalongsidepyproject.toml.
- LOW – Set timeout‑minutes on the workflow jobs Evidence: 3 workflows in
.github/workflows/declare notimeout-minutes. A wedged step can run six hours (platform default), causing overlapping runs on a two‑hourly schedule. Fix: Add a realistictimeout-minutesto each job (e.g., 120 for build, 60 for test).
No lockfile, unpinned Actions, and missing job timeouts are the only SDLC gaps the structure supports; otherwise the repo has CI (GitHub Actions), Dockerfiles, and a licence file.
The Bottom Line
Home‑Assistant‑core is a large, modular home‑automation codebase with solid test coverage and a clear component model. Its main weaknesses are reproducibility (missing lockfile) and CI security (Actions pinned only to branch tags). Teams that need deterministic builds and supply‑chain safety should lock dependencies and pin Actions to SHAs immediately. For operators who value local control and can tolerate manual dependency management, the platform remains a capable, well‑documented foundation.