|
Task Description
In-scope asset: https://api.alwaysdata.com — scheduled jobs (POST /v1/job/, type TYPE_URLS) Qualifying category: Server-Side Request Forgery (SSRF) Self-assessed severity: Medium (deferring to your worst-case analysis) Date of discovery: 2026-06-04 (reported within 24h)
## Compliance note (per your SSRF guidance)
Your rules state: "SSRF — Do not go playing around on any internal networks. Report as soon as you believe that you have a potential SSRF issue." I am following that guidance: I confirmed the server-side request primitive against my own external host, observed that the API accepts internal/link-local target URLs at validation time (no execution required to observe this), and then stopped. I did not explore, enumerate, or pivot into any internal network, accessed no data, and used only two test accounts I registered myself. All test artifacts were deleted afterwards.
## Summary
An authenticated customer can create a TYPE_URLS scheduled task via POST /v1/job/. When it runs, the alwaysdata job-runner performs a server-side HTTP(S) request to the customer-supplied URL:
curl --fail --silent --location --max-redirs 5 '<URL>' > /dev/null
Two issues: 1. No egress filtering — the API accepts URLs targeting loopback (127.0.0.1) and link-local / metadata (169.254.169.254) ranges at validation time (HTTP 201), instead of rejecting them. 2. Redirects are followed (–location –max-redirs 5), so an allowed public URL can redirect the server-side request toward an internal destination.
The runner executes on shared infrastructure separate from the customer's own sandbox. Response bodies are discarded (> /dev/null), so this is a blind SSRF. I am reporting the primitive per your guidance rather than demonstrating internal impact.
## Steps to reproduce (standard Linux tools; own test accounts)
1) Confirm server-side fetch (against my own external host only):
curl -s --basic --user "$APIKEY account=$ACCOUNT:" \
-X POST -H 'Content-Type: application/json' \
-d '{"type":"TYPE_URLS","argument":"https://$YOUR_HOST/probe","date_type":"FREQUENCY","frequency":1,"frequency_period":"minute"}' \
https://api.alwaysdata.com/v1/job/
Within ~1 minute my external host received an inbound GET from alwaysdata infrastructure, User-Agent: curl/7.88.1. This confirms the request is performed server-side by alwaysdata, not from my browser.
2) Show that internal/link-local targets are NOT rejected at validation (no execution needed):
curl -s -o /dev/null -w '%{http_code}\n' --basic --user "$APIKEY account=$ACCOUNT:" \
-X POST -H 'Content-Type: application/json' \
-d '{"type":"TYPE_URLS","argument":"http://169.254.169.254/","date_type":"DAILY","daily_time":"23:59"}' \
https://api.alwaysdata.com/v1/job/
⇒ 201 Created. Same for http://127.0.0.1/. Only URL syntax is validated (//host and file:// are rejected as malformed), but the destination address range is not checked.
The execution command (curl –fail –silent –location –max-redirs 5 '<URL>' > /dev/null) is visible in the account's own job log at ~/admin/logs/jobs/<id>-<date>.log, which also records the curl exit code. I observed this for my own jobs only; I did not use it to probe internal services.
## Impact
An authenticated user can cause alwaysdata infrastructure to issue server-side HTTP(S) requests to arbitrary destinations, including internal/loopback/link-local ranges that the API does not filter, with redirects followed. This is a classic SSRF primitive originating from shared infrastructure.
Stated limitations (no overclaim): the SSRF is blind (response body discarded); I did not retrieve any response content, did not access any data, and did not explore internal networks. No metadata credential access is claimed. Per your policy, I leave the worst-case severity assessment to your analysts.
## Security recommendation
- Reject loopback, private (RFC1918), link-local (169.254.0.0/16) and metadata address ranges before executing TYPE_URLS jobs. - Re-validate the destination after DNS resolution and after each redirect, not only the initial URL (or disable redirects / restrict to public ranges). - Apply egress filtering at the job-runner network layer so user-controlled fetches cannot reach internal or restricted destinations.
## Scope / safety statement
- Two test accounts I registered myself; no other users involved. - Server-side fetch confirmed against my own external host only. - Internal/link-local URLs were only shown to pass API validation; I did not explore internal networks, accessed no data, and did not pivot. - No automated scanners. Minimal manual requests. All test jobs and resources deleted after testing.
## Duplicate check (performed against the live public tracker)
No existing report covers the TYPE_URLS scheduled-job feature on /v1/job/ or its absent egress filtering. The nearest SSRF/job reports are different: - FS#307 — SSRF in webmail.alwaysdata.com (third-party Roundcube). Different component. - FS#327 — claimed email bounce webhook SSRF. Different (and that feature does not exist). - FS#320 — claimed cron timing oracle on a non-existent /api/v1/cron/ endpoint. Different class.
This report concerns the concrete POST /v1/job/ TYPE_URLS behavior, with observed server-side curl execution and out-of-band confirmation — empirically verified, not speculative.
|