Skip to content

Commit 360a9c9

Browse files
vsilentvsilentCopilot
authored
Feature/detectors (vsilent#103)
* ebpf files * refactoring, ebpf / containers * feat(cli): add clap subcommands (serve/sniff) + sniff config - Add clap 4 for CLI argument parsing - Refactor main.rs: dispatch to serve (default) or sniff subcommand - Create src/cli.rs with Cli/Command enums - Create src/sniff/config.rs with SniffConfig (env + CLI args) - Add new deps: clap, async-trait, reqwest, zstd - Update .env.sample with sniff + AI provider config vars - 12 unit tests (7 CLI parsing + 5 config loading) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(sniff): log source discovery + database persistence - Create src/sniff/discovery.rs: LogSource, LogSourceType, discovery functions for system logs, Docker containers, and custom paths - Create src/database/repositories/log_sources.rs: CRUD for log_sources and log_summaries tables (follows existing alerts repository pattern) - Add log_sources and log_summaries tables to init_database() - Export docker module from lib.rs for reuse by sniff discovery - 14 unit tests (8 discovery + 6 repository) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(sniff): log reader trait + File/Docker/Journald implementations - Create src/sniff/reader.rs with LogReader async trait and LogEntry struct - FileLogReader: byte offset tracking, incremental reads, log rotation detection - DockerLogReader: bollard-based container log streaming with timestamp filtering - JournaldReader: journalctl subprocess (Linux-gated with #[cfg(target_os = "linux")]) - Add futures-util dependency for Docker log stream consumption - 10 unit tests covering read, incremental, truncation, empty lines, metadata Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(sniff): AI log analysis with OpenAI and pattern backends - Create src/sniff/analyzer.rs with LogAnalyzer trait - OpenAiAnalyzer: single client for OpenAI/Ollama/vLLM/any compatible API sends batched logs to /chat/completions, parses structured JSON response - PatternAnalyzer: fallback local analyzer using regex-free pattern matching detects error spikes, counts errors/warnings without external AI - LogSummary and LogAnomaly types with serialization support - JSON response parsing with graceful handling of partial LLM output - 16 unit tests (prompt building, JSON parsing, pattern analysis, serialization) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(sniff): consume mode — zstd compression, dedup, log purge - Create src/sniff/consumer.rs with LogConsumer - FNV hashing deduplication with configurable capacity (100k entries) - zstd compression (level 3) with timestamped archive files - File purge via truncation (preserves fd for syslog daemons) - Docker log purge via /var/lib/docker/containers/ JSON log truncation - Full consume pipeline: deduplicate → compress → purge → report stats - ConsumeResult tracks entries_archived, duplicates_skipped, bytes_freed - 13 unit tests (hashing, dedup, compression, purge, full pipeline) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(sniff): reporter + orchestrator loop - Reporter: converts LogSummary/LogAnomaly into Alerts using existing AlertManager infrastructure (route_by_severity, NotificationChannel) - SniffOrchestrator: full discover → read → analyze → report → consume pipeline with continuous and one-shot modes - Wire up run_sniff() in main.rs to use SniffOrchestrator - Add events, rules, alerting, models modules to binary crate - 7 new tests (reporter: 5, orchestrator: 3) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(sniff): REST API for log sources and summaries - GET /api/logs/sources — list discovered log sources - POST /api/logs/sources — manually add a custom log source - GET /api/logs/sources/{path} — get a single source - DELETE /api/logs/sources/{path} — remove a source - GET /api/logs/summaries — list AI summaries (optional source_id filter) - Register routes in configure_all_routes - 7 tests covering all endpoints Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: update CHANGELOG and README for sniff feature - CHANGELOG: document all sniff additions (discovery, readers, AI analysis, consumer, reporter, orchestrator, REST API, deps) - README: add log sniffing to key features, architecture diagram, project structure, CLI usage examples, REST API examples, and completed tasks list Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: remove task files from repo and gitignore Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: add curl-based binary installation - install.sh: POSIX shell installer — detects Linux x86_64/aarch64, downloads from GitHub Releases, verifies SHA256, installs to /usr/local/bin - release.yml: GitHub Actions workflow — builds Linux binaries on tag push using cross, creates release with tarballs + checksums - README: add curl install one-liner to Quick Start Usage: curl -fsSL https://raw.githubusercontent.com/vsilent/stackdog/dev/install.sh | sudo bash Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: fix ML module status — stub infrastructure, not in progress Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(cli): add --ai-model and --ai-api-url flags to sniff command - Add --ai-model flag to specify AI model (e.g. qwen2.5-coder:latest) - Add --ai-api-url flag to specify API endpoint URL - Recognize "ollama" as AI provider alias (maps to OpenAI-compatible client) - CLI args override env vars for model and API URL - Log AI model and API URL at startup for transparency Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(sniff): add debug logging and robust LLM JSON extraction - Add debug/trace logging across entire sniff pipeline: discovery, reader, analyzer, orchestrator, reporter - Respect user RUST_LOG env var (no longer hardcoded to info) - Improve LLM response JSON extraction to handle: markdown code fences, preamble text, trailing text - Include raw LLM response in trace logs for debugging parse failures - Show first 200 chars of failed JSON in error messages - Add 5 tests for extract_json edge cases Usage: RUST_LOG=debug stackdog sniff --once ... Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(alerting): implement real Slack webhook notifications - Add --slack-webhook CLI flag to sniff command - Read STACKDOG_SLACK_WEBHOOK_URL env var (CLI overrides env) - Implement actual HTTP POST to Slack incoming webhook API - Build proper JSON payloads with serde_json (color-coded by severity) - Add reqwest blocking feature for synchronous notification delivery - Wire NotificationConfig through SniffConfig → Orchestrator → Reporter - Add STACKDOG_WEBHOOK_URL env var support - Update .env.sample with notification channel examples - Add 3 tests for Slack webhook config (CLI, env, override priority) Usage: stackdog sniff --once --slack-webhook https://hooks.slack.com/services/T/B/xxx # or via env: export STACKDOG_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T/B/xxx Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update docker.yml * ci: upgrade deprecated GitHub Actions to v4 - actions/cache v2 → v4 - actions/upload-artifact v2 → v4 - actions/download-artifact v2 → v4 - actions/checkout v2 → v4 - docker/build-push-action v1 → v6 (+ docker/login-action v3) - github/codeql-action/upload-sarif v1 → v3 Fixes: deprecated action versions causing workflow failures Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * ci: modernize Docker CICD workflow - Replace deprecated actions-rs/* with dtolnay/rust-toolchain + cargo commands - Fix broken rustfmt/clippy steps (were using wrong action parameters) - Use Swatinem/rust-cache for simpler, faster dependency caching - Use ubuntu-latest runners instead of self-hosted - Add Docker Buildx for improved image builds - Trigger on PRs to main and dev (pushes :latest on every build) - Use npm ci for deterministic frontend installs - Add artifact retention-days: 1 to save storage Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * build: switch to musl targets and rustls for portable binaries - reqwest: use rustls-tls instead of native-tls (no OpenSSL dependency) - release.yml: build x86_64/aarch64-unknown-linux-musl (static binaries) - Dockerfile: update debian:buster-slim → bookworm-slim, drop libpq-dev Statically linked binaries work on any Linux distro including Alpine. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: add pre-commit hook and apply cargo fmt Add .githooks/pre-commit that runs: - cargo fmt --all --check (strict, blocks commit) - cargo clippy (shows warnings, blocks on compile errors) Enable with: git config core.hooksPath .githooks Also applies cargo fmt --all to fix existing formatting across codebase. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: resolve all clippy warnings - Remove unused imports across 17 files - Prefix unused variables/fields with underscore - Implement Default trait instead of inherent default() methods (dedup, threat_scorer) - Implement FromStr trait instead of inherent from_str() methods (AiProvider, LogSourceType) - Replace Iterator::last() with next_back() on DoubleEndedIterator - Derive Default for EbpfLoader instead of manual impl - Remove useless .into() conversion in database connection - Wrap too-many-arguments functions with param structs (SniffArgs, CreateLogSummaryParams) - Replace filter_map(Some(...)) with map(...) in build_readers - Replace manual find loop with Iterator::find - Collapse nested if-let in signature_matcher - Gate program_to_tracepoint with cfg for Linux+ebpf only - Move api module to library crate, fix binary to import from library - Fix pre-existing test_get_alerts_empty to init database - Use std::io::Error::other() instead of Error::new(Other, e) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use _pid consistently in get_process_comm Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: resolve clippy errors in Linux-only firewall modules - Remove unused imports in nftables.rs, quarantine.rs - Replace inherent to_string() with Display trait for NfTable - Remove needless borrows in .args() calls (iptables.rs, nftables.rs) - Prefix unused variables with underscore (response.rs) - Add error() getter to ResponseLog Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: remove redundant to_string() in format! args NfTable implements Display, so format! uses it directly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: convert NfTable to string before passing to args() Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: bump VERSION.md to 0.2.0 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: resolve warnings in tests and examples - Remove unused imports (AlertSeverity, AlertType, anyhow::Result, SyscallEvent, SyscallType) - Prefix unused variables with underscore - Fix EbpfLoader::default() test (returns value, not Result) - Fix KernelVersionTooLow fields to use String not integer literals - Remove unnecessary mut on enricher variables Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: restore mutable enricher in enrichment tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: align test mutability and silence unused ptrace events var Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(tests): clean remaining all-target warnings and invalid literal - remove useless UID >= 0 assertion (u32) - replace invalid u16 port overflow test with type-safety test - remove redundant serde_json import - fix cfg-sensitive unused vars in enrichment tests - clean monitor test vars in syscall monitor unit tests - remove unused TestRule in rules engine tests - use from_ref instead of cloned slice in sniff discovery test Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: restore used enrichment vars and silence ptrace unused vars Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: handle non-linux unused vars in enrichment tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test: fix ebpf loader creation assertion for linux builds Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test: use valid 64-char hex container ID in enrichment test Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * ci: fallback to npm install when web lockfile is missing Use npm ci only when web/package-lock.json exists to avoid EUSAGE in CI. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * web: add webpack config with TS entrypoint for dashboard build Fix CI frontend build fallback to default ./src entry by defining explicit entry ./src/index.tsx and html template. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * web: fix dashboard import paths and TypeScript build errors - Correct component imports from ../../services|types to ../services|types - Fix react-bootstrap Alert alias in ContainerList - Add explicit typed mappings for alert/container badge variants - Type websocket stats callback payload - Import fireEvent in ThreatMap tests - Improve WebSocket test mock shape to satisfy TS - Expose ApiService.api for existing tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * log: show API URL instead of dashboard bind address - Replace misleading "Web Dashboard" startup line - Show user-facing API URL and map 0.0.0.0 -> 127.0.0.1 for display Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * web: default API/WS endpoints to APP_PORT or 5555 - Inject APP_PORT and REACT_APP_API_PORT into webpack env - API service default: http://localhost:${port}/api (port from env, fallback 5555) - WS service default: ws://localhost:${port}/ws (port from env, fallback 5555) Fixes frontend trying to connect to hardcoded port 5000. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * web: normalize container API payloads to prevent runtime crashes Handle both snake_case and camelCase fields for containers API responses, with safe defaults for missing nested fields (securityStatus/networkActivity). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * web: fix threat statistics endpoint path Use /threats/statistics to match backend routes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * web: guard ThreatMap against missing stats buckets Handle absent byType/bySeverity in API responses to prevent runtime Object.entries(undefined) crashes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * web: restore CSS injection and degrade gracefully without WS endpoint - Use style-loader + css-loader for .css files (fix dashboard styling) - Add css/style loader deps to web package - WebSocket service now falls back to REST-only mode when /ws is unavailable to avoid noisy reconnect/error spam in dev Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * web: add left sidebar navigation to dashboard layout - Introduce Sidebar component with Overview/Threats/Alerts/Containers links - Update App layout to include sidebar + main dashboard content - Add section anchors in Dashboard for sidebar navigation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * web: move logo to sidebar and add top actions bar - Move logo into sidebar at 39x39 (30% larger than 30x30)\n- Remove "Stackdog Security Dashboard" header text\n- Add top bar with right-aligned actions menu button (...) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * install: fallback when latest release is missing - Handle GitHub /releases/latest 404 gracefully\n- Fallback to most recent release entry\n- Improve install usage examples to main branch URL Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: avoid panic on malformed .env - Make .env loading non-fatal in main\n- Print warning and continue with existing environment\n- Ensures stackdog --help works even with malformed .env Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: update README and changelog for installer/env fixes - README: switch install script examples to main and v0.2.1\n- CHANGELOG: document non-fatal .env loading and installer fallback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Limit sniff analyzer prompts Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add live mail abuse guard Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * iptables & nftables * multiple updates, eBPF, container API quality is improved * tests, ip_ban engine implemented, frontend dashboard improvements * logs, containers in ui, ports, ws * context.to_string() * clippy fix * clippy fix * clippy fix * ip_ban::engine::tests * GLIBC_2.39 not found fix, using musl * docker files * multi stage build * The problem was cross build reusing the default target directory, which already contained host-built build-script binaries. Now musl build uses its own isolated target di * mount docker.sock to stackdog container * Audit, analyze syslog, new detectors, sniff command enriched * Audit, analyze syslog, new detectors, sniff command enriched --------- Co-authored-by: vsilent <jabberroid@gmail.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 10d00d8 commit 360a9c9

File tree

181 files changed

+13559
-8259
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

181 files changed

+13559
-8259
lines changed

.githooks/pre-commit

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/sh
2+
set -e
3+
4+
echo "🐕 Stackdog pre-commit: running cargo fmt..."
5+
cargo fmt --all -- --check || {
6+
echo "❌ cargo fmt failed. Run 'cargo fmt --all' to fix."
7+
exit 1
8+
}
9+
10+
echo "🐕 Stackdog pre-commit: running cargo clippy..."
11+
cargo clippy 2>&1
12+
CLIPPY_EXIT=$?
13+
if [ $CLIPPY_EXIT -ne 0 ]; then
14+
echo "❌ cargo clippy failed to compile. Fix errors before committing."
15+
exit 1
16+
fi
17+
18+
echo "✅ Pre-commit checks passed."

.github/workflows/codacy-analysis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
steps:
2222
# Checkout the repository to the GitHub Actions runner
2323
- name: Checkout code
24-
uses: actions/checkout@v2
24+
uses: actions/checkout@v4
2525

2626
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
2727
- name: Run Codacy Analysis CLI
@@ -41,6 +41,6 @@ jobs:
4141

4242
# Upload the SARIF file generated in the previous step
4343
- name: Upload SARIF results file
44-
uses: github/codeql-action/upload-sarif@v1
44+
uses: github/codeql-action/upload-sarif@v3
4545
with:
4646
sarif_file: results.sarif

.github/workflows/docker.yml

Lines changed: 64 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -2,161 +2,100 @@ name: Docker CICD
22

33
on:
44
push:
5-
branches:
6-
- master
7-
- testing
5+
branches: [main, dev]
86
pull_request:
9-
branches:
10-
- master
7+
branches: [main, dev]
118

129
jobs:
13-
cicd-linux-docker:
14-
name: Cargo and npm build
15-
#runs-on: ubuntu-latest
16-
runs-on: [self-hosted, linux]
10+
build:
11+
name: Build & Test
12+
runs-on: ubuntu-latest
1713
steps:
18-
- name: Checkout sources
19-
uses: actions/checkout@v2
14+
- uses: actions/checkout@v4
2015

21-
- name: Install stable toolchain
22-
uses: actions-rs/toolchain@v1
16+
- name: Install Rust toolchain
17+
uses: dtolnay/rust-toolchain@stable
2318
with:
24-
toolchain: stable
25-
profile: minimal
26-
override: true
2719
components: rustfmt, clippy
20+
targets: x86_64-unknown-linux-musl
2821

29-
- name: Cache cargo registry
30-
uses: actions/cache@v2.1.6
31-
with:
32-
path: ~/.cargo/registry
33-
key: docker-registry-${{ hashFiles('**/Cargo.lock') }}
34-
restore-keys: |
35-
docker-registry-
36-
docker-
37-
38-
- name: Cache cargo index
39-
uses: actions/cache@v2.1.6
40-
with:
41-
path: ~/.cargo/git
42-
key: docker-index-${{ hashFiles('**/Cargo.lock') }}
43-
restore-keys: |
44-
docker-index-
45-
docker-
22+
- name: Cache Rust dependencies
23+
uses: Swatinem/rust-cache@v2
24+
25+
- name: Install cross
26+
run: cargo install cross --git https://github.com/cross-rs/cross
4627

4728
- name: Generate Secret Key
48-
run: |
49-
head -c16 /dev/urandom > src/secret.key
29+
run: head -c16 /dev/urandom > src/secret.key
5030

51-
- name: Cache cargo build
52-
uses: actions/cache@v2.1.6
53-
with:
54-
path: target
55-
key: docker-build-${{ hashFiles('**/Cargo.lock') }}
56-
restore-keys: |
57-
docker-build-
58-
docker-
59-
60-
- name: Cargo check
61-
uses: actions-rs/cargo@v1
62-
with:
63-
command: check
31+
- name: Check
32+
run: cargo check
6433

65-
- name: Cargo test
66-
if: ${{ always() }}
67-
uses: actions-rs/cargo@v1
68-
with:
69-
command: test
34+
- name: Format check
35+
run: cargo fmt --all -- --check
7036

71-
- name: Rustfmt
72-
uses: actions-rs/toolchain@v1
73-
with:
74-
toolchain: stable
75-
profile: minimal
76-
override: true
77-
components: rustfmt
78-
command: fmt
79-
args: --all -- --check
80-
81-
- name: Rustfmt
82-
uses: actions-rs/toolchain@v1
83-
with:
84-
toolchain: stable
85-
profile: minimal
86-
override: true
87-
components: clippy
88-
command: clippy
89-
args: -- -D warnings
90-
91-
- name: Run cargo build
92-
uses: actions-rs/cargo@v1
93-
with:
94-
command: build
95-
args: --release
37+
- name: Clippy
38+
run: cargo clippy -- -D warnings
39+
40+
- name: Test
41+
run: cargo test
42+
43+
- name: Build static release
44+
env:
45+
CARGO_TARGET_DIR: target-cross
46+
run: cross build --release --target x86_64-unknown-linux-musl
9647

97-
- name: npm install, build, and test
48+
- name: Build frontend
9849
working-directory: ./web
9950
run: |
100-
npm install
51+
if [ -f package-lock.json ]; then
52+
npm ci
53+
else
54+
npm install
55+
fi
10156
npm run build
102-
# npm test
10357
104-
- name: Archive production artifacts
105-
uses: actions/upload-artifact@v2
106-
with:
107-
name: dist-without-markdown
108-
path: |
109-
web/dist
110-
!web/dist/**/*.md
111-
112-
# - name: Archive code coverage results
113-
# uses: actions/upload-artifact@v2
114-
# with:
115-
# name: code-coverage-report
116-
# path: output/test/code-coverage.html
117-
- name: Display structure of downloaded files
118-
run: ls -R web/dist
119-
120-
- name: Copy app files and zip
58+
- name: Package app
12159
run: |
12260
mkdir -p app/stackdog/dist
123-
cp target/release/stackdog app/stackdog
124-
cp -a web/dist/. app/stackdog
61+
cp target-cross/x86_64-unknown-linux-musl/release/stackdog app/stackdog/
62+
cp -a web/dist/. app/stackdog/
12563
cp docker/prod/Dockerfile app/Dockerfile
126-
cd app
127-
touch .env
128-
tar -czvf ../app.tar.gz .
129-
cd ..
64+
touch app/.env
65+
tar -czf app.tar.gz -C app .
13066
131-
- name: Upload app archive for Docker job
132-
uses: actions/upload-artifact@v2.2.2
67+
- name: Upload build artifact
68+
uses: actions/upload-artifact@v4
13369
with:
134-
name: artifact-linux-docker
70+
name: app-archive
13571
path: app.tar.gz
72+
retention-days: 1
13673

137-
cicd-docker:
138-
name: CICD Docker
139-
#runs-on: ubuntu-latest
140-
runs-on: [self-hosted, linux]
141-
needs: cicd-linux-docker
74+
docker:
75+
name: Docker Build & Push
76+
runs-on: ubuntu-latest
77+
needs: build
14278
steps:
143-
- name: Download app archive
144-
uses: actions/download-artifact@v2
79+
- name: Download build artifact
80+
uses: actions/download-artifact@v4
14581
with:
146-
name: artifact-linux-docker
82+
name: app-archive
14783

148-
- name: Extract app archive
149-
run: tar -zxvf app.tar.gz
84+
- name: Extract archive
85+
run: tar -xzf app.tar.gz
15086

151-
- name: Display structure of downloaded files
152-
run: ls -R
87+
- name: Set up Docker Buildx
88+
uses: docker/setup-buildx-action@v3
15389

154-
- name: Docker build and publish
155-
uses: docker/build-push-action@v1
90+
- name: Login to Docker Hub
91+
uses: docker/login-action@v3
15692
with:
15793
username: ${{ secrets.DOCKER_USERNAME }}
15894
password: ${{ secrets.DOCKER_PASSWORD }}
159-
repository: trydirect/stackdog
160-
add_git_labels: true
161-
tag_with_ref: true
162-
#no-cache: true
95+
96+
- name: Build and push
97+
uses: docker/build-push-action@v6
98+
with:
99+
context: .
100+
push: true
101+
tags: trydirect/stackdog:latest

.github/workflows/release.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ jobs:
1818
strategy:
1919
matrix:
2020
include:
21-
- target: x86_64-unknown-linux-gnu
21+
- target: x86_64-unknown-linux-musl
2222
artifact: stackdog-linux-x86_64
23-
- target: aarch64-unknown-linux-gnu
23+
- target: aarch64-unknown-linux-musl
2424
artifact: stackdog-linux-aarch64
2525

2626
steps:
@@ -36,12 +36,14 @@ jobs:
3636
run: cargo install cross --git https://github.com/cross-rs/cross
3737

3838
- name: Build release binary
39+
env:
40+
CARGO_TARGET_DIR: target-cross
3941
run: cross build --release --target ${{ matrix.target }}
4042

4143
- name: Package
4244
run: |
4345
mkdir -p dist
44-
cp target/${{ matrix.target }}/release/stackdog dist/stackdog
46+
cp target-cross/${{ matrix.target }}/release/stackdog dist/stackdog
4547
cd dist
4648
tar czf ${{ matrix.artifact }}.tar.gz stackdog
4749
sha256sum ${{ matrix.artifact }}.tar.gz > ${{ matrix.artifact }}.tar.gz.sha256

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,7 @@ Cargo.lock
3333
# End of https://www.gitignore.io/api/rust,code
3434

3535
.idea
36+
*.db
3637
docs/tasks/
38+
web/node_modules/
39+
web/dist/

CHANGELOG.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.2.2] - 2026-04-07
11+
12+
### Fixed
13+
14+
- **CLI startup robustness**`.env` loading is now non-fatal.
15+
- `stackdog --help` and other commands no longer panic when `.env` is missing or contains malformed lines.
16+
- Stackdog now logs a warning and continues with existing environment variables.
17+
18+
- **Installer release resolution**`install.sh` now handles missing `/releases/latest` responses gracefully.
19+
- Falls back to the most recent release entry when no stable "latest" release is available.
20+
- Improves error messaging and updates install examples to use the `main` branch script URL.
21+
1022
### Added
1123

24+
- **Expanded detector framework** with additional log-driven detection coverage.
25+
- Reverse shell, sensitive file access, cloud metadata / SSRF, exfiltration chain, and secret leakage detectors.
26+
- file integrity monitoring with SQLite-backed baselines via `STACKDOG_FIM_PATHS`.
27+
- configuration assessment via `STACKDOG_SCA_PATHS`.
28+
- package inventory heuristics via `STACKDOG_PACKAGE_INVENTORY_PATHS`.
29+
- Docker posture audits for privileged mode, host namespaces, dangerous capabilities, Docker socket mounts, and writable sensitive mounts.
30+
31+
- **Improved syslog ingestion**
32+
- RFC3164 and RFC5424 parsing in file-based log ingestion for cleaner timestamps and normalized message bodies.
33+
1234
#### Log Sniffing & Analysis (`stackdog sniff`)
1335
- **CLI Subcommands** — Multi-mode binary with `stackdog serve` and `stackdog sniff`
1436
- `--once` flag for single-pass mode
@@ -66,6 +88,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6688
- Refactored `main.rs` to dispatch `serve`/`sniff` subcommands via clap
6789
- Added `events`, `rules`, `alerting`, `models` modules to binary crate
6890
- Updated `.env.sample` with `STACKDOG_LOG_SOURCES`, `STACKDOG_AI_*` config vars
91+
- Version metadata updated to `0.2.2` across Cargo, the web package manifest, and current release documentation.
6992

7093
### Testing
7194

Cargo.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "stackdog"
3-
version = "0.2.0"
3+
version = "0.2.2"
44
authors = ["Vasili Pascal <info@try.direct>"]
55
edition = "2021"
66
description = "Security platform for Docker containers and Linux servers"
@@ -48,13 +48,15 @@ r2d2 = "0.8"
4848
bollard = "0.16"
4949

5050
# HTTP client (for LLM API)
51-
reqwest = { version = "0.12", features = ["json", "blocking"] }
51+
reqwest = { version = "0.12", default-features = false, features = ["json", "blocking", "rustls-tls"] }
52+
sha2 = "0.10"
5253

5354
# Compression
5455
zstd = "0.13"
5556

5657
# Stream utilities
5758
futures-util = "0.3"
59+
lettre = { version = "0.11", default-features = false, features = ["tokio1", "tokio1-rustls-tls", "builder", "smtp-transport"] }
5860

5961
# eBPF (Linux only)
6062
[target.'cfg(target_os = "linux")'.dependencies]
@@ -78,6 +80,8 @@ ebpf = []
7880
# Testing
7981
tokio-test = "0.4"
8082
tempfile = "3"
83+
actix-test = "0.1"
84+
awc = "3"
8185

8286
# Benchmarking
8387
criterion = { version = "0.5", features = ["html_reports"] }

DEVELOPMENT.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Stackdog Security - Development Plan
22

3-
**Last Updated:** 2026-03-13
4-
**Current Version:** 0.2.0
3+
**Last Updated:** 2026-04-07
4+
**Current Version:** 0.2.2
55
**Status:** Phase 2 In Progress
66

77
## Project Vision

0 commit comments

Comments
 (0)