Find open redirects and mixed content in a built site (offline) or a live crawl: http:// scripts and styles on HTTPS pages, insecure forms, client-side redirects fed by the URL, open redirect rules in _redirects/vercel.json/nginx, HTTPS downgrades, and optional safe redirect probing.
1 Point the @mrlouiswright scope at GitHub Packages in .npmrc
Published to GitHub Packages, not npmjs.com. GitHub Packages needs a GitHub token with read:packages to install, even for public packages: add //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN} to .npmrc or run npm login --registry=https://npm.pkg.github.com.
$npx redirect-sentinel siteredirect-sentinel — 1 target(s)site html: 2 js: 1 css: 0 config: 3 HIGH site/index.html:14 Form submits to http://forms.example.com/submit [insecure-form] ↳ http://forms.example.com/submit ↳ fix: Post to https:// only. HIGH site/index.html:3 <link rel="stylesheet" href="http://cdn.example.com/style.css"> on an HTTPS page [mixed-content-active] ↳ http://cdn.example.com/style.css HIGH site/index.html:5 <script src="http://cdn.example.com/lib.js"> on an HTTPS page [mixed-content-active]...12 high, 5 medium, 2 low✖ Failing (fail-on: high).
Real output from running redirect-sentinel locally on a test fixture.
Why it exists
Point redirect-sentinel at your build output (dist/, public/, _site/) in CI, or at a URL to crawl the live site. CLI, library and GitHub Action. Node.js 18+, zero runtime dependencies. Broken links are out of scope (see static-link-sentinel).
Features
Mixed content
on HTTPS pages: http:// scripts, stylesheets, @import, iframes, objects and <base> (active, high); images, srcset, media, icons and CSS url() (passive, medium); forms posting to http://; http:// links (low, once per host). localhost URLs are ignored. Use --http if the static site is not served over HTTPS.
Client-side open redirects
location = …, location.assign/replace, window.open, router.push, navigate fed by location.search/hash, URLSearchParams, document.referrer or window.name, directly or through a variable. Redirects guarded by startsWith('/') or an origin check are skipped. This is a heuristic, not a data-flow engine: minified bundles are only checked for direct flows.
Server redirect rules
Netlify _redirects and netlify.toml, vercel.json/next.config.js, nginx (return 302 $arg_url) and Apache (RewriteRule … %1 [R]) rules whose destination host comes from the request.
Links
that pass a full URL in a redirect-style parameter (next, url, returnTo, redirect_uri, continue, goto…).
Crawl only
redirect chains longer than 3 hops, https:// → http:// downgrades (including meta refresh), http:// not redirecting to https://, and same-origin JavaScript files.
--probe
(crawl only, opt-in): for each same-origin link with a redirect-style parameter, requests it with https://redirect-sentinel.invalid/, //redirect-sentinel.invalid/ and similar payloads, without following the redirect. A Location pointing at that host is a confirmed open-redirect (critical). .invalid can never resolve, so nobody is sent anywhere. Only probe sites you own or are authorised to test.