Skip to content

Commit d6e7db8

Browse files
authored
Merge pull request #20924 from davelopez/explore_url_fetch_with_headers
Add Support for HTTP Headers in URL Fetch Requests with Secure Storage for Landing Requests
2 parents 3028bb6 + a12a082 commit d6e7db8

19 files changed

Lines changed: 2108 additions & 6 deletions

client/src/api/schema/schema.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23533,6 +23533,13 @@ export interface components {
2353323533
extra_files?: components["schemas"]["ExtraFiles"] | null;
2353423534
/** Hashes */
2353523535
hashes?: components["schemas"]["FetchDatasetHash"][] | null;
23536+
/**
23537+
* Headers
23538+
* @description Optional headers to include in the URL fetch request
23539+
*/
23540+
headers?: {
23541+
[key: string]: string;
23542+
} | null;
2353623543
/**
2353723544
* Info
2353823545
* @description Free text field that can be used to store arbitrary information about the dataset. This used to be prominently

config/url_headers_conf.yml.sample

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../lib/galaxy/config/sample/url_headers_conf.yml.sample
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
# Enabling HTTP Headers in Fetch Requests
2+
3+
Galaxy allows users to **fetch remote data by URL** (for example via _Upload → Paste/Fetch data_ or via APIs that retrieve external resources).
4+
By default, Galaxy **does not forward any custom HTTP headers** when fetching URLs. This restriction is intentional and is part of Galaxy’s security model.
5+
6+
Starting with recent Galaxy releases, administrators can **explicitly allow a controlled set of HTTP headers** to be sent with fetch requests, based on the target URL. This enables integrations with authenticated services (e.g. APIs requiring `Authorization` headers) while maintaining strict security boundaries.
7+
8+
This document explains **how to safely enable HTTP headers for fetch requests**, how the allow‑list mechanism works, and how to configure it.
9+
10+
## Why Header Allow‑Listing Is Required
11+
12+
Allowing arbitrary headers in server‑side HTTP requests is dangerous. Without restrictions, users could:
13+
14+
- Access internal services (SSRF attacks)
15+
- Exfiltrate credentials via forwarded headers
16+
- Abuse Galaxy as a proxy to privileged networks
17+
18+
To prevent this, Galaxy implements **explicit header allow‑listing with URL pattern matching**:
19+
20+
- **No headers are allowed by default**
21+
- Each allowed header must be explicitly configured
22+
- Headers are only sent to URLs that match defined patterns
23+
- Sensitive headers can be stored securely using Galaxy’s Vault
24+
25+
## Configuration Overview
26+
27+
Header forwarding for fetch requests is controlled via a dedicated configuration file:
28+
29+
```yaml
30+
galaxy:
31+
url_headers_config_file: url_headers_conf.yml
32+
```
33+
34+
This file defines:
35+
36+
- Which **HTTP headers** are allowed
37+
- For which **URL patterns** they may be sent
38+
- Whether headers are **sensitive** (stored encrypted in the Vault)
39+
40+
If this configuration file is **not set or empty**, **no headers will ever be forwarded**.
41+
42+
## url_headers_conf.yml Format
43+
44+
The configuration file is a YAML list of rules. Each rule applies to one or more URL patterns.
45+
46+
### Basic Structure
47+
48+
```yaml
49+
- url_pattern: "https://api.example.org/.*"
50+
headers:
51+
- name: Authorization
52+
sensitive: true
53+
- name: X-API-Key
54+
sensitive: true
55+
```
56+
57+
### Fields
58+
59+
| Field | Description |
60+
| --------------------- | -------------------------------------------------------- |
61+
| `url_pattern` | A regular expression matched against the full URL |
62+
| `headers` | List of allowed HTTP headers for matching URLs |
63+
| `headers[].name` | Exact HTTP header name (case‑insensitive) |
64+
| `headers[].sensitive` | Whether the header value is stored securely in the Vault |
65+
66+
## Sensitive vs Non‑Sensitive Headers
67+
68+
### Sensitive Headers
69+
70+
Sensitive headers (for example `Authorization`, `X-API-Key`, `Cookie`) are:
71+
72+
- **Encrypted and stored in the Galaxy Vault**
73+
- Never logged or exposed in plaintext
74+
- Managed through Galaxy’s secure secrets infrastructure
75+
76+
Example:
77+
78+
```yaml
79+
- url_pattern: "https://protected.example.com/.*"
80+
headers:
81+
- name: Authorization
82+
sensitive: true
83+
```
84+
85+
### Non‑Sensitive Headers
86+
87+
Non‑sensitive headers may be stored in plain configuration and are typically used for:
88+
89+
- Feature flags
90+
- API versioning
91+
- Public metadata headers
92+
93+
Example:
94+
95+
```yaml
96+
- url_pattern: "https://public.example.com/.*"
97+
headers:
98+
- name: X-Client-Version
99+
sensitive: false
100+
```
101+
102+
## Multiple Rules and URL Matching
103+
104+
Multiple rules may be defined. The first rule whose `url_pattern` matches the request URL is applied.
105+
106+
```yaml
107+
- url_pattern: "https://api.github.com/.*"
108+
headers:
109+
- name: Authorization
110+
sensitive: true
111+
112+
- url_pattern: "https://raw.githubusercontent.com/.*"
113+
headers:
114+
- name: X-Client-Version
115+
sensitive: false
116+
```
117+
118+
```{note}
119+
Rules are evaluated in order. Be careful with overly broad patterns such as `.*`.
120+
```
121+
122+
## Using Headers in Practice
123+
124+
Once configured, users (or tools) may provide header values when performing fetch operations. Galaxy will:
125+
126+
1. Validate the target URL against the allow‑list
127+
2. Filter headers to the allowed set
128+
3. Securely inject sensitive headers at request time
129+
130+
Headers not explicitly allowed **will be silently dropped**.
131+
132+
## Security Best Practices
133+
134+
```{warning}
135+
Only allow headers and URL patterns that are strictly necessary.
136+
```
137+
138+
Recommended practices:
139+
140+
- Prefer **narrow URL patterns** over wildcards
141+
- Mark authentication headers as `sensitive: true`
142+
- Avoid allowing `Cookie` headers unless absolutely required
143+
- Never allow headers for internal or private network ranges
144+
145+
## Troubleshooting
146+
147+
If headers are not being forwarded as expected:
148+
149+
1. Verify `url_headers_config_file` is configured in `galaxy.yml`
150+
2. Confirm the URL matches the configured `url_pattern`
151+
3. Check that the header name matches exactly
152+
4. Ensure Galaxy has access to the configured Vault

doc/source/admin/galaxy_options.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5638,6 +5638,26 @@
56385638
:Type: str
56395639

56405640

5641+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
5642+
``url_headers_config_file``
5643+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
5644+
5645+
:Description:
5646+
Configuration file for URL request headers allow-list with URL
5647+
pattern matching. This file defines which HTTP headers are allowed
5648+
in URL fetch requests based on URL patterns, and whether they
5649+
should be treated as sensitive (encrypted in the vault) or not. If
5650+
no allow-list is specified, no headers will be allowed in URL
5651+
requests. This provides fine-grained security control over what
5652+
headers can be sent when Galaxy fetches external URLs on behalf of
5653+
users, allowing different headers for different target domains or
5654+
services.
5655+
The value of this option will be resolved with respect to
5656+
<config_dir>.
5657+
:Default: ``url_headers_conf.yml``
5658+
:Type: str
5659+
5660+
56415661
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
56425662
``display_builtin_converters``
56435663
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

doc/source/admin/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Galaxy Deployment & Administration
1818
jobs
1919
job_metrics
2020
authentication
21+
enable_headers_in_fetch_requests
2122
tool_panel
2223
data_tables
2324
mq

lib/galaxy/app_unittest_utils/galaxy_mock.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ def __init__(self, **kwargs):
291291
self.monitor_thread_join_timeout = 1
292292
self.integrated_tool_panel_config = None
293293
self.vault_config_file = kwargs.get("vault_config_file")
294+
self.url_headers_config_file = None
294295
self.max_discovered_files = 10000
295296
self.display_builtin_converters = True
296297
self.enable_notification_system = True

lib/galaxy/config/sample/galaxy.yml.sample

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3048,6 +3048,18 @@ galaxy:
30483048
# <config_dir>.
30493049
#vault_config_file: vault_conf.yml
30503050

3051+
# Configuration file for URL request headers allow-list with URL
3052+
# pattern matching. This file defines which HTTP headers are allowed
3053+
# in URL fetch requests based on URL patterns, and whether they should
3054+
# be treated as sensitive (encrypted in the vault) or not. If no
3055+
# allow-list is specified, no headers will be allowed in URL requests.
3056+
# This provides fine-grained security control over what headers can be
3057+
# sent when Galaxy fetches external URLs on behalf of users, allowing
3058+
# different headers for different target domains or services.
3059+
# The value of this option will be resolved with respect to
3060+
# <config_dir>.
3061+
#url_headers_config_file: url_headers_conf.yml
3062+
30513063
# Display built-in converters in the tool panel.
30523064
#display_builtin_converters: true
30533065

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# Allowed URL Headers Configuration
2+
#
3+
# This file defines which HTTP headers are allowed in URL fetch requests based
4+
# on URL patterns, and whether they should be treated as sensitive (encrypted
5+
# in the vault) or not.
6+
#
7+
# If no allow-list is specified or this file is empty/missing, NO headers will
8+
# be allowed in URL requests.
9+
#
10+
# Configuration structure:
11+
# patterns:
12+
# - url_pattern: A regular expression pattern to match URLs
13+
# headers:
14+
# - name: The exact header name (case-insensitive)
15+
# sensitive: Whether this header contains sensitive information that should
16+
# be encrypted when stored in the database (requires vault configuration)
17+
#
18+
# IMPORTANT:
19+
# ------------------------------------
20+
# When a URL matches MULTIPLE patterns, the union of all allowed headers is used.
21+
# This means you can compose permissions from multiple patterns for flexibility.
22+
#
23+
# Example: A URL matching both pattern A (allows headers X, Y) and pattern B
24+
# (allows headers Y, Z) will allow headers X, Y, and Z.
25+
#
26+
# Security: If ANY matching pattern marks a header as sensitive, it will be
27+
# treated as sensitive (secure-by-default).
28+
#
29+
# The following examples are for illustration purposes only; please use only the minimum configuration for your needs.
30+
# Examples:
31+
32+
patterns:
33+
# GitHub API access - allow authentication headers for GitHub URLs
34+
- url_pattern: "^https://api\\.github\\.com/.*"
35+
headers:
36+
- name: Authorization
37+
sensitive: true
38+
- name: Accept
39+
sensitive: false
40+
- name: X-GitHub-Api-Version
41+
sensitive: false
42+
43+
# Generic GitHub content (raw files, releases) - no auth needed
44+
- url_pattern: "^https://(raw\\.githubusercontent\\.com|github\\.com/.*/releases/download)/.*"
45+
headers:
46+
- name: Accept
47+
sensitive: false
48+
- name: Accept-Encoding
49+
sensitive: false
50+
51+
# AWS S3 buckets - allow AWS authentication headers
52+
- url_pattern: "^https://.*\\.s3\\..+\\.amazonaws\\.com/.*"
53+
headers:
54+
- name: Authorization
55+
sensitive: true
56+
- name: X-Amz-Date
57+
sensitive: false
58+
- name: X-Amz-Content-Sha256
59+
sensitive: false
60+
- name: X-Amz-Security-Token
61+
sensitive: true
62+
63+
# Generic cloud storage APIs
64+
- url_pattern: "^https://.*\\.(googleapis\\.com|azure\\.com|digitaloceanspaces\\.com)/.*"
65+
headers:
66+
- name: Authorization
67+
sensitive: true
68+
- name: X-API-Key
69+
sensitive: true
70+
- name: Accept
71+
sensitive: false
72+
73+
# FTP over HTTP services
74+
- url_pattern: "^https?://ftp\\..*/.*"
75+
headers:
76+
- name: Authorization
77+
sensitive: true
78+
- name: Accept
79+
sensitive: false
80+
81+
# Academic/research data repositories
82+
- url_pattern: "^https://.*(zenodo\\.org|figshare\\.com|dryad\\.org|dataverse\\.org)/.*"
83+
headers:
84+
- name: Authorization
85+
sensitive: true
86+
- name: X-API-Key
87+
sensitive: true
88+
- name: Accept
89+
sensitive: false
90+
91+
# HTTPS URLs - basic headers only (most restrictive for unknown sources)
92+
- url_pattern: "^https://.*"
93+
headers:
94+
- name: Authorization
95+
sensitive: true
96+
- name: X-Auth-Token
97+
sensitive: true
98+
- name: X-API-Key
99+
sensitive: true
100+
- name: Accept
101+
sensitive: false
102+
- name: Accept-Language
103+
sensitive: false
104+
- name: Accept-Encoding
105+
sensitive: false
106+
- name: Cache-Control
107+
sensitive: false
108+
109+
# Security notes:
110+
# - All matching patterns contribute their allowed headers (union of permissions)
111+
# - If ANY pattern marks a header as sensitive, it's treated as sensitive
112+
# - Only add headers that are absolutely necessary for your use case
113+
# - When in doubt, mark headers as sensitive to ensure encryption
114+
# - Patterns are order-independent, making configuration more composable
115+
# - HTTP (non-HTTPS) URLs are generally not recommended and may be blocked

lib/galaxy/config/schemas/config_schema.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4172,6 +4172,20 @@ mapping:
41724172
desc: |
41734173
Vault config file.
41744174
4175+
url_headers_config_file:
4176+
type: str
4177+
default: url_headers_conf.yml
4178+
path_resolves_to: config_dir
4179+
required: false
4180+
desc: |
4181+
Configuration file for URL request headers allow-list with URL pattern matching.
4182+
This file defines which HTTP headers are allowed in URL fetch requests based
4183+
on URL patterns, and whether they should be treated as sensitive (encrypted
4184+
in the vault) or not. If no allow-list is specified, no headers will be
4185+
allowed in URL requests. This provides fine-grained security control over
4186+
what headers can be sent when Galaxy fetches external URLs on behalf of users,
4187+
allowing different headers for different target domains or services.
4188+
41754189
display_builtin_converters:
41764190
type: bool
41774191
default: true

0 commit comments

Comments
 (0)