santifer/career-ops · error · Error
jobstreet: URL must use HTTPS
Error message
jobstreet: URL must use HTTPS: ${url} What it means
The jobstreet provider's assertJobstreetUrl() validates every URL used against the SEEK v5 JobSearch API. If the configured `api:` URL (or any derived URL) parses but its protocol is not `https:`, it throws this error. The guard exists to prevent credentials/query params from being sent over plaintext and as part of the SSRF defense on the base URL.
Solutions
- Change the URL scheme in portals.yml `api:` to https:// (e.g. https://id.jobstreet.com/api/jobsearch/v5/search).
- If no `api:` is set, remove it and let the provider use its default https://id.jobstreet.com/api/jobsearch/v5/search.
- Verify the hostname is also in the allowlist (jobstreet.com, jobstreet.co.id, sg/my/id subdomains, hk.jobsdb.com, www.seek.com.au, www.seek.co.nz) so the next check passes.
Example fix
// before (portals.yml) provider: jobstreet api: http://sg.jobstreet.com/api/jobsearch/v5/search // after provider: jobstreet api: https://sg.jobstreet.com/api/jobsearch/v5/search
Defensive patterns
Strategy: validation
Validate before calling
const u = new URL(entry.api);
if (u.protocol !== 'https:') throw new Error(`api must be https: ${entry.api}`); Type guard
const isHttpsUrl = (s) => { try { return new URL(s).protocol === 'https:'; } catch { return false; } }; Try / catch
try {
await provider.fetch(entry, ctx);
} catch (e) {
if (String(e.message).startsWith('jobstreet: URL must use HTTPS')) {
entry.api = entry.api.replace(/^http:/, 'https:');
}
} Prevention
- Always write full https:// URLs in portals.yml api: fields.
- Add a config lint step that rejects http: URLs for provider endpoints.
- Prefer omitting api: and using the provider default, which is already HTTPS.
When it happens
Trigger: A portals.yml entry with `provider: jobstreet` sets `api: http://id.jobstreet.com/api/jobsearch/v5/search` (http instead of https), or code constructs the search endpoint from a base origin captured over plain HTTP.
Common situations: Copy-pasting a URL from an internal proxy or local dev environment; hand-writing the api URL and forgetting the 's'; an http:// link stored in an older portals.yml from a pre-HTTPS template.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- consider: needs an https careers_url on a public host
- himalayas: untrusted hostname
- itviec: untrusted hostname
- itviec: URL must use HTTPS
- jobbankca: invalid URL
AI-assisted analysis of santifer/career-ops@e7abd431fc (2026-09-16).
Data as JSON: /api/errors/5cb62aa1bcde2be3.
Report an issue: GitHub.
Appendix: source
Thrown at providers/jobstreet.mjs:84
// switch either way breaks one market, which is why this is keyed on the host.
const ID_LOCALE_HOSTS = new Set(['id.jobstreet.com', 'www.jobstreet.co.id', 'jobstreet.co.id']);
/** @param {string} origin — scheme + hostname */
function jobDetailPath(origin) {
let host = '';
try { host = new URL(origin).hostname; } catch { /* fall through to the common path */ }
return ID_LOCALE_HOSTS.has(host) ? '/id/job/' : '/job/';
}
/** @param {string} url */
function assertJobstreetUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`jobstreet: invalid URL: ${url}`);
}
if (parsed.protocol !== 'https:') throw new Error(`jobstreet: URL must use HTTPS: ${url}`);
if (!ALLOWED_JOBSTREET_HOSTS.has(parsed.hostname))
throw new Error(`jobstreet: untrusted hostname "${parsed.hostname}" — must be one of: ${[...ALLOWED_JOBSTREET_HOSTS].join(', ')}`);
return url;
}
/**
* Derive the origin from the API hostname.
* e.g. id.jobstreet.com → https://id.jobstreet.com
* @param {string} apiUrl
* @returns {string}
*/
function deriveOrigin(apiUrl) {
try {
const parsed = new URL(apiUrl);
return `${parsed.protocol}//${parsed.hostname}`;
} catch {
return 'https://id.jobstreet.com';
}View on GitHub (pinned to e7abd431fc)