You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
[6.7.1] - 2026-07-25
Updated Starkiller to v3.6.0
Security
Fixed a path traversal vulnerability where a crafted multipart upload filename could write files outside the downloads directory via the avatar (POST /api/v2/users/{uid}/avatar) and download (POST /api/v2/downloads/) upload endpoints (#824)
Fixed
Empire Compiler downloads now authenticate against the GitHub API with GITHUB_TOKEN/GH_TOKEN when set, avoiding intermittent 403 rate-limit failures on shared egress IPs (e.g. CI). When the compiler still can't be fetched, the server degrades gracefully and raises a clear error only if C# compilation is attempted, instead of crashing at startup.
[6.7.0] - 2026-07-06
Fixed
http_malleable listener no longer crashes with AttributeError when a request arrives on a URI not defined in the malleable profile. It now returns a 404 default response instead of propagating an unhandled exception.
Added
Performance indexes migration (0002) — apply with poetry run alembic -c alembic.ini upgrade head (from the Empire root) on existing databases.
Changed
Migrated the data-access layer from the SQLAlchemy 1.x Query API to the 2.0 select() idiom across the core services, data_util, jwt_auth, the http/http_malleable listeners, and basic_reporting. Behavior-preserving and still synchronous; db.query() no longer appears in empire/server.
Migrated the ORM models in core/db/models.py from Column()/declarative_base() to 2.0 typed declarative (Mapped[]/mapped_column()). Schema-preserving: generated DDL is identical and alembic autogenerate detects no diff.
Modernization quick wins (no behavior change): timezone-aware datetime.now(UTC) in jwt_auth, O(1) startup existence checks in core/db/base.py, removal of the Python-2 old_div shim and unused math_util.py, and a ruff pre-commit bump to match pyproject.toml.
Bounded the dynamic-PowerShell helper caches with lru_cache and made script generation deterministic, cutting test_load_modules from ~54s to ~1s on CI.
Trimmed agent-comms SQL hot paths: dropped lazy="joined" on Agent.host, and used db.get(Agent, session_id) / a scalar select(Agent.hostname) in the hot request paths.
Collapsed the per-result-packet SessionLocal.begin() loop in _handle_agent_response so one agent callback opens a single transaction regardless of how many result packets it carries. Per-callback wall time roughly halves for multi-packet batches on MySQL (e.g. 2.0x at N=10, 2.2x at N=25); N=1 is unchanged. Trade-off: a mid-batch failure now rolls back the whole batch instead of partially committing.
Indexed columns the agent-comms / auth hot paths filter on: composite (listener, archived) on Agent, single-column AgentFile.session_id, AgentFile.parent_id, and User.username. Model-only via index=True; fresh databases pick the indexes up automatically.
profile_service.load_malleable_profiles preloads existing Profile names once and dedupes in-memory instead of one SELECT per file (mirrors module_service.load_modules). Duplicate names across categories now log a warning naming the conflicting file instead of being silently caught at commit time.
Lazy-loaded custom_generate module classes. The importlib.spec_from_file_location + Module() instantiation now happens on first execute and is cached, so boot skips the file-by-file import work for modules that may never run in a given session.
Replaced three large credential test fixtures with a tiny synthetic module to cut CI obfuscation time; production module sources are unchanged.
Promoted the main_menu_mock and module_service fixtures in test_modules.py to module scope so the five tests share one ModuleService.
Removed
Dropped 4 unused/redundant Python dependencies to reduce supply-chain surface: pycryptodome (superseded by cryptography in the 2021 pycrypto migration; no Crypto.* imports remain), pyOpenSSL (last imports removed in 2020 cleanup, forgotten in pyproject.toml), pytest-timeout (the @pytest.mark.timeout markers that justified it have since been removed), and the redundant direct coverage pin (already pulled transitively by pytest-cov).
Replaced python-jose with pyjwt. python-jose is effectively abandoned (last release 3.3.0 in 2022) and pulled unmaintained ecdsa / rsa transitive dependencies with a poor security history. pyjwt is the actively-maintained library FastAPI now recommends in its OAuth2/JWT tutorial; the call surface in jwt_auth.py is identical (jwt.encode/jwt.decode), with the exception type changing from JWTError to jwt.InvalidTokenError.
Replaced the SQLAlchemy-Utc dependency with a 90-line vendored module (empire/server/core/db/utc_datetime.py) carrying the upstream MIT notice. The package shipped only two helpers (UtcDateTime column type + dialect-aware utcnow() SQL expression); behavior — including per-dialect SQL — is byte-identical so the existing schema and column defaults are unchanged.
Replaced requests-file with inline file:// dispatch in plugin_service._download_tar using stdlib urllib.parse + Path.open. The dependency existed solely to mount a FileAdapter on a requests.Session for one method; HTTP downloads now use requests.get(...) directly and file:// URLs are handled with a short scheme check.
Modernized the vendored malleable/ profile parser from Py2/Py3 compatibility (six.moves.urllib.* + six.moves.range) to Py3 stdlib (urllib.parse + builtin range). Mechanical change — six.moves.urllib.parse ↔ urllib.parse is a 1:1 rename, and six.moves.range is just the Py3 builtin. Drops the six direct dep that was added back when python-jose was removed.
Fixed
Preserved subprocess diagnostics across stager compile failures: the Go/Dotnet compilers now include the return code and fall back to stdout when stderr is empty, and stager_service.generate_stager surfaces a 400 instead of a 500 stack trace.
Removed the instance-level threading.Lock in AgentCommunicationService that serialized all concurrent agent file writes; also fixed a zero-byte file left on decompression failure and guarded the download-progress calc against a malformed total_filesize.
Fixed clone_git_repo leaking its /tmp staging directory, which could fill a tmpfs-backed /tmp and cause cascades of unrelated-looking test failures.
Fixed the update-starkiller release action updating the wrong ref in config.yaml; it now scopes updates to starkiller.repo/starkiller.ref with yq.
Fixed undefer(AgentTask.output_original) referencing a nonexistent attribute (the column is original_output).