Skip to content

lantern 0.1.6

Latest

Choose a tag to compare

@ianclemence ianclemence released this 02 Oct 05:38
d5f6c11

lantern 0.1.6

Every item on the 0.1.5 roadmap is now built, plus two security-hardening
passes over the agent's own attack surface, bounded multi-agent delegation,
full session CRUD, and a real daemon mode.

Roadmap, closed

  • AD / Impacket-style tooling (--offensive-gated): GetUserSPNs.py
    (Kerberoasting), GetNPUsers.py (AS-REP roasting), crackmapexec
    (SMB/WinRM/LDAP enumeration - a closed allowlist of read-only modules,
    no execution method ever accepted), bloodhound-python (AD relationship
    collection).
  • API-schema-aware testing: api_schema_scan walks an OpenAPI/Swagger
    document and resolves the real auth requirement per endpoint, honoring
    operation-level security: [] overriding a document default.
    graphql_introspect reports whether introspection is enabled and, if so,
    the schema's types and root names. Both passive - they read a schema the
    target already serves and call nothing it describes.
  • Cloud posture / container exposure: cloud_bucket_check (anonymous
    S3/Azure Blob/GCS listing, credential-free), container_expose_check
    (unauthenticated Docker daemon API or anonymous Kubelet API, one read-only
    request), host_kubehunter (active, --offensive-gated).
  • Daemon mode: lantern queue add/list/remove plus lantern daemon,
    a polling loop against Lantern's own SQLite file (no socket, no HTTP
    server) that claims and runs jobs one at a time and stops cleanly on
    SIGINT/SIGTERM.
  • Bounded multi-agent delegation: researcher/coder/pentester can call
    delegate_task to spin off one sub-investigation. Four properties hold by
    construction, not just by docstring: a delegated task's tools are a
    subset of the calling role's own list, it shares the parent's scope/
    --offensive grant exactly, it cannot delegate again, and it's capped at
    5 steps per call / 10 total per role turn. Now rendered in chat as a
    nested block (↳ researcher delegates: "...") and logged to the audit
    trail as its own event.
  • Full session CRUD: lantern delete <flow-id> --yes; chat's /new
    and /delete <flow-id> yes, exercised live under a pty.

Five more native tools, and role-scoped tool schemas

waf_fingerprint (WAF/CDN signature match from one ordinary response - no
payloads - so a zero-finding scan can tell "clean" apart from "a WAF ate
every probe"), secret_scan (regex match for cloud/SaaS keys and JWTs on
text another tool already captured, every hit masked), host_testssl,
host_gobuster, and host_amass (active, --offensive-gated - distinct
from the passive subdomain_enum below).

Registry::defs_for(focus) now scopes the tool schemas sent to the model
to each role's own focus list instead of sending all 26 tools' schemas to
every role - pentester's per-call overhead drops to ~2,656 tokens,
researcher ~1,898, coder ~953, reflector ~444, down from a flat worst case
that was already over 3,400 before this release added anything.

Passive subdomain discovery, and prompts that earn their own budget

subdomain_enum (certificate-transparency lookup via crt.sh - touches no
target infrastructure). A role whose prompt repeats enough of its own
vocabulary (named injection classes, GraphQL/IAM/Kerberoasting/JWT/
container-escape, ...) now earns up to 4 extra steps over its static
default. Engagement-profile prompts (WebApp/Api/InternalAd/Cloud/
NetworkInfra) add a short block naming the right taxonomy (OWASP, MITRE
ATT&CK, CIS) and what the toolset genuinely cannot check for that profile,
so a role says "no tool for that" instead of narrating a check it never ran.

Security hardening

  • Scope bypass, closed: a bare CIDR target (e.g. msfconsole's RHOSTS)
    was checked against only its network's base address, so a scope of
    10.0.0.0/24 waved through a target of 10.0.0.0/8. A CIDR target is
    now checked as the whole range it names.
  • DNS drift pinned to the audit trail: host-tool targets are resolved
    immediately before execution; a hostname that now resolves outside every
    declared scope range is refused, and the resolved IPs land in the command
    audit row (new resolved_ips column) and in lantern report either way.
  • Runtime limits now actually device-derived: concurrency and child
    memory limits were computed from the live device profile and then
    discarded in favor of hardcoded defaults. They now derive from the host's
    real cores/RAM unless LANTERN_CONCURRENCY/LANTERN_CHILD_MEM_MB is set.
  • Unbounded reads, closed on both sides: every in-process HTTP fetch
    facing a target (http_probe, waf_fingerprint, dir_bruteforce,
    subdomain/search lookups) buffered a full response before truncating -
    a hostile or oversized response could grow this process's own heap
    without limit. New capped readers stop at the limit instead of reading
    past it first. The same pattern is fixed on the model-provider side
    (Anthropic/OpenAI-compatible/Ollama embedding clients, the setup wizard's
    model-list fetch).
  • Target-facing User-Agent is now configurable (LANTERN_USER_AGENT),
    self-identifying by default.
  • Cross-process flow-id collision, fixed: flow IDs mixed only a
    millisecond timestamp and a per-process counter that resets on every
    start - two lantern run processes launched in the same millisecond
    produced the same flow ID and shared one row. The OS pid is now mixed in;
    verified against 20 real concurrent processes, 20 distinct IDs.
  • chat TUI: the approval card's default highlight flipped from
    "allow once" to "deny" (matching the module's own "deny-by-inaction"
    doc comment - a reflexive Enter no longer grants active testing);
    str::floor_char_boundary reimplemented locally rather than relying on
    a newer Rust than the declared 1.85 minimum; a Mutex guard held across
    an .await in the steering-queue drain is fixed (clippy
    await_holding_lock).

README

Rewritten twice for structure and to close out every section the roadmap
items touch - "Roles and delegation," "Session lifecycle," "Concurrency,
sessions, and the daemon," and a corrected "Detectability, traces, and the
agent's own attack surface" - plus GETTING_STARTED.md kept in sync with
the current tool and test counts.

Verified

  • 317 tests pass, 0 failed, 1 ignored (the live NVD query) across the
    workspace: lantern-core 58, lantern-llm 33, lantern-tools 109,
    lantern-agent 65, lantern-cli 52.
  • cargo check --workspace --all-targets --release: zero warnings.
  • lantern doctor on the reference device (4-core aarch64, 8.5 GiB RAM):
    reports the device-derived runtime (concurrency 4, child limit 503 MB,
    token budget 6000) and exits in ~91 ms.
  • Built and tested on this device at 2.8 GB / 29 GB free (under its own 20%
    floor) - doctor correctly reports UNDER THE FLOOR, confirming the
    0.1.5 behavior (the floor guards setup, not run/ask/chat) still
    holds.
  • Release binary: 9,464,360 bytes (aarch64).

Upgrade

git pull
cargo build --release          # ~/.cargo/bin/cargo if it is not on PATH
./target/release/lantern doctor

Schema migrates automatically to v3 (the resolved_ips column from 0.1.5's
work and the new queue table) - no manual step, and flows recorded on
earlier versions still render.

Attached: lantern-v0.1.6-aarch64-linux-gnu (9,464,360 bytes), built on
Debian 13 / aarch64, kernel 6.18. For anything else, build from source as
above.