santifer/career-ops · error
bamboohr: URL must use HTTPS
Error message
bamboohr: URL must use HTTPS: ${url} What it means
assertBambooHRUrl rejects any parsed URL whose protocol is not https. BambooHR endpoints carry board/tenant data, so the provider enforces HTTPS to prevent plaintext transport and scheme-downgrade tricks.
Solutions
- Switch the URL to `https://` — all real BambooHR tenants serve HTTPS.
- Remove leftover localhost/http test URLs from portals.yml before running scans.
- Normalize scheme at config load: upgrade `http://` to `https://` for known-good hosts only.
- Check for concatenation bugs that dropped the 's' (e.g. building from a scheme constant).
Example fix
// before
assertBambooHRUrl('http://mycompany.bamboohr.com/careers/list'); // throws
// after
assertBambooHRUrl('https://mycompany.bamboohr.com/careers/list'); // ok Defensive patterns
Strategy: validation
Validate before calling
function isHttpsBambooUrl(url) {
try { return new URL(url).protocol === 'https:'; } catch { return false; }
} Type guard
function asHttpsBambooOrigin(value) {
const u = new URL(value);
return u.protocol === 'https:' ? u.origin : null;
} Try / catch
try {
assertBambooHRUrl(apiUrl);
} catch (err) {
if (/must use HTTPS/.test(err.message)) {
apiUrl = apiUrl.replace(/^http:/, 'https:');
assertBambooHRUrl(apiUrl);
} else throw err;
} Prevention
- All BambooHR tenants serve HTTPS — always write https:// origins.
- Remove localhost/http stub URLs from production config.
- Lint config for non-https URLs at startup.
- Check scheme constants used when building URLs programmatically.
When it happens
Trigger: Calling assertBambooHRUrl with `http://mycompany.bamboohr.com/careers/list` or any other non-https scheme that still parses (e.g. a `file://` or custom-scheme URL).
Common situations: Hand-written config using http because the tenant page once redirected, or internal test/stub URLs like `http://localhost` accidentally left in portals.yml.
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
- arbeitnow: URL must use HTTPS
- ashby: URL must use HTTPS
- bamboohr: untrusted hostname
- breezy: URL must use HTTPS
- builtin: URL must use HTTPS
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/72d229e4267b734c.
Report an issue: GitHub.
Appendix: source
Thrown at providers/bamboohr.mjs:27
// match on `<safe-tenant>.bamboohr.com` rather than a static allowlist
// (same approach as the recruitee provider).
//
// The list endpoint (`/careers/list`) returns lightweight metadata — enough for
// the Job contract (title, url, location) at zero token cost. The full JD lives
// behind a second `/careers/<id>/detail` request, which the scanner deliberately
// skips to stay zero-token (so `description`/`postedAt` are omitted).
const BAMBOOHR_HOST_RE = /^[a-z0-9][a-z0-9-]*\.bamboohr\.com$/;
/** @param {string} url */
function assertBambooHRUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`bamboohr: invalid URL: ${url}`);
}
if (parsed.protocol !== 'https:') throw new Error(`bamboohr: URL must use HTTPS: ${url}`);
if (!BAMBOOHR_HOST_RE.test(parsed.hostname)) {
throw new Error(`bamboohr: untrusted hostname "${parsed.hostname}" — must match <tenant>.bamboohr.com`);
}
return url;
}
/**
* Resolve the tenant origin (`https://<tenant>.bamboohr.com`) from an entry.
* Honours an explicit `api:` URL, else parses `careers_url`.
* @param {import('./_types.js').PortalEntry} entry
* @returns {string | null}
*/
function resolveOrigin(entry) {
const rawApi = typeof entry.api === 'string' ? entry.api : '';
const rawCareers = typeof entry.careers_url === 'string' ? entry.careers_url : '';
const raw = (rawApi || rawCareers).trim();
if (!raw) return null;
let parsed;View on GitHub (pinned to aac998c7ed)