Skip to content

Release v2.1.x: Penguin-DAL migration, centralized libs, and test suite overhaul#46

Open
PenguinzTech wants to merge 112 commits into
mainfrom
v2.1.x
Open

Release v2.1.x: Penguin-DAL migration, centralized libs, and test suite overhaul#46
PenguinzTech wants to merge 112 commits into
mainfrom
v2.1.x

Conversation

@PenguinzTech

Copy link
Copy Markdown
Contributor

This pull request merges the v2.1.x branch into main, representing a significant modernization and consolidation of the Squawk codebase.

Key Changes

1. Architectural Consolidation

  • Centralized Libraries: Removed vendored libraries in favor of centralized .
  • Penguin-DAL Migration: Migrated and from PyDAL to , including new SQLAlchemy schemas and Alembic migrations.
  • Service Consolidation: Removed separate and components, integrating DHCP and Time (NTP/PTP) services directly across components.

2. Frontend Modernization

  • React WebUI: Converted the Flask web console to an API-only backend with a modern React-based WebUI ().
  • Dependency Hardening: Pinned and dependencies to exact versions and immutable SHA references.
  • Component Integration: Integrated (LoginPageBuilder, SidebarMenu, AppConsoleVersion) into the frontend applications.

3. Testing & Quality Assurance

  • Comprehensive Test Suite: Added a new directory with E2E (Playwright), Integration, Load, and Smoke tests.
  • Coverage Improvements: Achieved 100% coverage for key frontend components (Login, Sidebar) and improved Python test coverage for backend services.
  • CI/CD Hardening: Updated GitHub Actions workflows with security scanning (Trivy), dependency monitoring, and standardized build processes.

4. Infrastructure & Deployment

  • Standardized K8s: Added standardized Kubernetes deployment configurations and deployment scripts (, ).
  • Security Fixes: Resolved high-severity vulnerabilities in Next.js and other dependencies.

5. Documentation & Standards

  • Unified Documentation: Massive overhaul of and project-wide documentation to meet new base standards.
  • Standardized Templates: Added GitHub issue templates for bugs, features, and security reports.

PenguinzTech and others added 30 commits December 11, 2025 10:18
Version files added (all at v1.0.0):
- dns-client-go/.version - Go DNS client
- dns-server/.version - DNS server
- dns-client/.version - Python DNS client (docker-client)
- dns-server/flask_app/.version - Web console (webui)

Workflow updates:
- Go client workflow now uses dns-client-go/.version
- Build triggers only when component's .version changes
- Added Windows ARM64 to build targets (6 platforms total)
- Release tags now use format: v{VERSION}-go-client

Release notes reorganized with sections for each package:
- go-client, dns-server, docker-client, webui
- Each with independent versioning and changelogs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add .version file monitoring to all build workflows
- Implement epoch64 timestamp-based naming (alpha/beta-<epoch64>)
- Add version-based release naming (vX.X.X-alpha/beta)
- Add auto pre-release creation on .version changes
- Add security scanning (gosec for Go, bandit for Python, npm audit for Node.js)
- Create comprehensive docs/WORKFLOWS.md
- Update docs/STANDARDS.md with CI/CD section
- Update CLAUDE.md with CI/CD section and pre-commit checklist

🤖 Generated with Claude Code

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Backend:
- Add DHCP models (pools, leases, reservations, servers) with PyDAL
- Add Time models (servers, sync logs, clients, config) with PTP/NTP support
- Add full REST API for DHCP pool management and lease tracking
- Add full REST API for time server management and sync operations
- Fix RBAC middleware: add check_team_access function
- Fix team model: remove unsupported PyDAL unique constraint

Frontend:
- Add TypeScript types for DHCP and Time services
- Add DHCPPools management component with utilization visualization
- Add TimeServers management component with PTP/NTP protocol selection
- Integrate new tabs into Management page

Go Client:
- Add NTP client package with automatic server failover
- Add NTP forwarder to intercept OS time requests (port 123)
- Add time configuration with environment variable support
- Add CLI commands: time query, time forward, time status
- Add comprehensive unit and integration tests

Documentation:
- Update API.md with DHCP and Time API endpoints
- Update ARCHITECTURE.md with network services diagrams
- Update STANDARDS.md with service-specific guidelines

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Restructure from server-side templates to a three-container architecture:
- Flask backend serves JSON-only REST API with JWT + Flask-Login auth
- React WebUI (Vite + TypeScript + Tailwind) as separate nginx container
- DNS server unchanged

Flask changes: add Flask-JWT-Extended, Flask-CORS, Flask-Limiter; convert
all dashboard routes to /api/v1/ JSON endpoints; add safe PyDAL row
serialization (exact type checks to exclude RecordUpdater/LazySet);
enforce auth on all API endpoints.

Docker: add Dockerfile.api for Flask, dns-webui service with nginx
reverse proxy, update docker-compose.yml with new services.

Tests: add comprehensive smoke test suite (130 tests) covering container
health, API endpoints, JWT auth flows, pagination, and response formats.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes Dependabot alerts #33 and #34:
- CVE: Next.js HTTP request deserialization DoS (high)
- CVE: Next.js Image Optimizer DoS (medium)

Also fixes js-yaml prototype pollution via npm audit fix.

Remaining 2 moderate alerts (eslint stack overflow, Next.js PPR memory)
require breaking major version upgrades and have no stable patches.

quic-go alerts (#28-30) are already resolved on this branch (v0.59.0
includes all patches).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The root Dockerfile's dns-server and dns-client stages both COPY docs/
into the image. The .dockerignore was excluding the docs directory,
which would cause the CI docker-multi-build job to fail.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit addresses all identified security vulnerabilities across Python,
Node.js, and Go components, and adds extensive smoke test coverage for both
alpha (local) and beta (K8s) environments to ensure production readiness.

Security Fixes:
- Python: Update cryptography (41→44), PyMySQL (1.1.0→1.1.1), Pillow (10→11),
  aiohttp (3.9→3.11.11), add defusedxml for XXE prevention
- Node.js: Update react-router-dom (6→7), eslint (8→9), vite (5→7),
  next (15→16) to fix XSS, DoS, and stack overflow vulnerabilities
- Go: Fix integer overflow in NTP time handling, replace math/rand with
  crypto/rand, enforce TLS 1.2+ minimum, update quic-go to v0.59.0

New Features:
- Add version management script (scripts/version/update-version.sh)
  supporting major/minor/patch/build version increments
- Add 150 mock tests for isolated component testing (DNS client/server,
  Manager API, database operations)
- Add 79 comprehensive smoke tests covering security, edge cases,
  integration, and user experience for alpha and beta environments

Test Coverage:
- Security: 32 tests (auth, authorization, input validation, injection
  prevention, CORS, TLS, data isolation)
- Edge Cases: 37 tests (boundaries, special chars, concurrency, large
  datasets, error recovery)
- Integration: 39 tests (component communication, data flow, K8s
  integration, monitoring)
- User Experience: 24 tests (page loads, forms, navigation, error messages)
- Mock Tests: 150 tests (fast, isolated, no network/database dependencies)

Version: Bump to v2.1.1.1770072428 (patch increment for security fixes)

Resolves: Critical PyMySQL SQL injection, XSS in react-router, integer
overflow in Go NTP client, weak RNG in HTTP backoff, TLS misconfiguration

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Install shared/react_libs dependencies before webui build to resolve
zod module import error during vite build.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update dal2-beta cluster deployment to use the pre-existing
penguintech-wildcard-tls certificate from cert-manager instead of
generating a new certificate.

Changes:
- Create comprehensive K8s manifests in k8s/manifests/
- Configure ingress for squawk.penguintech.io with proper TLS
- Use pre-existing Cloudflare wildcard certificate (penguintech-wildcard-tls)
- Deploy DNS server, Flask API, WebUI, and Valkey services
- Add health checks, resource limits, and HA configuration (2 replicas)
- Configure proper routing: / → webui, /api/v1 → flask-api, /dns-query → dns-server

Ingress Configuration:
- Host: squawk.penguintech.io
- TLS Secret: penguintech-wildcard-tls (Cloudflare wildcard cert)
- SSL redirect enabled
- NGINX ingress class

Deployed to: dal2-beta cluster, squawk namespace

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove restrictive security contexts and add emptyDir volumes for
directories that need write access (database logs, nginx cache).

Fixes:
- flask-api: Health check path /api/v1/health → /health
- flask-api: Add volume mount for /app/flask_app/databases
- webui: Add volume mounts for nginx cache and run directories
- All: Remove runAsUser/runAsNonRoot to allow containers to start properly

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Change @penguin/react_libs reference from local file path to GitHub
repository to ensure consistent versioning across all PenguinTech projects.

- Update package.json to reference github:penguintechinc/penguin-libs#main
- Install @penguintechinc/react-libs from main branch
- Remove dependency on local shared/react_libs copy

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace local copies of shared libraries with git-referenced dependencies
from github.com/penguintechinc/penguin-libs. This ensures consistent
versioning across all PenguinTech projects.

- Remove entire shared/ directory (react_libs, node_libs, go_libs, py_libs,
  licensing, database) including duplicate shared/shared/ nested copy
- Update Dockerfile to remove COPY shared/react_libs build steps
- Update tailwind.config.js content path to node_modules dist
- Update all imports from @penguin/react_libs to @penguintechinc/react-libs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PenguinzTech and others added 3 commits April 22, 2026 14:32
* chore: upgrade GitHub Actions + add missing e2e/smoke test coverage

Actions upgrades:
- actions/checkout v5→v6, actions/cache v4→v5, actions/setup-go v5→v6
- docker/setup-qemu-action v3→v4, docker/setup-buildx-action v3→v4
- docker/build-push-action v6→v7, docker/login-action v3→v4
- docker/metadata-action → v6, linear-b/gitstream-github-action → v2

Test coverage gaps closed (per standards audit):
- /ready readiness endpoint tests in DNS server and web console smoke suites
- API filter/pagination param tests: /api/v1/queries (page, limit, empty page),
  /api/v1/domains (active filter), /api/v1/logs, /api/v1/ioc/feeds invalid-ID 404
- Playwright: one-time auth fixture + protected-route page-load tests for all
  7 web console routes (index, tokens, domains, permissions, blacklist, certs, logs)
- Playwright: form modal validation-error tests (new token, new domain)
- CI cleanup step (if: always()) for /tmp/playwright-squawk artifacts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: migrate ingress to Cilium Gateway API HTTPRoute

Replace nginx Ingress with Gateway API HTTPRoute targeting the shared
Gateway in the gateway namespace. Part of dal2-beta nginx-ingress EOL.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: pin gosec to v2.22.11 (last Go 1.24-compatible version)

gosec@latest resolves to v2.25.0 which requires Go >= 1.25.0.
Pin to v2.22.11 (go 1.24.0 minimum) to match our Go 1.24.2 toolchain.
Also fixes the @latest ban from dependency pinning standards.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add k8s/kustomize/base/ with DNS server, DNS client (Go), Valkey
- Add k8s/kustomize/overlays/beta/ patching CI images and beta resource limits
- DNS client bridges traditional UDP/TCP port 53 → squawk DoH (port 5300 internal)
- CoreDNS forward patch ready at k8s/coredns-external-patch.yaml (not applied yet)
- Extend push.yml: add build-dns-client + merge-dns-client jobs so squawk-dns-client
  gets a beta image on every branch push alongside the main squawk image

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment thread dns-client/requirements.txt Fixed
Comment thread docs/requirements.txt Fixed
Comment thread docs/requirements.txt Fixed
Comment thread docs/requirements.txt Fixed
Comment thread docs/requirements.txt Fixed
Comment thread docs/requirements.txt Fixed
Comment thread dns-client/requirements.txt Fixed
Comment thread dns-client/requirements.txt Fixed
Comment thread dns-client/requirements.txt Fixed
PenguinzTech and others added 3 commits May 9, 2026 17:07
… overlays

- Rename all kustomize base/overlay files from .yaml to .yml
- Add alpha overlay with local registry (localhost:32000)
- Create complete Helm chart: Chart.yaml, values-{base,beta,prod}.yml
- Add 7 Helm templates: namespace, dns-server, dns-client, valkey deployments/services
- Rename coredns-external-patch.yaml to .yml
- Support alpha (Kustomize), beta/prod (Helm) deployments
Adds a new Go service (squawk-k8s-dns) that watches the Kubernetes API
and serves cluster.local DNS queries directly from a local zone cache,
enabling eventual full CoreDNS replacement.

Key changes:
- pkg/zonecache: thread-safe in-memory zone cache (sync.RWMutex)
- pkg/k8swatcher: SharedIndexInformer watches Services + Endpoints;
  synthesizes A, AAAA, SRV, and pod records; headless vs ClusterIP aware
- pkg/resolver: dns.Handler routing cluster.local/in-addr.arpa to cache,
  all other queries forwarded to DoH upstream
- pkg/metrics: Prometheus metrics registry (OTel-bridge ready) covering
  query duration, cache hit/miss, upstream latency, watcher events
- pkg/forwarder: instrumented with Prometheus metrics
- cmd/squawk-k8s-dns: Cobra CLI serving UDP+TCP DNS on :5300 with
  /healthz, /readyz, /metrics on :8081
- Dockerfile.k8s-dns: multi-stage bookworm build, rootless UID 1000
- CI: build-k8s-dns + merge-k8s-dns jobs in push.yml
- K8s: Deployment, Service (53->5300), RBAC in Helm + Kustomize
- Helm: fix Helm 4.1.4 .helmignore negation bug (Chart.yaml missing error)
- Helm: rewrite NOTES.txt + nil-safe _helpers.tpl for Helm 4 strict mode

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment thread docs/requirements.txt Fixed
Comment thread dns-client/requirements.txt Fixed
Comment thread docs/requirements.txt Fixed
Comment thread docs/requirements.txt Fixed
Comment thread docs/requirements.txt Fixed
Comment thread dns-client/requirements.txt Fixed
Comment thread dns-client/requirements.txt Fixed
* fix(security): close auth bypass, remove default creds & backdoor tokens

Enterprise-readiness security hardening (Wave 2):

- CRITICAL: dns-server app/ verified JWT signatures on zone-authorization
  paths (selective_router, resilience) instead of verify_signature=False;
  fail-closed when JWT_SECRET_KEY unset. Adds regression tests.
- manager: no default SECRET_KEY/JWT_SECRET_KEY; ProductionConfig fails
  fast if unset; default config -> ProductionConfig; CORS allowlist
  (drop wildcard+credentials); admin seed requires SQUAWK_ADMIN_PASSWORD.
- bins (live server): strict Bearer parsing; import-time admin123 seed
  removed from flask_app.
- compose: all secret/password defaults now required (${VAR:?}).
- scripts/init-postgres.sql: backdoor seed tokens/wildcard grant removed
  (moved to unmounted scripts/dev-seed.sql).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: remove dead py4web/legacy code; add app/ to CI coverage

- Delete unreferenced stacks confirmed dead by parity audit: web/ py4web
  console, bins/py4web_extended_app.py (also removes an unauthenticated
  /metrics endpoint), bins/server_optimized.py, start_console.sh, and the
  web-console service in dns-server/docker-compose.yml.
- CI: add --cov=dns-server/app to build/release workflows; add
  non-blocking acceptance-future job for tests_full_future/ (migration
  parity gate); add dns-server/app codecov flag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: untrack committed virtualenvs and sqlite .table files

Remove vendored venv/ trees and *.table SQLite artifacts from version
control (kept on disk) and add .gitignore rules so they stay out.
These should never have been tracked; isolated in its own commit to
keep the security diff reviewable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(manager): add IOC ingestion schema (ioc_entry, ioc_override) + migration

Wave 3 / IOC migration Chunk A — database layer:
- Extend ioc_feed with format, enabled, parser_config, authentication,
  entry_count, last_success columns.
- Add ioc_entry (indicators + threat metadata + MISP refs, indexed) and
  ioc_override (token-scoped allow/block, expiry) tables.
- Alembic 002_ioc_entries chained off 001_initial (reversible).
- Reconcile the duplicate pydal ioc_feed def in models/config.py.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(manager): IOCIngestionService with feed parsing, overrides, matching

Wave 3 / IOC migration Chunk B — the ingestion service (parity gate green:
27/27 tests_full_future/test_ioc_manager.py pass).

- New app/services/ioc_ingestion_service.py (IOCManager): txt/csv/json/xml
  feed parsing, per-row typing for "mixed" feeds, domain wildcard + CIDR IP
  matching, per-token allow/block overrides with expiry, feed scheduling
  (update_frequency_hours), stats, cleanup_old_indicators, default feeds.
  Runtime DB via penguin-dal (reflects Chunk A schema); @DataClass(slots=True).
- Cache rebuilt after every mutation (ingest/update-all/override/cleanup).
- Failed feed fetches no longer counted as success; malformed content
  returns success=False.
- conftest: wire manager services path + temp DB schema (SQLAlchemy) for the
  acceptance suite. Add aiohttp dependency.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(ioc): wire ingestion into config-sync + resolver (end-to-end blocking)

Wave 3 / IOC migration Chunk C+D — make IOC blocking actually work:

manager:
- config_service.get_active_ioc_feeds() now returns feeds with normalized
  indicator `entries` under config key `ioc_feeds`; get_config_version()
  changes when ioc_entry data changes (triggers dns-server resync).
- blueprints/ioc_feeds.py POST /<id>/sync now ingests via IOCManager
  (was a no-op stub). IOCManager wired into app factory as app.ioc_manager.

dns-server (app/):
- Fix dead-path key bug: iocFeeds -> ioc_feeds (3 sites in main.py).
- ioc_checker: wildcard-domain + CIDR/IP matching; loads the feed contract.
- main.py: block resolved A/AAAA answers whose IP is in an IOC feed.

Tests: dns-server test_ioc_checker 21, manager test_config_ioc_sync 5,
acceptance test_ioc_manager 27 — all green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(security): SSRF guard on IOC feed fetching (both fetch sites)

Addresses automated security review finding (HIGH SSRF) on feed fetching:
- Add _assert_feed_url_safe(): rejects non-http(s) schemes and hosts that
  resolve to private/loopback/link-local/reserved/multicast/unspecified
  addresses (incl. cloud metadata 169.254.169.254). IOC_ALLOW_PRIVATE_FEEDS
  env override for on-prem internal feeds.
- Call the guard before fetching in BOTH sites: blueprints/ioc_feeds.py
  /sync endpoint and ioc_ingestion_service._update_single_feed
  (scheduled update_all_feeds).
- allow_redirects=False on both fetches (an allowed host could 302 to an
  internal target).
- Dedicated tests (test_ioc_ssrf.py, 10) + hermetic autouse fixture so the
  acceptance suite doesn't depend on live DNS. Acceptance gate stays 27/27.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(ioc): scheduled feed refresh via supercronic

Wave 3 / IOC migration Chunk E — auto-refresh (feeds previously updated
only on manual /sync):
- app/jobs/ioc_refresh.py: CLI (`python3 -m app.jobs.ioc_refresh`) running
  IOCManager.update_all_feeds(); structured stdout summary; non-zero exit on
  failure; PostHog gating hook stubbed. Tests: test_ioc_refresh_job (5).
- manager/backend/crontab + Dockerfile: supercronic (org standard, non-root)
  so the same image runs gunicorn (default) or supercronic (scheduler) via
  CMD override, every 30 min.
- K8s: manager Deployment + manager-scheduler Deployment (Helm + Kustomize
  base; overlays validate). securityContext hardened; DB_URL via Secret;
  scheduler single-replica to avoid concurrent runs.

NOTE: supercronic image digest not pinned (sandbox lacks ghcr.io access);
documented TODO with fetch command in Dockerfile — tracked under Wave 6
external-image digest pinning.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(ioc): PostHog feature-flag + license gating

Wave 3 / IOC migration Chunk F — gate the feature per org rules:
- New app/services/posthog_client.py: feature_enabled() with graceful
  degradation (last-known cache, never raises), wired as app.posthog.
  New flags default OFF.
- IOC ingestion gated behind PostHog flag 'squawkdns.ioc-ingestion':
  refresh job skips when disabled; blueprint write/sync endpoints 403.
- Enterprise feed formats (taxii/misp/stix/openioc) gated behind license
  feature 'ioc_advanced_feeds' (402 unlicensed); community formats
  (txt/csv/json/xml) always allowed. Order: flag first, license second.
- POSTHOG_* config (optional; unset -> flags fall back to default).

Ships DARK: IOC stays disabled until 'squawkdns.ioc-ingestion' is enabled.
Tests: test_ioc_gating (16) + regressions; 63 IOC tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(manager): add WHOIS cache schema + Alembic 003

Wave 3 / WHOIS migration W-A: whois_cache, whois_search_index,
whois_query_log SQLAlchemy tables + Alembic 003_whois_cache chained off
002_ioc_entries. Foundation for the WHOIS service.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(manager): WHOISManager service (domain/IP lookup, cache, RDAP fallback)

Wave 3 / WHOIS migration W-B — service to the acceptance spec (19/19
test_whois_manager.py green):
- app/services/whois_service.py: async lookup_domain/lookup_ip (flat result
  shape), penguin-dal cache in whois_cache, RDAP -> legacy whois fallback,
  search_whois, get_stats, cleanup_old_data(retention_days=), _is_valid_domain/
  _is_valid_ip, asyncio rate limiting + same-domain dedup. Runtime DB via
  penguin-dal (reflects W-A tables; no self-migration).
- whois_manager.py alias for the acceptance import path.
- conftest temp_db creates whois tables. Pin python-whois==0.9.6, ipwhois==1.3.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(whois): API blueprint, PostHog gating, scheduled cleanup

Wave 3 / WHOIS migration W-C — complete the feature:
- app/blueprints/whois.py: GET /api/v1/whois/{domain/<d>,ip/<ip>,search,stats},
  token-required, gated behind PostHog flag 'squawkdns.whois-lookup' (403 when
  off); sanitized errors.
- app/jobs/whois_cleanup.py: daily cleanup CLI, flag-gated (skips when off).
- app factory wires app.whois_manager + registers whois_bp.
- crontab: daily whois_cleanup alongside ioc_refresh (supercronic).

WHOIS ships DARK (flag default OFF); community-entitled (flag-gated, not
enterprise-locked). Full IOC+WHOIS suite: 91 tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(manager): migrate client-config generation + fix cross-tenant IDOR

Wave 3 / client-config migration (23/23 acceptance green):
- schema: deployment_domain, client_config, config_role, config_user_role,
  client_instance, config_history (+ Alembic 004). Service
  app/services/client_config_service.py on penguin-dal; blueprint
  app/blueprints/client_config.py gated by PostHog flag squawkdns.client-config.
- SECURITY (cross-tenant IDOR, from security review): register_client now
  scopes client_instance lookup by domain_id and rejects a client_id already
  registered under another domain; assign_config_to_client refuses a config
  whose domain_id differs from the client's. Regression test
  test_client_config_tenant.py (2).
- Test maintenance for intended changes: test_config default->ProductionConfig,
  test_schema expected table set incl. ioc/whois/client_config tables,
  test_app limiter check tolerant of mocked penguin_limiter. conftest temp_db
  creates config tables + resilient teardown. .gitignore: *.db artifacts.

Full manager+acceptance suite: 144 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(dns-server): migrate Prometheus metrics into app/services (33/33)

Wave 3 / prometheus-metrics migration:
- Real prometheus_client-based metrics (counters/histograms/labels, 0.0.4
  exposition) now live in the SURVIVING tree: dns-server/app/services/
  prometheus_metrics.py. app/main.py + grpc_server.py repointed off the
  hand-rolled MetricsReporter to init_prometheus_metrics()/record_query();
  /metrics serves the real exposition. Pinned prometheus-client==0.21.1.
- Import correctness: app/main.py imports from app.services.prometheus_metrics
  (works under `python -m app.main` with bins/ absent), NOT the legacy bins
  copy. tests_full_future/conftest adds app/services to sys.path so the
  acceptance test resolves to the surviving module (not bins, which is slated
  for deletion). Left bins/prometheus_metrics.py unchanged (removed in Wave 5).

Acceptance: 33/33 (dns-server venv). penguin_dal group unaffected: 71/71.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(k8s): add default-deny NetworkPolicies (Helm + Kustomize)

Wave 6 hardening — the audit found ZERO NetworkPolicies. Adds a default-deny
(ingress+egress) baseline for the squawk namespace plus scoped allow rules,
wired into BOTH deploy methods (Kustomize base -> all overlays; Helm template
gated by networkPolicy.enabled=true):
- default-deny-all + allow-same-namespace + allow-egress-kube-dns.
- dns-server/dns-client: public ingress 53 udp/tcp + DoH 8080; upstream DNS egress.
- manager + manager-scheduler: ingress 5000/50051 same-namespace only; egress
  443 (+53) for IOC feed fetch, license.penguintech.io, PostHog; egress 5432 to
  external Postgres.
- valkey(6379)/postgres(5432): ingress from same-namespace app pods only.

Selectors use app.kubernetes.io/name+component (consistent across both deploy
methods). Renders: kustomize alpha/beta = 11 NetworkPolicy each; helm = 12
(adds allow-ingress-k8s-dns). helm lint clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(dns-server): migrate selective DNS routing to penguin-dal (25/25)

Wave 3 / selective-dns-routing migration (final acceptance-tested feature):
- Reimplemented dns-server/app/services/selective_dns_routing.py on penguin-dal
  (was raw pydal — standards violation): SelectiveDNSRouter with group-based
  zone visibility (public/internal/restricted/private), wildcard + domain-
  hierarchy matching, strict token->user resolution (unknown token -> None).
- Tables added to manager schema (dns_group, user_group_assignment,
  dns_routing_zone, group_zone_access) + Alembic 005; dedicated dns_routing_zone
  name avoids clobbering existing dns_zone. conftest temp_db creates them.
- Removed an unacceptable hack the migration introduced (hardcoded
  "test-token-123" seeded from production assign_user_to_group). The canonical
  test principal is now seeded in the test's dns_router fixture instead.
- sample_token_data now returns the schema `token` id (what services read),
  making token_id assertions order-robust. test_schema expected set updated.
- Existing selective_router.py (JWT-verify fix) untouched; no verify_signature
  False on any authz path.

Acceptance: selective 25/25; penguin_dal group 96; prometheus 33; manager unit 73.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(dns-server): mTLS certificate lifecycle (penguin-dal, 39 tests)

Wave 3 / build-with-authored-tests (user-requested):
- New dns-server/app/services/cert_manager.py — CertManager mTLS lifecycle:
  self-signed CA create/load, server cert issuance (SAN), client cert
  issue/sign with CN identity, verification against CA (chain + validity),
  expiry detection, rotation, and revocation (CRL-ish). penguin-dal for all
  runtime persistence (SQLAlchemy is schema-only). Gated by PostHog flag
  squawkdns.mtls (default OFF, graceful degradation). cryptography==44.0.0.
- Schema: mtls_certificate + mtls_revocation tables + Alembic 006 (chained
  after 005). conftest temp_db + test_schema expected set updated.
- Authored suite dns-server/tests_full_future/test_cert_manager.py: 39 tests
  (CA, server/client issuance, verify valid/wrong-CA/expired/tampered,
  revocation, rotation, expiry, flag-off) — run under manager venv (penguin-dal).

Regression: penguin_dal group 96; prometheus 33; manager unit green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(dns-server): HTTP/3 (QUIC) serving via hypercorn (20 tests)

Wave 3 / build-with-authored-tests (user-requested):
- New dns-server/app/services/http3_serving.py — build_serving_config() builds a
  hypercorn Config that adds quic_bind (HTTP/3) alongside the TCP bind when
  enabled, wiring TLS cert/key (HTTP/3 mandates TLS). Integrates CertManager to
  obtain a server cert when explicit TLS_CERT_FILE/KEY are absent. Fails safe:
  no TLS material -> HTTP/3 disabled, resolver still serves DoH over HTTP/2
  (never QUIC without TLS). ALPN h3,h2,http/1.1 when on; h2,http/1.1 when off.
- Config: HTTP3_ENABLED (default False), QUIC_BIND (0.0.0.0:8443),
  TLS_CERT_FILE/KEY. Gated by PostHog flag squawkdns.http3 (default OFF) with
  graceful degradation (flag server unreachable -> TCP-only). hypercorn[h3]==0.18.0.
- app/main.py __main__ now launches via hypercorn serve() with this config
  (hypercorn ASGI, not gunicorn/uvicorn).
- Authored suite test_http3_serving.py: 20 tests (disabled default, enabled+cert,
  fail-safe without cert, flag precedence, CertManager integration, degradation).

Regression: prometheus 33; cert+selective 64.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* build(dns-server): repoint container run to app.main (hypercorn) + native healthcheck

Wave 4 — repoint build from the legacy bins/ stack to the canonical Quart app:
- Root Dockerfile (dns-server + production stages) and dns-server/Dockerfile now
  run `python -m app.main` (PYTHONPATH=/app/dns-server) — the Quart resolver
  served by hypercorn (app.main __main__ builds the hypercorn/HTTP-3 config).
  No more bins/server.py / bins/server_premium_integrated.py.
- Replaced curl HEALTHCHECKs with native Python urllib.request checks against
  /health (no curl/wget — org standard). Venv installs full app requirements
  (quart, hypercorn[h3], penguin-dal, prometheus-client, cryptography).
- Production image builds clean (docker build --target production OK).
- Note: testing stage still runs dns-server/tests (tests_full_future acceptance
  suite runs separately — needs manager schema + penguin-dal).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* ci: repoint dns-server workflows from bins/flask_app to app/

Wave 4 — align CI with the consolidated Quart stack ahead of legacy deletion:
- build.yml + server-release.yml: drop dns-server/flask_app/tests; coverage
  now --cov=dns-server/app (was bins/flask_app). In-image bandit/flake8 target
  app/ (was bins/). tests_full_future acceptance stays in its non-blocking job.
- version-monitor.yml: DNS server presence probe repointed from the deleted
  bins/server_optimized.py to app/main.py.
- All workflows remain SHA-pinned; YAML valid; no dangling bins/flask_app refs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* refactor: delete legacy dns-server stacks (bins/flask_app/web) — Wave 5

The Quart app (dns-server/app, run via `python -m app.main`) is the sole shipped
dns-server stack (Wave 4 repointed build/CI). Remove the now-dormant legacy trees:
- Deleted dns-server/bins/, dns-server/flask_app/ (+ its alembic/templates/tests),
  dns-server/web/ (py4web console), and dns-server/Dockerfile.api (flask image).
- Deleted obsolete tests that only exercised the removed stacks: dns-server/tests
  {test_dns_core, test_health_check, test_server_premium}, tests_full_future
  {test_server, test_api_integration, test_authentication}, tests/test_blacklist.
- Reconciled harnesses: dns-server/tests/conftest.py schema import repointed from
  flask_app to the manager schema (flask_app path removed); tests_full_future
  conftest dropped dead bins/web sys.path inserts; tests/unit/conftest dropped the
  flask_app path + unused mock_flask_app, and mock_admin_user no longer mutates the
  shared mock_user fixture (fixes a pre-existing cross-test bleed).
- Repointed tooling: Makefile coverage/black/mypy dns-server targets bins->app;
  codecov flags; scripts/deploy-beta.sh dropped the flask-api service;
  update-version.sh dropped flask_app/.version; install.py + dns-client compose
  console URL -> /health.

Surviving suites green: acceptance 135, in-image dns-server/tests 56, prometheus+
http3 53, manager unit 73, root unit 52. dns-client/bins untouched (still ships).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* security(dns-client): default TLS verification on; no global warning suppression

Wave 6 hardening (audit #7): dns-client no longer disables cert validation by
default. _configure_ssl now: uses a CA bundle if configured, else verify=True
(default), else verify=False ONLY under the explicit SQUAWK_VERIFY_SSL=false /
config opt-out — and logs a prominent one-time warning that TLS is disabled.
Removed the global urllib3.disable_warnings() call.

(Note: 5 pre-existing dns-client gRPC-mock/failover test failures are unrelated
to this change — confirmed failing identically on HEAD.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* build(k8s): pin external image digests; drop supercronic :latest

Wave 6 hardening (audit #8, containers):
- manager/backend/Dockerfile: supercronic FROM :latest -> :0.2.47 (mutable tag
  removed). Full @sha256 digest pending — ghcr.io is unauthenticated/403 in this
  environment; the resolve command is documented inline for CI/dev with ghcr access.
- k8s/manifests/valkey-deployment.yaml: valkey/valkey:8-bookworm pinned by
  @sha256 digest.
- Verified other external base images (python/debian/golang/node/nginx) were
  already sha256-pinned in the Dockerfiles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: lint configs + git hooks + wire make targets; fix 3 bugs lint caught

Wave 6 hardening (audit #11):
- Add .flake8 (critical codes E9/F63/F7/F82 blocking), pyproject.toml (black/
  isort/mypy/pytest/coverage), .golangci.yml (staticcheck/gosec/errcheck/...),
  .pre-commit-config.yaml (gitleaks, flake8/black/isort, hadolint, shellcheck;
  pre-push heavier scans).
- Makefile: `lint` now blocking on critical flake8/hadolint (was `|| true`;
  black/isort/golangci/shellcheck advisory to avoid mass-reformatting existing
  code); smoke-test -> tests/smoke, test-e2e -> tests/integration+load, test-unit
  -> all unit suites; new `install-hooks`.
- Blocking flake8 immediately caught 3 real F821 undefined-name bugs (latent
  NameErrors) — fixed:
  * dns-server/app/grpc_server.py: response_time -> response_time_sec (prometheus
    migration leftover).
  * manager/backend/app/services/whois_service.py: db: DAL -> db: DB (dangling
    pydal type annotation after the penguin-dal conversion).
  * manager/backend/app/utils/decorators.py: handle_db_errors returned undefined
    `decorator` and had a misplaced inner return -> returns decorated_function.

make lint passes; affected suites green (whois + manager unit 92).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: track .pre-commit-config.yaml (negate broad *.yaml ignore)

The repo .gitignore has a broad `*.yaml` rule that silently ignored the new
pre-commit hook config (so `make install-hooks` had no config to install).
Add a `!.pre-commit-config.yaml` negation and commit the hook config.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: add lint tooling (flake8/black/isort/mypy) to dev requirements

Ensures `make lint` + pre-commit hooks have their tools available reproducibly:
add isort to dns-server/requirements-dev.txt and create
manager/backend/requirements-dev.txt with flake8/black/isort/mypy (dev-only,
not in the runtime images). Tools installed into both project venvs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: track manager dev requirements (negate broad *.txt ignore)

The .gitignore `*.txt` blanket rule silently dropped new requirements files.
Add `!**/requirements*.txt` negation and commit manager/backend/requirements-dev.txt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: consolidate pytest config into pyproject.toml

Wave 6 (audit #14): the root pytest.ini was stale+broken — it referenced the
deleted dns-server/flask_app/tests + dns-server/bins coverage and forced a
blanket --cov-fail-under=98, and (as pytest.ini) silently overrode the clean
[tool.pytest.ini_options] in pyproject.toml. Deleted root pytest.ini and made
pyproject the canonical root config, migrating the full marker set (20 markers)
+ python_classes/functions. tests/pytest.ini kept as the scoped config for the
tests/ suite. Runs green (manager unit 73).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(dns-client): fix 5 pre-existing gRPC/failover test failures

Pre-existing failures (failed on HEAD, unrelated to the TLS hardening):
- test_query_failover: used hostnames rejected by IP validation + caught bare
  Exception -> use loopback IPs + requests.exceptions.RequestException.
- 4 gRPC client tests: protobuf/grpc optional-import left stub/request classes
  undefined at module scope. Client now defines safe fallbacks
  (DNSQueryServiceStub/QueryRequest/BatchQueryRequest/HealthCheckRequest = None)
  so the module attributes always exist; tests patch PROTOBUF/GRPC_AVAILABLE and
  the request classes to exercise the gRPC path.
TLS-verify hardening preserved (verify=True default; verify=False only on opt-out).

dns-client suite: 13 passed (was 8/5).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(dns-server): make in-image test conftest schema import defensive

CI "Run unit tests on complete application image" failed: after the legacy-stack
deletion, dns-server/tests/conftest.py imported the SQLAlchemy schema from
manager/backend/app — but the dns-server container image ships dns-server/ only,
so `from schema import metadata` raised ImportError and no in-image test could
collect.

Fix: try the manager schema (repo/canonical); on ImportError fall back to an
empty MetaData (the dns-server unit tests exercise app/services logic and don't
depend on manager-owned tables). clean_db_tables now references the module-level
metadata instead of re-importing. Verified: 56 passed both in-repo (manager
present) and with manager/backend absent (image scenario).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* security(manager): bump aiohttp 3.10.0 -> 3.11.11 (GHSA-6mq8-rvhq-8wgg)

Socket.dev flagged a HIGH CVE (GHSA-6mq8-rvhq-8wgg): aiohttp's HTTP parser
auto_decompress is vulnerable to a zip bomb. manager was pinned to the
vulnerable aiohttp==3.10.0; bump to 3.11.11 (matches dns-server, clears this +
other aiohttp advisories). aiohttp is used by the IOC ingestion service/feed
fetch. Verified: manager unit 73 + IOC/WHOIS acceptance green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(ci): install pytest in test image so in-image tests run

Two regressions broke the in-image pytest step in build.yml/server-release.yml:

1. dns-server/Dockerfile lacked `ARG SQUAWK_ENV`, so `--build-arg
   SQUAWK_ENV=test` never reached the RUN layer (docker emitted
   'UndefinedVar $SQUAWK_ENV'). $SQUAWK_ENV defaulted to production,
   the dev-deps branch was skipped, and pytest was never installed ->
   'No module named pytest'. Added the ARG and made the dev-install
   strict (no silent '|| echo' swallow) so a broken dev requirement
   fails the build instead of hiding.

2. dns-server/requirements-dev.txt had a corrupted final line
   ('responses>=0.23.0isort>=5.12.0') from an earlier append without a
   trailing newline, which made the whole `pip install -r
   requirements-dev.txt` fail. Split into two lines.

Verified: docker build --build-arg SQUAWK_ENV=test + in-image
'python3.13 -m pytest tests/' -> 56 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(security): bump aiohttp 3.11.11 -> 3.13.3 (GHSA-6mq8-rvhq-8wgg)

Socket.dev flagged a Block-level HIGH CVE on aiohttp 3.11.11: the HTTP
parser auto_decompress feature is vulnerable to a zip bomb
(GHSA-6mq8-rvhq-8wgg), affecting < 3.13.3. The prior bump (433e0bd)
cleared an older advisory but not this one. 3.13.3 is the patched
release; transitive deps are unpinned here so pip resolves them fresh
(verified aiohttp==3.13.3 resolves in python:3.13).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread dns-client/requirements.txt Fixed
PenguinzTech and others added 9 commits July 9, 2026 13:42
Reconcile the two divergent lines for the v2.1.x -> main release (PR #46).
main and v2.1.x had diverged bidirectionally; this merges them into a
lose-nothing UNION:

Kept from main (data plane + new components):
- dhcp-server/, ntp-server/ standalone protocol servers (to be hardened)
- Go client pkgs dhcp, ntp (NTS), transport (HTTP/3)
- website/ (marketing site)
- client dir naming: dns-client -> squawk-client, dns-client-go -> squawk-client-go

Kept from v2.1.x (consolidation + management plane, newer everywhere):
- app/ Quart stack, manager/ mgmt-plane (DHCP/time blueprints), k8s/ Helm+kustomize
- Go client pkgs time (classic NTP), k8swatcher, resolver, zonecache, metrics;
  cmd squawk-k8s-dns binary
- newer Python client (TLS-verify hardening + gRPC test fallbacks)
- all dependencies (penguin-dal, exact pins, hypercorn[h3], aiohttp 3.13.3),
  standards docs, lint configs

Resolution: dropped committed venv/build artifacts and main's local shared/
(violates penguin-libs standard); kept bins/flask_app deleted (consolidation).
Go client unified under squawk-client-go with all 15 packages (go build/vet/test
pass, both binaries build). Repointed all build/CI/Makefile/pyproject/k8s
references from dns-client(-go) to squawk-client(-go).

Verified on merged tree: manager 73, acceptance 135, http3+prometheus 53,
dns-server 56 tests pass; kustomize alpha/beta render; flake8 critical clean.

NOTE: dhcp-server/ntp-server are prototype-grade and are hardened in the
follow-up commits on this branch (persistence, real JWT auth, full RFC 8915 NTS).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the prototype's in-memory leases and any-token auth with a
production-grade DHCP-over-HTTPS service:

- Persistence via penguin-dal into the manager's dhcp_pool/dhcp_reservation/
  dhcp_lease tables (per-service scoped DATABASE_URL). Allocation engine stays
  in-server: discover honors reservations then picks a free IP, request creates
  a persistent lease (T1=50%/T2=87.5%), release marks released, background task
  expires leases. penguin-dal only — no raw SQLAlchemy/pydal at runtime.
- Real JWT HS256 auth (JWT_SECRET_KEY shared with manager, fail-closed):
  client endpoints require scope dhcp:read, admin endpoints dhcp:admin.
- Standards: @DataClass(slots=True), full type hints, PostHog flag
  squawkdns.dhcp-server (default OFF -> 503, graceful degradation), structlog,
  startup config validation, rootless Dockerfile (sha256-pinned bookworm base,
  native-python healthcheck).
- 32 tests (auth: header/signature/expiry/scope; allocation: offer/request/
  release/expiry/stats). Verified: 32 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the prototype's XOR cookie stub and any-token auth with a
production-grade, RFC 8915-compliant NTS server:

- NTS-KE (RFC 8915 §4): standalone pyOpenSSL TLS server on port 4460 that
  terminates TLS itself and derives c2s/s2c keys via the RFC 5705 exporter
  (label "EXPORTER-network-time-security", per-key context [proto|aead|dir]).
  Formal NTS-KE record encoding (Critical bit, End-of-Message, NEXT_PROTOCOL/
  AEAD_ALGORITHM/NEW_COOKIE records).
- Cookies: real AES-SIV-CMAC-256 AEAD sealing of key material under a rotating
  master key (version byte + grace window). No XOR.
- Authenticated time (RFC 8915 §5.7): NTPv4 over UDP with NTS extension fields;
  the NTS authenticator uses AES-SIV (NOT HMAC) — unsupported AEADs and any
  crypto failure fail closed rather than downgrading.
- Auth: JWT HS256 (shared JWT_SECRET_KEY, read at call time, fail closed),
  scope ntp:client for KE, ntp:admin for status.
- UDP port configurable via NTP_UDP_PORT (default 123) so deployment can bind a
  high port and stay rootless.
- Standards: @DataClass(slots=True), type hints, PostHog flag squawkdns.ntp-server
  (default OFF, graceful degradation), startup config validation, rootless
  Dockerfile (sha256-pinned bookworm base).
- 25 tests: NTS-KE record roundtrip, TLS-exporter key agreement, AES-SIV cookie
  seal/unseal (tamper/expiry/version), AES-SIV authenticator verify/generate,
  key confirmation, JWT scope checks. Verified: 25 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Automated security review flagged two plaintext-transport paths in the
merged client code:

- squawk-client (Python) gRPC used grpc.insecure_channel unconditionally,
  sending the bearer token in the clear. Now: loopback targets may stay
  plaintext for local dev; all other targets use grpc.secure_channel with
  ssl_channel_credentials (+ optional CA bundle) and the token attached as
  composite call-credentials (gRPC only permits these over TLS). Removed the
  dead access_token_call_credentials that was never wired to the call.
- squawk-client-go transport (http2.go) fell through to
  insecure.NewCredentials() (plaintext gRPC) when VerifySSL=false. Now keeps
  the channel encrypted with credentials.NewTLS(InsecureSkipVerify) — parity
  with the HTTP transports' verify=false — so the token is never on the wire
  in cleartext. Default remains fully-verified TLS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add Deployments/Services/NetworkPolicies for the two hardened servers to
both the Helm chart and the Kustomize base + alpha/beta overlays:

- dhcp-server: port 8081, /health probes, env JWT_SECRET_KEY (squawk-jwt-secret)
  + DATABASE_URL (dhcp-server-db, scoped dhcp-server-rw) + POSTHOG_KEY (optional).
- ntp-server: 8082 HTTP + 4460 NTS-KE (TLS terminated in-pod; documented that any
  future Gateway/Ingress fronting 4460 MUST use TLS/SNI passthrough, never
  terminate) + 123/udp Service -> targetPort 11123 so the pod binds a high UDP
  port and stays rootless. Mounts ntp-server-tls at /etc/ntp-tls.
- Rootless securityContext, resource tiers, feature flags default OFF in-app.
- Secrets referenced by name (must be provisioned out-of-band): squawk-jwt-secret,
  dhcp-server-db, ntp-server-tls, squawk-posthog-secret (optional).

kustomize alpha/beta render clean with the new resources.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
PyJWT==2.8.1 does not exist and penguin-dal>=1.0.0 exceeds the public
release (max 0.3.0); the image build failed at pip install. Pin PyJWT==2.10.1
and penguin-dal==0.3.0 (matching manager/dns-server), posthog==3.6.0. Verified:
docker build dhcp-server succeeds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The two new servers had no CI coverage. Add:
- build.yml: run dhcp-server tests (penguin-dal + JWT) and ntp-server tests
  (RFC 8915 NTS, with a generated TLS cert) in build-and-test; build + smoke
  their images (dep-import check) in docker-multi-build.
- server-release.yml: publish both on release tags via new matrix entries with
  per-service context/dockerfile and the org-standard image name
  ghcr.io/penguintechinc/squawk/{dhcp-server,ntp-server} (matching the k8s
  manifests). Generalized the build step to support separate-Dockerfile services
  alongside the existing root-Dockerfile targets.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Apply black formatting to the new/modified Python (agent-generated server code
and the client gRPC-TLS change). Formatting only — no behavior change; suites
still pass (dhcp 32, ntp 25, client 13) and blocking flake8 is clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The client union brought two codebases under squawk-client-go's blocking
golangci-lint gate, surfacing 89 issues. Fix all (linter now exits 0) without
weakening config:

- errcheck (29): handle/deferred-ignore Close()/Encode()/AddEventHandler().
- staticcheck (46): WriteString(Sprintf) -> Fprintf; deprecated
  http3.RoundTripper -> http3.Transport; remove ineffectual ctx assignments;
  labeled break.
- gosec (10): add ReadHeaderTimeout to http.Servers (G112); targeted
  //nolint:gosec with justification for intentional InsecureSkipVerify (G402,
  the opt-in no-plaintext TLS path) and safe integer conversions (G115).
- ineffassign (1), unused (3): remove dead ctx assignment and unused
  HTTP2Transport client fields.

Verified: golangci-lint run, go build ./..., go vet ./..., go test ./... all
exit 0; both binaries build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread dhcp-server/requirements.txt Fixed
Comment thread dhcp-server/requirements.txt Fixed
Comment thread dhcp-server/requirements.txt Fixed
Comment thread dns-server/requirements.txt Fixed
Comment thread dns-server/requirements.txt Fixed
Comment thread dhcp-server/requirements.txt Fixed
Comment thread dhcp-server/requirements.txt Fixed
Comment thread dns-server/requirements.txt Fixed
Comment thread dhcp-server/requirements.txt Fixed
Comment thread dns-server/requirements.txt Fixed
@socket-security

socket-security Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatednpm/​next@​15.5.9 ⏵ 15.5.1852 -13100 +7591 +19970
Addedpypi/​aiohttp@​3.13.37460100100100
Updatednpm/​eslint-config-next@​15.5.9 ⏵ 15.5.18991006598100
Updatednpm/​react-router-dom@​6.30.2 ⏵ 7.18.1100 +210065 -996100
Addednpm/​jsdom@​26.1.0951001009070
Addedpypi/​penguin-aaa@​0.1.010010010010070
Addedpypi/​penguin-dal@​0.3.010010010010070
Addedpypi/​penguin-licensing@​0.1.010010010010070
Addedpypi/​penguin-sal@​0.1.010010010010070
Addedpypi/​penguin-utils@​0.1.010010010010070
Addedpypi/​pytest-html@​4.2.09910010010070
Updatedpypi/​psycopg2-binary@​2.9.9 ⏵ 2.9.10100 +110010010070
Updatednpm/​@​typescript-eslint/​parser@​6.21.0 ⏵ 8.54.0100 +110071 +198 +1100
Addedgolang/​github.com/​prometheus/​client_golang@​v1.22.072100100100100
Updatedgolang/​github.com/​quic-go/​quic-go@​v0.50.0 ⏵ v0.59.174 +1100 +24100100100
Addedgolang/​k8s.io/​apimachinery@​v0.32.574100100100100
Updatednpm/​@​types/​react-dom@​18.3.7 ⏵ 18.2.01001007585100
Updatedgolang/​google.golang.org/​grpc@​v1.67.3 ⏵ v1.79.375 +1100 +75100100100
Addedgolang/​k8s.io/​client-go@​v0.32.57510010075100
Addednpm/​@​types/​recharts@​1.8.51001007580100
Updatedgolang/​google.golang.org/​protobuf@​v1.36.1 ⏵ v1.36.1075100100100100
Addedpypi/​mergedeep@​1.3.410010010075100
Addedgolang/​k8s.io/​api@​v0.32.576100100100100
Updatednpm/​@​types/​react@​18.3.27 ⏵ 18.2.01001007995 +3100
Updatednpm/​vitest@​1.6.1 ⏵ 4.1.1098 +1100 +7579 +199100
Updatednpm/​@​vitest/​coverage-v8@​1.6.1 ⏵ 4.1.109910079 +899 +2100
Updatednpm/​@​typescript-eslint/​eslint-plugin@​6.21.0 ⏵ 8.54.099 +1110080 +198100
Updatednpm/​@​emotion/​styled@​11.14.1 ⏵ 11.11.0991008182100
Updatednpm/​@​emotion/​react@​11.14.0 ⏵ 11.11.097 -21008782100
Updatednpm/​postcss@​8.5.6 ⏵ 8.4.3299998292 +3100
Updatednpm/​vite@​6.4.1 ⏵ 6.4.394100 +2483 +198100
Updatednpm/​react@​19.2.3 ⏵ 18.2.010010084 +197100
See 44 more rows in the dashboard

View full report

@socket-security

socket-security Bot commented Jul 9, 2026

Copy link
Copy Markdown

Caution

Review the following alerts detected in dependencies.

According to your organization's Security Policy, you must resolve all "Block" alerts before proceeding. It is recommended to resolve "Warn" alerts too. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Block High
Obfuscated code: npm data-urls is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: manager/frontend/package-lock.jsonnpm/jsdom@26.1.0npm/data-urls@5.0.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/data-urls@5.0.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: npm next is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: website/package-lock.jsonnpm/next@15.5.18

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/next@15.5.18. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: npm rrweb-cssom is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: manager/frontend/package-lock.jsonnpm/jsdom@26.1.0npm/rrweb-cssom@0.8.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/rrweb-cssom@0.8.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: npm scheduler is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: website/package-lock.jsonnpm/react-dom@19.0.0npm/scheduler@0.25.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/scheduler@0.25.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi flask is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: manager/backend/requirements.txtpypi/flask@3.1.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/flask@3.1.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi flask is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: manager/backend/requirements.txtpypi/flask@3.1.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/flask@3.1.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Medium
Low adoption: pypi penguin-dal

Location: Package overview

From: dhcp-server/requirements.txtpypi/penguin-dal@0.3.0

ℹ Read more on: This package | This alert | What are unpopular packages?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Unpopular packages may have less maintenance and contain other problems.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/penguin-dal@0.3.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Filesystem access: golang github.com/beorn7/perks

Location: Package overview

From: ?golang/github.com/prometheus/client_golang@v1.22.0golang/github.com/beorn7/perks@v1.0.1

ℹ Read more on: This package | This alert | What is filesystem access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: If a package must read the file system, clarify what it will read and ensure it reads only what it claims to. If appropriate, packages can leave file system access to consumers and operate on data passed to it instead.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/beorn7/perks@v1.0.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Unmaintained: golang github.com/beorn7/perks was last published 7 years ago

Last Publish: 7/31/2019, 12:00:54 PM

From: ?golang/github.com/prometheus/client_golang@v1.22.0golang/github.com/beorn7/perks@v1.0.1

ℹ Read more on: This package | This alert | What are unmaintained packages?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Package should publish periodic maintenance releases if they are maintained, or deprecate if they have no intention in further maintenance.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/beorn7/perks@v1.0.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Filesystem access: golang github.com/cespare/xxhash/v2

Location: Package overview

From: ?golang/google.golang.org/grpc@v1.79.3golang/github.com/prometheus/client_golang@v1.22.0golang/github.com/cespare/xxhash/v2@v2.3.0

ℹ Read more on: This package | This alert | What is filesystem access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: If a package must read the file system, clarify what it will read and ensure it reads only what it claims to. If appropriate, packages can leave file system access to consumers and operate on data passed to it instead.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/cespare/xxhash/v2@v2.3.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Filesystem access: golang github.com/davecgh/go-spew

Location: Package overview

From: ?golang/github.com/prometheus/client_golang@v1.22.0golang/k8s.io/client-go@v0.32.5golang/k8s.io/apimachinery@v0.32.5golang/github.com/davecgh/go-spew@v1.1.2-0.20180830191138-d8f796af33cc

ℹ Read more on: This package | This alert | What is filesystem access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: If a package must read the file system, clarify what it will read and ensure it reads only what it claims to. If appropriate, packages can leave file system access to consumers and operate on data passed to it instead.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/davecgh/go-spew@v1.1.2-0.20180830191138-d8f796af33cc. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Unmaintained: golang github.com/davecgh/go-spew was last published 8 years ago

Last Publish: 2/21/2018, 11:26:28 PM

From: ?golang/github.com/prometheus/client_golang@v1.22.0golang/k8s.io/client-go@v0.32.5golang/k8s.io/apimachinery@v0.32.5golang/github.com/davecgh/go-spew@v1.1.2-0.20180830191138-d8f796af33cc

ℹ Read more on: This package | This alert | What are unmaintained packages?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Package should publish periodic maintenance releases if they are maintained, or deprecate if they have no intention in further maintenance.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/davecgh/go-spew@v1.1.2-0.20180830191138-d8f796af33cc. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Filesystem access: golang github.com/emicklei/go-restful/v3

Location: Package overview

From: ?golang/k8s.io/client-go@v0.32.5golang/k8s.io/apimachinery@v0.32.5golang/github.com/emicklei/go-restful/v3@v3.11.0

ℹ Read more on: This package | This alert | What is filesystem access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: If a package must read the file system, clarify what it will read and ensure it reads only what it claims to. If appropriate, packages can leave file system access to consumers and operate on data passed to it instead.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/emicklei/go-restful/v3@v3.11.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Filesystem access: golang github.com/go-logr/logr

Location: Package overview

From: ?golang/k8s.io/client-go@v0.32.5golang/k8s.io/apimachinery@v0.32.5golang/github.com/go-logr/logr@v1.4.3

ℹ Read more on: This package | This alert | What is filesystem access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: If a package must read the file system, clarify what it will read and ensure it reads only what it claims to. If appropriate, packages can leave file system access to consumers and operate on data passed to it instead.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/go-logr/logr@v1.4.3. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Filesystem access: golang github.com/gogo/protobuf

Location: Package overview

From: ?golang/k8s.io/client-go@v0.32.5golang/k8s.io/apimachinery@v0.32.5golang/k8s.io/api@v0.32.5golang/github.com/gogo/protobuf@v1.3.2

ℹ Read more on: This package | This alert | What is filesystem access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: If a package must read the file system, clarify what it will read and ensure it reads only what it claims to. If appropriate, packages can leave file system access to consumers and operate on data passed to it instead.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/gogo/protobuf@v1.3.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Unmaintained: golang github.com/gogo/protobuf was last published 5 years ago

Last Publish: 1/10/2021, 8:01:47 AM

From: ?golang/k8s.io/client-go@v0.32.5golang/k8s.io/apimachinery@v0.32.5golang/k8s.io/api@v0.32.5golang/github.com/gogo/protobuf@v1.3.2

ℹ Read more on: This package | This alert | What are unmaintained packages?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Package should publish periodic maintenance releases if they are maintained, or deprecate if they have no intention in further maintenance.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/gogo/protobuf@v1.3.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Filesystem access: golang github.com/golang/protobuf

Location: Package overview

From: ?golang/google.golang.org/grpc@v1.79.3golang/k8s.io/client-go@v0.32.5golang/k8s.io/apimachinery@v0.32.5golang/google.golang.org/protobuf@v1.36.10golang/github.com/golang/protobuf@v1.5.4

ℹ Read more on: This package | This alert | What is filesystem access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: If a package must read the file system, clarify what it will read and ensure it reads only what it claims to. If appropriate, packages can leave file system access to consumers and operate on data passed to it instead.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/golang/protobuf@v1.5.4. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Filesystem access: golang github.com/google/gnostic-models

Location: Package overview

From: ?golang/k8s.io/client-go@v0.32.5golang/k8s.io/apimachinery@v0.32.5golang/github.com/google/gnostic-models@v0.6.8

ℹ Read more on: This package | This alert | What is filesystem access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: If a package must read the file system, clarify what it will read and ensure it reads only what it claims to. If appropriate, packages can leave file system access to consumers and operate on data passed to it instead.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/google/gnostic-models@v0.6.8. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Filesystem access: golang github.com/google/go-cmp

Location: Package overview

From: ?golang/google.golang.org/grpc@v1.79.3golang/github.com/quic-go/quic-go@v0.59.1golang/github.com/spf13/viper@v1.20.1golang/github.com/prometheus/client_golang@v1.22.0golang/k8s.io/client-go@v0.32.5golang/k8s.io/apimachinery@v0.32.5golang/github.com/miekg/dns@v1.1.68golang/google.golang.org/protobuf@v1.36.10golang/github.com/google/go-cmp@v0.7.0

ℹ Read more on: This package | This alert | What is filesystem access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: If a package must read the file system, clarify what it will read and ensure it reads only what it claims to. If appropriate, packages can leave file system access to consumers and operate on data passed to it instead.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/google/go-cmp@v0.7.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Unmaintained: golang github.com/google/gofuzz was last published 6 years ago

Last Publish: 8/4/2020, 10:43:24 PM

From: ?golang/github.com/prometheus/client_golang@v1.22.0golang/k8s.io/client-go@v0.32.5golang/k8s.io/apimachinery@v0.32.5golang/github.com/google/gofuzz@v1.2.0

ℹ Read more on: This package | This alert | What are unmaintained packages?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Package should publish periodic maintenance releases if they are maintained, or deprecate if they have no intention in further maintenance.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/google/gofuzz@v1.2.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Unmaintained: golang github.com/josharian/intern was last published 7 years ago

Last Publish: 12/14/2019, 10:12:22 PM

From: ?golang/k8s.io/client-go@v0.32.5golang/k8s.io/apimachinery@v0.32.5golang/github.com/josharian/intern@v1.0.0

ℹ Read more on: This package | This alert | What are unmaintained packages?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Package should publish periodic maintenance releases if they are maintained, or deprecate if they have no intention in further maintenance.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/josharian/intern@v1.0.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Filesystem access: golang github.com/mailru/easyjson

Location: Package overview

From: ?golang/k8s.io/client-go@v0.32.5golang/k8s.io/apimachinery@v0.32.5golang/github.com/mailru/easyjson@v0.7.7

ℹ Read more on: This package | This alert | What is filesystem access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: If a package must read the file system, clarify what it will read and ensure it reads only what it claims to. If appropriate, packages can leave file system access to consumers and operate on data passed to it instead.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/mailru/easyjson@v0.7.7. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Unmaintained: golang github.com/munnerz/goautoneg was last published 7 years ago

Last Publish: 10/10/2019, 8:34:16 AM

From: ?golang/github.com/prometheus/client_golang@v1.22.0golang/k8s.io/client-go@v0.32.5golang/k8s.io/apimachinery@v0.32.5golang/github.com/munnerz/goautoneg@v0.0.0-20191010083416-a7dc8b61c822

ℹ Read more on: This package | This alert | What are unmaintained packages?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Package should publish periodic maintenance releases if they are maintained, or deprecate if they have no intention in further maintenance.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/munnerz/goautoneg@v0.0.0-20191010083416-a7dc8b61c822. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Unmaintained: golang github.com/pkg/errors was last published 6 years ago

Last Publish: 1/14/2020, 7:47:44 PM

From: ?golang/github.com/pkg/errors@v0.9.1

ℹ Read more on: This package | This alert | What are unmaintained packages?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Package should publish periodic maintenance releases if they are maintained, or deprecate if they have no intention in further maintenance.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/pkg/errors@v0.9.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Filesystem access: golang github.com/prometheus/client_golang

Location: Package overview

From: squawk-client-go/go.modgolang/github.com/prometheus/client_golang@v1.22.0

ℹ Read more on: This package | This alert | What is filesystem access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: If a package must read the file system, clarify what it will read and ensure it reads only what it claims to. If appropriate, packages can leave file system access to consumers and operate on data passed to it instead.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/prometheus/client_golang@v1.22.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Filesystem access: golang github.com/prometheus/common

Location: Package overview

From: ?golang/github.com/prometheus/client_golang@v1.22.0golang/github.com/prometheus/common@v0.62.0

ℹ Read more on: This package | This alert | What is filesystem access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: If a package must read the file system, clarify what it will read and ensure it reads only what it claims to. If appropriate, packages can leave file system access to consumers and operate on data passed to it instead.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/prometheus/common@v0.62.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Filesystem access: golang github.com/prometheus/procfs

Location: Package overview

From: ?golang/github.com/prometheus/client_golang@v1.22.0golang/github.com/prometheus/procfs@v0.15.1

ℹ Read more on: This package | This alert | What is filesystem access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: If a package must read the file system, clarify what it will read and ensure it reads only what it claims to. If appropriate, packages can leave file system access to consumers and operate on data passed to it instead.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore golang/github.com/prometheus/procfs@v0.15.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

See 60 more rows in the dashboard

View full report

PenguinzTech and others added 2 commits July 9, 2026 14:53
…bump oauth2

CI environment mismatches surfaced on PR #46 (masked locally by a newer
toolchain / the manager venv):

- squawk-client-go/go.mod required `go 1.25.0` but all CI jobs run Go 1.24.2,
  breaking `go mod download`/build (Test Go Client, build-dns-client,
  build-k8s-dns). Lower to `go 1.24.0` (matches CI + rest of repo; 1.24.x is
  standards-acceptable while migrating).
- build.yml dhcp/ntp test steps installed only `pytest`; the server tests use
  `@pytest.mark.asyncio`, so add `pytest-asyncio` (the async tests failed with
  "async def functions are not natively supported").
- version-monitor.yml's format check required exactly vMAJOR.MINOR.PATCH but
  the repo's .version carries a build-epoch 4th component (v2.1.1.1770072428);
  accept an optional trailing .epoch.
- Bump golang.org/x/oauth2 v0.25.0 -> v0.30.0 (Socket HIGH CVE, transitive via
  k8s.io/client-go). go build + golangci-lint still clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…Trivy, Socket)

Test Go Client:
- .golangci.yml: target go 1.24 (was 1.25) to match CI's go1.24-built
  golangci-lint and go.mod; config parses clean, 0 issues.

build-and-test (NTP RFC 8915):
- Pin Flask 3.0.0 + Werkzeug 3.1.4 with Quart: Flask 3.1 requires a
  PROVIDE_AUTOMATIC_OPTIONS config key Quart doesn't set, breaking route
  registration (KeyError on test collection). dhcp mirrors the same pins.
- cryptography 48.0.1: RFC 8915 authenticator seals empty plaintext, which
  cryptography <45 rejects; 48.0.1 also clears the crypto HIGH CVEs below.
- ntp full suite verified 25/25.

build-dns-client:
- squawk-client-go/Dockerfile: restore stripped `\` line-continuations,
  drop Alpine-only apk/useradd -D on the Debian base, fix build path
  ./cmd/squawk-client (was ./cmd/squawk-dns-client). Builds amd64 locally.

Trivy (dependency CVEs):
- PyJWT 2.10.1 -> 2.13.0 (CVE-2026-32597/48526 HIGH + 4 more) in
  dhcp/ntp/manager.
- python-dotenv 1.0.1 -> 1.2.2 (CVE-2026-28684).
- quart 0.19.4 -> 0.20.0 in dhcp (CVE-2024-49767).
- cryptography 44.0.0 -> 48.0.1 in dns-server/manager
  (CVE-2026-26007 + GHSA-537c-gmf6-5ccf HIGH).

Socket (PR dependency alerts):
- axios 1.6.0 -> 1.18.1, vite 5.0.0 -> 5.4.21 in manager/frontend and
  services/dns-webui (+ regenerated package-lock.json).
- Regenerated docs/ and squawk-client/ pip lockfiles so the merge no longer
  downgrades certifi/gitpython/pathspec below main.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
# does not set, breaking route registration.
quart==0.20.0
flask==3.0.0
werkzeug==3.1.4
# does not set, breaking route registration.
quart==0.20.0
flask==3.0.0
werkzeug==3.1.4
# Flask 3.1+ requires a PROVIDE_AUTOMATIC_OPTIONS config key this Quart line
# does not set, breaking route registration.
quart==0.20.0
flask==3.0.0
PenguinzTech and others added 5 commits July 9, 2026 16:02
CI installs golangci-lint v1.64.8 (go install @latest under go1.24 can't
build v2, which needs go1.25), so a `version: 2` config was rejected
("config for v2 with v1"). Convert .golangci.yml to v1 schema
(issues.exclude-dirs, drop version key) and pin the workflow install to
@v1.64.8 (removes @latest drift).

Fix the errcheck findings the strict config (check-blank +
check-type-assertions) then surfaces:
- cmd/squawk-client/main.go: check json.MarshalIndent errors (5 sites).
- pkg/k8swatcher/watcher.go: guard informer type assertions with the
  two-value form + early return (6 sites) — unchecked assertions panic on
  tombstone/DeletedFinalStateUnknown objects.
- pkg/performance/dns_performance.go: check os.Hostname error.

Verified with golangci-lint v1.64.8 locally: 0 issues; go build + go test pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`make security` runs `gosec ./...` directly, which honors gosec's own
`#nosec` annotations but ignores `//nolint:gosec` (a golangci-lint-only
directive). The two intentional suppressions were written as `//nolint`,
so standalone gosec still failed:
- pkg/k8swatcher/watcher.go G115 (int32->uint16 port, always 0-65535)
- pkg/transport/http2.go G402 (opt-in InsecureSkipVerify when VerifySSL=false)

Switch both to `// #nosec Gxxx` (honored by standalone gosec and by
golangci's gosec). Verified with gosec v2.22.11 and golangci-lint v1.64.8
locally: both 0 issues; go build passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ain, renovate

Pod hardening:
- Add `seccompProfile: RuntimeDefault` to every workload (pod-level
  securityContext) across k8s/helm/squawk/templates + k8s/kustomize/base
  (16 manifests) — completes PodSecurity "restricted" posture. Both overlays
  render clean.

Dependabot remediation (101 open alerts → actionable set cleared):
- npm: 0 critical / 0 high across root, manager/frontend, website,
  services/dns-webui (verified via `npm audit`). Key bumps: vite 5→6.4.3,
  vitest 4.1.10, next 15.5.18, @playwright/test 1.61.1, react-router-dom
  7.18.1; transitive overrides for basic-ftp/lodash/ws/form-data/flatted/
  minimatch/picomatch/@remix-run/router. 9 moderate/low remain (no fix /
  breaking-only).
- Go (squawk-client-go): grpc v1.67.3→v1.79.3, quic-go v0.50.0→v0.59.1
  (no source changes needed; build + golangci v1.64.8 + gosec all pass).
- pip cryptography/PyJWT alerts were already cleared by the prior CVE commit
  (Dependabot will auto-close on rescan). shared/go_libs + shared/node_libs
  alert paths are stale (dropped in the merge).

Supply-chain (SLSA-style):
- cosign keyless (OIDC) image signing + syft SPDX SBOM generation/attestation
  added to push.yml, server-release.yml, go-client-release.yml. Every pushed
  image is signed by digest and gets an attested SBOM (+ uploaded artifact).
  New actions SHA-pinned; digests passed via injection-safe env vars; zizmor
  clean.

Automation:
- Add renovate.json (pinDigests for external images, vulnerability alerts,
  first-party images by tag) per standards.

Caveat: manager/frontend and services/dns-webui have pre-existing TypeScript
build errors and a react-router-dom v6→v7 major bump; these frontends are not
CI-built. Flagged for a follow-up frontend validation pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The per-platform SBOM step failed on arm64: syft can't scan a push-by-digest
per-arch image on the amd64 runner. Move cosign sign + syft SBOM/attest out of
the per-platform build jobs and into the MERGE jobs, signing the final
multi-arch index digest (the artifact users pull) — which scans cleanly on
amd64. Also adds multi-arch merges + signing for dhcp-server and ntp-server
(previously only per-arch tags, no merged manifest to sign).

id-token: write added to merge jobs; new uses: SHA-pinned; refs passed via
env-indirection (no new zizmor findings).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the global shared-secret HS256 scheme for USER tokens with asymmetric
signing: the manager SIGNS with a private key (ES256 default, RS256 supported);
dns-server, dhcp-server, ntp-server and the manager middleware VERIFY with the
public key, accepting algorithms ["ES256","RS256"] ONLY — never HS256 (blocks
the public-key-as-HMAC alg-confusion attack). Adds mandatory sub/iss/aud/tenant
claims; every verify site requires exp/iat/tenant and denies an empty tenant
(fail closed).

Manager (signer):
- config.py: JWT_ALGORITHM (default ES256), JWT_PRIVATE/PUBLIC_KEY[_FILE],
  JWT_ISSUER/AUDIENCE, TENANT_ID. ProductionConfig fails fast without keys;
  Dev/Test generate an ephemeral ES256 keypair. auth_service mints ES256 with
  the new claims. Per-server tokens (create_server_jwt) stay HS256 by design
  (per-server secret, TODO: SPIFFE/mTLS). client_config download tokens keep
  their per-instance HS256 secret (self-contained; TODO follow-up).

Verifiers (dns-server selective_router + resilience, dhcp auth, ntp verify_jwt):
- verify with the public key read at call time (supports rotation + testing),
  require tenant, reject HS256. Fail closed when no public key is configured.

Keys + deploy:
- scripts/gen-jwt-keys.sh (ES256/RS256 PEM generation, verified roundtrip).
- k8s: manager mounts jwt-private-key + jwt-public-key from Secret
  `squawk-jwt-keys`; verifiers project ONLY jwt-public-key (private key never
  enters a verifier pod). Helm values + Kustomize base wired; example Secret
  template added (placeholder only). *.pem gitignored.

Tests (verified locally): manager 86, dns-server 58 (auth-bypass regression
suite rewritten for ES256 + new forged-key/missing-tenant cases), ntp 27, dhcp
auth 22. New regression coverage: HS256 rejected, missing/empty tenant rejected,
wrong aud/iss rejected, RS256 round-trip, ES256 forged-key denied.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants