DIYgod/RSSHub · error · RejectError

Authentication failed. Access denied.\n${requestPath}

Error message

Authentication failed. Access denied.\n${requestPath}

What it means

Thrown by the access-control middleware when an operator has set ACCESS_KEY and the incoming request fails both auth checks. A request is allowed only if query param `key` exactly equals config.accessKey, or query param `code` equals md5(requestPath + accessKey). Paths '/', '/robots.txt', '/favicon.ico', '/logo.png' are exempt. It uses RejectError, which RSSHub maps to a distinct rejection response (HTTP 403) rather than a generic 500.

Source

Thrown at lib/middleware/access-control.ts:8

import type { MiddlewareHandler } from 'hono';

import { config } from '@/config';
import RejectError from '@/errors/types/reject';
import md5 from '@/utils/md5';

const reject = (requestPath) => {
    throw new RejectError(`Authentication failed. Access denied.\n${requestPath}`);
};

const middleware: MiddlewareHandler = async (ctx, next) => {
    const requestPath = new URL(ctx.req.url).pathname;
    const accessKey = ctx.req.query('key');
    const accessCode = ctx.req.query('code');

    if (['/', '/robots.txt', '/favicon.ico', '/logo.png'].includes(requestPath)) {
        await next();
    } else {
        if (config.accessKey && !(config.accessKey === accessKey || accessCode === md5(requestPath + config.accessKey))) {
            return reject(requestPath);
        }
        await next();
    }
};

export default middleware;

View on GitHub (pinned to bed535e087)

Solutions

  1. Append `?key=<your ACCESS_KEY value>` to the RSSHub URL.
  2. Or compute `?code=md5(pathname + ACCESS_KEY)` (lowercase hex) and append it.
  3. If protection is unwanted, unset the ACCESS_KEY env var and restart the instance.
  4. Ensure no reverse proxy/CDN strips query parameters before the request reaches RSSHub.

Example fix

// before
https://rsshub.example.com/bbc
// after (share-the-key form)
https://rsshub.example.com/bbc?key=YOUR_ACCESS_KEY
// after (code form: md5('/bbc' + ACCESS_KEY))
https://rsshub.example.com/bbc?code=<md5hex>
Defensive patterns

Strategy: validation

Validate before calling

// Client side: compute the access code before the call.
import crypto from 'node:crypto';
const ACCESS_KEY = process.env.ACCESS_KEY!;
const pathname = new URL(targetUrl).pathname;
const code = crypto.createHash('md5').update(pathname + ACCESS_KEY).digest('hex');
const authedUrl = new URL(targetUrl);
if (!authedUrl.searchParams.has('key') && !authedUrl.searchParams.has('code')) {
  authedUrl.searchParams.set('code', code);
}

Type guard

// Narrow an authenticated request before sending.
const isAuthed = (u: URL, accessKey: string): boolean =>
  u.searchParams.get('key') === accessKey ||
  u.searchParams.get('code') ===
    crypto.createHash('md5').update(u.pathname + accessKey).digest('hex');

Try / catch

// Operators usually do not catch this — it is a deliberate 403.
// If automating, treat a 403 from access-control as a credentials issue, not a retry candidate.
if (res.status === 403 && /Access denied/.test(body)) {
  throw new Error('RSSHub access key missing/wrong — fix credentials, do not retry');
}

Prevention

When it happens

Trigger: config.accessKey is set (e.g. ACCESS_KEY env) and the request to any non-exempt path omits both `?key=` and `?code=`, supplies a wrong key, or supplies a code computed against a different path/accessKey.

Common situations: Operator enables ACCESS_KEY to protect a public instance but forgets to distribute the key; client uses `?code=` computed with a stale or URL-encoded path; reverse proxy strips the query string; CI hits a protected route without credentials.

Understand the failure class

Related errors


AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12). Data as JSON: /api/errors/d4cd898eb5452ada. Report an issue: GitHub.