[9.4](backport #7009) fix: enforce policy-based access control on artifact downloads#7162
[9.4](backport #7009) fix: enforce policy-based access control on artifact downloads#7162mergify[bot] wants to merge 1 commit into
Conversation
* 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)
TL;DRThe Buildkite E2E step failed ( Remediation
Investigation detailsRoot CauseI could not conclusively determine a single root cause from the provided Buildkite log file because the failing assertion is not present in the available output. What is verifiable:
Given this PR’s scope, the most likely affected surface is the updated artifact E2E flow:
These paths now depend on eventual consistency (policy artifact manifest visibility + retry-on-403), which is a common source of CI-only flakiness/timeouts when logs are truncated. Evidence
Verification
Follow-up
Note 🔒 Integrity filter blocked 1 itemThe following item were blocked because they don't meet the GitHub integrity level.
To allow these resources, lower tools:
github:
min-integrity: approved # merged | approved | unapproved | noneWhat is this? | From workflow: PR Buildkite Detective Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not. |
|
This pull request has not been merged yet. Could you please review and merge it @ycombinator? 🙏 |
2 similar comments
|
This pull request has not been merged yet. Could you please review and merge it @ycombinator? 🙏 |
|
This pull request has not been merged yet. Could you please review and merge it @ycombinator? 🙏 |
|
@ycombinator do we need this backport? |
|
This pull request has not been merged yet. Could you please review and merge it @ycombinator? 🙏 |
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 returnednil) to enforce policy-based access control:GetPolicy(ctx, policyID)method to thepolicy.Monitorinterface that returns the cached policy for a given ID (reloads from ES on cache miss).authorizeArtifact, fetches the agent's policy via the monitor usingagent.AgentPolicyIDand verifies that the requested artifact (identifier+decoded_sha256) appears in the policy'sinputs[].artifact_manifest.artifacts.ErrUnauthorizedArtifact) if the artifact is not listed in the agent's assigned policy.How to test this PR locally
Design Checklist
Checklist
./changelog/fragmentsusing the changelog toolThis is an automatic backport of pull request fix: enforce policy-based access control on artifact downloads #7009 done by Mergify.