Skip to content

DISABLE_COLLECTIONS ignored when DISABLE_AGENT=true — LAPI-only container keeps unremovable default collections #4563

Description

@aversag

What happened?

In a LAPI-only container (DISABLE_AGENT=true, no agent, no acquisition — CrowdSec used purely as a decision store fed by CAPI, with a remote bouncer enforcing decisions), the default collections baked into the image (crowdsecurity/linux and its dependencies: sshd, whitelist-good-actors, plus the related parsers/scenarios/contexts/postoverflows) are present in /etc/crowdsec and show up in cscli collections list.

Setting DISABLE_COLLECTIONS=crowdsecurity/linux — the documented way to drop default collections — has no effect, because the removal runs inside prepare_hub(), which returns early when the agent is disabled (build/docker/docker_start.sh):

prepare_hub() {
    if istrue "$DISABLE_AGENT"; then
        return
    fi
    ...
    ## Remove collections, parsers, scenarios & postoverflows
    if [ "$DISABLE_COLLECTIONS" != "" ]; then
        cscli_if_clean collections remove "$DISABLE_COLLECTIONS" --force
    fi
    ...
}

However, the collections arrive independently of the agent, via the staging populate step, which is not gated on DISABLE_AGENT:

if [ ! -e "/etc/crowdsec/local_api_credentials.yaml" ] && [ ! -e "/etc/crowdsec/config.yaml" ]; then
    ...
    rsync -av --ignore-existing /staging/etc/crowdsec/* /etc/crowdsec
fi

So the copy is unconditional but the removal knob is agent-gated → in a LAPI-only container there is no declarative way to remove the baked-in collections. On an emptyDir config this repeats on every boot.

What did you expect to happen?

One of:

  • DISABLE_COLLECTIONS (and DISABLE_PARSERS / DISABLE_SCENARIOS / …) still honored when DISABLE_AGENT=true, so a LAPI-only deployment can clean up hub items it doesn't use; or
  • the staging populate of hub items skipped when the agent is disabled (a pure LAPI has no use for scenarios/parsers); or
  • at minimum, this behavior documented.

Visible symptom: cscli collections list on a LAPI-only engine advertises SSH scenarios that can never fire (no acquisition). It's misleading during audits and feeds "Security Engine: no activity" confusion in the Console.

How can we reproduce it (as minimally and precisely as possible)?

docker run -d --name cs-lapi \
  -e DISABLE_AGENT=true \
  -e DISABLE_COLLECTIONS="crowdsecurity/linux" \
  crowdsecurity/crowdsec:v1.7.7

docker exec cs-lapi cscli collections list
# crowdsecurity/linux, crowdsecurity/sshd, crowdsecurity/whitelist-good-actors
# are still installed despite DISABLE_COLLECTIONS

Same on Kubernetes via the official helm chart with agent.enabled=false (LAPI-only).

Anything else we need to know?

Current workarounds are all post-copy — e.g. a lifecycle.postStart hook running cscli collections remove crowdsecurity/linux --force (which cascades all deps cleanly, confirmed via --dry-run). With an emptyDir config this has to re-run every boot. An agent-independent DISABLE_*, or skipping the hub-item staging when the agent is off, would remove the need for that.

Related but distinct (both agent-side): #1910 (COLLECTIONS not authoritative), #1331 (install/remove ordering). This one is specifically the DISABLE_AGENT / LAPI-only path.

Crowdsec version

crowdsec/v1.7.7-981e6166-docker

OS version

alpine (docker) - 3.21.6

Enabled collections and parsers

crowdsecurity/linux, crowdsecurity/sshd, crowdsecurity/whitelist-good-actors
(all baked-in image defaults; no acquisition configured)

Acquisition config

none — LAPI-only (DISABLE_AGENT=true)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions