{
  "variant_id": "CVE-2026-85706-variant-files-api-trailing-slash",
  "created_at": "2026-09-12T08:15:00Z",
  "variant_summary": "Alternate trigger for CVE-2026-85706 confirmed on the vulnerable build: the Repository Files API endpoints POST/PUT /api/v4/projects/:id/repository/files/:file_path (lib/api/files.rb) lack authenticate! in GitLab 19.3.1 and call the same CommitsBodyUploaderHelper#file_params_from_body_upload sink as the Repository Commits API. A trailing slash in the URL (.../repository/files/vfile.txt/) defeats gitlab-workhorse's anchored classification regex ^/api/v4/projects/[^/]+/repository/files/[^/]+\\z while Grape still routes the path, yielding the same unauthenticated arbitrary file read with full content echo. The 19.3.2 fix (authenticate! before the sink in commits.rb, files.rb and the authorize helper; ::UploadedFile-only file params) blocks every tested entry point on the fixed build - no bypass.",
  "relation": "newer_version_sibling",
  "origin_kind": "pruva_variant",
  "repository": "https://gitlab.com/gitlab-org/gitlab",
  "submitted_target": {
    "target_kind": "docker_image",
    "version": "19.3.1-ce.0",
    "ref": "gitlab/gitlab-ce:19.3.1-ce.0",
    "display": "gitlab/gitlab-ce:19.3.1-ce.0 (parent CVE target, digest sha256:f63df4c43029fe91db370609c0b40a1e3585cebd06e3e9637d93a9a3030eb86e)"
  },
  "variant_target": {
    "target_kind": "docker_image",
    "commit_sha": "668508315ee5b5a59aa018424f741c27e81bafe1",
    "version": "19.3.1-ce.0",
    "ref": "gitlab/gitlab-ce:19.3.1-ce.0",
    "display": "gitlab/gitlab-ce:19.3.1-ce.0, image digest sha256:f63df4c43029fe91db370609c0b40a1e3585cebd06e3e9637d93a9a3030eb86e, gitlab-rails build revision 668508315ee5b5a59aa018424f741c27e81bafe1 (alternate trigger confirmed here); fixed control gitlab/gitlab-ce:19.3.2-ce.0, digest sha256:05453dd1d9aba27c2c487613141596868409b4d03247647f7d66cb0b36f321b8, gitlab-rails 34042bf7d00ca54c5e04079df6cdc6151485fd46 (no bypass)"
  },
  "same_root_cause_confidence": "high",
  "same_surface_confidence": "high",
  "claimed_surface": "api_remote",
  "validated_surface": "api_remote",
  "required_entrypoint_kind": "endpoint",
  "required_entrypoint_detail": "Unauthenticated POST (or PUT) http://target/api/v4/projects/<id>/repository/files/<any-single-segment>/ with trailing slash, through the real omnibus HTTP boundary (nginx -> gitlab-workhorse -> puma/Rails)",
  "attacker_controlled_input": "URL trailing slash (defeats workhorse classification) plus flat request parameters file, file.size, Content-Type=application/x-www-form-urlencoded, and file.path=<arbitrary filesystem path>; empty body; no credentials",
  "trigger_path": "nginx -> gitlab-workhorse (regex ^/api/v4/projects/[^/]+/repository/files/[^/]+\\z fails on trailing slash, raw proxy with signed Gitlab-Workhorse header) -> Rails/Grape routes .../files/vfile.txt/ -> API::Files post/put ':id/repository/files/:file_path' (19.3.1: require_gitlab_workhorse! only, no authenticate!) -> file_params_from_body_upload -> File.exist?/File.read(params['file.path']) -> Rack::Utils.parse_nested_query(file content) -> InvalidParameterError message embeds file content in 400 response",
  "observed_impact_class": "info_leak",
  "exploitability_confidence": "high",
  "evidence_scope": "production_path",
  "runtime_manifest_present": true,
  "end_to_end_target_reached": true,
  "inferred": false,
  "file_path": "lib/api/files.rb",
  "line_start": 362,
  "line_end": 421,
  "secondary_anchors": [
    {
      "file_path": "lib/api/helpers/commits_body_uploader_helper.rb",
      "line_start": 13,
      "line_end": 50
    },
    {
      "file_path": "lib/api/commits.rb",
      "line_start": 331,
      "line_end": 360
    }
  ],
  "review_scope_paths": [
    "lib/api/files.rb",
    "lib/api/commits.rb",
    "lib/api/helpers/commits_body_uploader_helper.rb",
    "lib/api/markdown_uploads.rb",
    "lib/api/wikis.rb",
    "lib/api/alert_management_alerts.rb",
    "lib/api/ci/runner.rb",
    "lib/api/project_import.rb",
    "lib/api/group_import.rb",
    "lib/api/terraform/state.rb",
    "lib/api/helpers/packages_helpers.rb",
    "lib/api/group_placeholder_reassignments.rb",
    "lib/api/geo.rb",
    "lib/gitlab/middleware/multipart.rb",
    "lib/uploaded_file.rb"
  ],
  "artifact_refs": {
    "variant_manifest": "bundle/vuln_variant/variant_manifest.json",
    "validation_verdict": "bundle/vuln_variant/validation_verdict.json",
    "runtime_manifest": "bundle/vuln_variant/runtime_manifest.json",
    "repro_log": "bundle/logs/vuln_variant/reproduction_steps.log",
    "root_cause_equivalence": "bundle/vuln_variant/root_cause_equivalence.json",
    "reproducer": [
      "bundle/vuln_variant/reproduction_steps.sh"
    ]
  }
}
