santifer/career-ops · error
comeet: URL must use HTTPS
Error message
comeet: URL must use HTTPS: ${redactToken(url)} What it means
assertComeetUrl enforces HTTPS because the Comeet careers-api carries a per-tenant token in the query string and the scanner refuses to send credentials over plaintext. Any URL whose parsed protocol is not 'https:' (http:, ftp:, etc.) is rejected with this error, token redacted in the message.
Solutions
- Change the scheme to https:// in the entry's api/careers_url
- Verify Comeet's endpoint is served over HTTPS (it is: www.comeet.co) — there is no legitimate http variant
- If testing locally, use an https-capable mock or extend the provider's host allowlist consciously rather than downgrading the scheme
- Grep portals.yml for 'http://' to catch all downgraded entries at once
Example fix
// before api: http://www.comeet.co/careers-api/2.0/company/acme/positions?token=abc // after api: https://www.comeet.co/careers-api/2.0/company/acme/positions?token=abc
Defensive patterns
Strategy: validation
Validate before calling
function isHttpsUrl(raw) {
try { return new URL(raw).protocol === 'https:'; } catch { return false; }
}
if (!isHttpsUrl(entry.api)) throw new Error(`entry ${entry.name}: comeet api must be https`); Type guard
function isHttpsUrlString(raw) {
if (typeof raw !== 'string') return false;
try { return new URL(raw).protocol === 'https:'; } catch { return false; }
} Try / catch
try {
assertComeetUrl(entry.api);
} catch (err) {
if (String(err.message).includes('must use HTTPS')) {
logger.error({entry: entry.name}, 'downgrade the scheme to https:// — comeet tokens must not travel over http');
} else throw err;
} Prevention
- Treat HTTPS as non-negotiable for any URL carrying a ?token= credential
- Grep config for /^http:\/\// when onboarding entries
- Never point provider entries at local http mocks in shared config — use a test fixture instead
- Add a CI lint that rejects non-https api:/careers_url: values
When it happens
Trigger: fetch() resolves an entry whose api or careers_url is a valid URL string with an explicit http: (or other non-https) scheme — isComeetApiUrl already rejects those, so this surfaces when the guard is bypassed, the entry is mutated between detect and fetch, or assertComeetUrl is invoked directly on http input.
Common situations: Copying the API URL from an old doc that used http://; writing the URL into portals.yml without the s; a config transform downgrading the scheme; testing against a local http mock by pointing the entry at it.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- breezy: URL must use HTTPS
- builtin: URL must use HTTPS
- careerviet: URL must use HTTPS
- gem: URL must use HTTPS
- arbeitnow: URL must use HTTPS
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/69aedb9b0ea042a9.
Report an issue: GitHub.
Appendix: source
Thrown at providers/comeet.mjs:36
if (typeof raw !== 'string' || !raw) return false;
let parsed;
try {
parsed = new URL(raw);
} catch {
return false;
}
return parsed.protocol === 'https:' && parsed.hostname === COMEET_API_HOST && parsed.pathname.startsWith('/careers-api/');
}
/** @param {string} url */
function assertComeetUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`comeet: invalid URL: ${redactToken(url)}`);
}
if (parsed.protocol !== 'https:') throw new Error(`comeet: URL must use HTTPS: ${redactToken(url)}`);
if (parsed.hostname !== COMEET_API_HOST)
throw new Error(`comeet: untrusted hostname "${parsed.hostname}" — must be ${COMEET_API_HOST}`);
if (!parsed.pathname.startsWith('/careers-api/'))
throw new Error(`comeet: URL path must be the careers-api endpoint: ${redactToken(url)}`);
return url;
}
// Redact the per-tenant ?token= so neither the (informational, possibly-logged)
// DetectHit url nor a thrown validation error carries the secret. Best-effort:
// falls back to a regex strip when the value can't be parsed as a URL.
function redactToken(url) {
try {
const parsed = new URL(url);
if (parsed.searchParams.has('token')) parsed.searchParams.set('token', 'REDACTED');
return parsed.href;
} catch {
return typeof url === 'string' ? url.replace(/([?&]token=)[^&#]*/gi, '$1REDACTED') : url;
}View on GitHub (pinned to aac998c7ed)