santifer/career-ops · error · Error

remotli: untrusted hostname

Error message

remotli: untrusted hostname "${parsed.hostname}" — must be remotli.ch

What it means

remotli provider pins all requests to the remotli.ch host. assertRemotliUrl parses the URL and rejects any hostname not matching HOST_RE with this error. This prevents SSRF and misdirected requests by ensuring every request goes only to the trusted board host.

Solutions

  1. Use a URL whose hostname is exactly remotli.ch (check for typos like remotli.com or subdomain changes).
  2. If you must route through a proxy, proxy at the network level — do not change the URL hostname.
  3. Inspect the provider entry/portals.yml value that supplied the URL and correct it.

Example fix

// before
url = 'https://mirror.example.com/remotli/jobs';
// after
url = 'https://remotli.ch/api/jobs';
Defensive patterns

Strategy: validation

Validate before calling

function isTrustedHost(url) { try { return new URL(url).hostname === 'remotli.ch'; } catch { return false; } }
if (!isTrustedHost(entry.url)) throw new Error(`skip: untrusted host in ${entry.url}`);

Type guard

const isRemotliUrl = (u) => { try { return new URL(u).hostname === 'remotli.ch'; } catch { return false; } };

Try / catch

try { await provider.fetch(entry, ctx); } catch (e) { if (e.message.includes('untrusted hostname')) { console.error(`Entry ${entry.name} points at a non-remotli.ch host`); return null; } throw e; }

Prevention

When it happens

Trigger: Calling the remotli provider with a URL whose parsed hostname fails HOST_RE — e.g. https://api.example.com/jobs, a typo'd domain (remotli.com), a localhost/mirror host, or an attacker-controlled URL passed through an entry's config.

Common situations: Config pointing at a proxy or local mirror, a renamed/moved board endpoint, copy-pasted URLs from another provider, or a config-injection attempt supplying a foreign hostname.

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


AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16). Data as JSON: /api/errors/d1ff1deddf8eef1e. Report an issue: GitHub.

Appendix: source

Thrown at providers/remotli.mjs:243

  if (postedAt !== undefined) out.postedAt = postedAt;

  const salary = resolveSalary(job);
  if (salary) out.salary = salary;

  return out;
}

/** Guard the API URL: HTTPS + remotli.ch only. */
function assertRemotliUrl(url) {
  let parsed;
  try {
    parsed = new URL(url);
  } catch {
    throw new Error(`remotli: invalid URL: ${url}`);
  }
  if (parsed.protocol !== 'https:') throw new Error(`remotli: URL must use HTTPS: ${url}`);
  if (!HOST_RE.test(parsed.hostname))
    throw new Error(`remotli: untrusted hostname "${parsed.hostname}" — must be remotli.ch`);
  return url;
}

/** @type {Provider} */
export default {
  id: 'remotli',

  detect(entry) {
    const raw = typeof entry.careers_url === 'string' ? entry.careers_url : '';
    if (!raw) return null;
    let parsed;
    try {
      parsed = new URL(raw);
    } catch {
      return null;
    }
    if (parsed.protocol !== 'https:') return null;
    if (!HOST_RE.test(parsed.hostname)) return null;

View on GitHub (pinned to aac998c7ed)