Skip to content

[9.3](backport #7009) fix: enforce policy-based access control on artifact downloads#7163

Open
mergify[bot] wants to merge 1 commit into
9.3from
mergify/bp/9.3/pr-7009
Open

[9.3](backport #7009) fix: enforce policy-based access control on artifact downloads#7163
mergify[bot] wants to merge 1 commit into
9.3from
mergify/bp/9.3/pr-7009

Conversation

@mergify

@mergify mergify Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

What is the problem this PR solves?

The artifact download endpoint (/api/fleet/artifacts/{id}/{sha256}) only validates the agent's API key but never checks whether the requested artifact belongs to the agent's assigned policy. This means an agent enrolled under one policy can download artifacts belonging to a different policy if it knows the artifact ID and SHA256 hash. For example, an agent enrolled under a policy with no integrations can retrieve Elastic Defend trust lists, exception lists, and other security artifacts from another policy.

How does this PR solve the problem?

Implements the authorizeArtifact() function (previously a no-op that returned nil) to enforce policy-based access control:

  1. Adds a GetPolicy(ctx, policyID) method to the policy.Monitor interface that returns the cached policy for a given ID (reloads from ES on cache miss).
  2. In authorizeArtifact, fetches the agent's policy via the monitor using agent.AgentPolicyID and verifies that the requested artifact (identifier + decoded_sha256) appears in the policy's inputs[].artifact_manifest.artifacts.
  3. Returns 403 Forbidden (ErrUnauthorizedArtifact) if the artifact is not listed in the agent's assigned policy.

How to test this PR locally

  1. Set up Fleet Server with Elasticsearch and Kibana
  2. Create two agent policies: Victim-Policy with Elastic Defend integration (add a trusted application), and Attacker-Policy with no integrations
  3. Create an enrollment token for Attacker-Policy and enroll an agent
  4. Attempt to download an artifact belonging to Victim-Policy using the attacker agent's API key — should now receive 403 Forbidden instead of the artifact contents
  5. Verify that an agent enrolled under Victim-Policy can still download its own artifacts normally (200 OK)

Design Checklist

  • I have ensured my design is stateless and will work when multiple fleet-server instances are behind a load balancer.
  • I have or intend to scale test my changes, ensuring it will work reliably with 100K+ agents connected.
  • I have included fail safe mechanisms to limit the load on fleet-server: rate limiting, circuit breakers, caching, load shedding, etc.

Checklist

* fix: enforce policy-based access control on artifact downloads

The artifact download endpoint (/api/fleet/artifacts/{id}/{sha256})
previously only validated the agent's API key but never checked whether
the requested artifact belonged to the agent's assigned policy. This
allowed an agent enrolled under one policy to download artifacts from
a different policy if it knew the artifact ID and SHA256 hash.

Add authorizeArtifact implementation that fetches the agent's policy
from the in-memory policy monitor cache and verifies the requested
artifact appears in the policy's artifact_manifest before serving it.
Returns 403 Forbidden if the artifact is not in the agent's policy.

Resolves: https://github.com/elastic/security/issues/8396

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

* chore: add changelog fragment for artifact access control fix

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

* docs: document race condition tradeoffs in authorizeArtifact

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

* fix: use any instead of interface{} per Go conventions

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

* refactor: add typed ArtifactManifest struct for policy input parsing

Defines model.ArtifactManifest and model.ManifestEntry structs so
policyHasArtifact no longer navigates untyped map[string]any chains.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit caa8b2d)
@mergify mergify Bot requested a review from a team as a code owner June 5, 2026 07:24
@mergify mergify Bot added the backport label Jun 5, 2026
@mergify mergify Bot requested review from blakerouse and michel-laterman June 5, 2026 07:24
@github-actions github-actions Bot added bug Something isn't working Team:Elastic-Agent-Control-Plane Label for the Agent Control Plane team labels Jun 5, 2026
@mergify

mergify Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

This pull request has not been merged yet. Could you please review and merge it @ycombinator? 🙏

1 similar comment
@mergify

mergify Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

This pull request has not been merged yet. Could you please review and merge it @ycombinator? 🙏

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

Labels

backport bug Something isn't working Team:Elastic-Agent-Control-Plane Label for the Agent Control Plane team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant