Package Exports
- @ktbatterham/external-posture-core
- @ktbatterham/external-posture-core/cli
- @ktbatterham/external-posture-core/history-diff
- @ktbatterham/external-posture-core/types
Readme
@ktbatterham/external-posture-core
The passive security posture engine behind SecURL.
@ktbatterham/external-posture-core is the reusable scanner engine behind SecURL, a posture-first external security review tool for public web targets.
It is designed for passive, low-noise assessment rather than active exploitation or broad reconnaissance. The engine turns public web signals into structured JSON, Markdown, SARIF, and CI-friendly output.
Visit the SecURL site · Try the live scanner · View the source
Quick Start
Run a scan without installing:
npx @ktbatterham/external-posture-core scan example.comInstall globally for the short epi command:
npm install -g @ktbatterham/external-posture-core
epi scan example.comPrefer the hosted report workspace? Use app.securl.online.
Package trust and release signals
- public source repository with package code under
packages/core - npm publishing from GitHub Actions with provenance enabled
- CI checks covering audit, build, lint, tests, and dry-run packaging
- no install scripts
- one runtime dependency (
node-html-parser) - published MIT license, changelog, release notes, and security policy
Security disclosure guidance:
Safety model
External Posture Insight is passive-first and production-conscious, but it is not magic invisibility dust. A standard scan may make DNS queries, perform TLS handshakes, fetch the target page, follow redirects, query third-party public datasets such as Certificate Transparency / OSV, and run a small set of low-noise HTTP checks. It does not attempt exploitation, brute forcing, authentication bypass, form submission, fuzzing, password testing, or vulnerability exploitation.
Use it only against systems you own or are authorized to assess. Results are heuristic and should be treated as decision support, not a formal penetration test or compliance attestation.
What it covers
- HTTP security headers and redirect posture
- TLS and certificate inspection
- Cookie hygiene
- Passive HTML inspection
- Passive public IOC and abuse indicators for suspicious scripts, off-origin credential flows, exposed paths, CT takeover clues, and visible vulnerable client libraries
- AI surface and third-party trust signals
- Low-noise exposure, CORS, API-surface, and DNS/mail posture checks
- OWASP/MITRE-aligned finding labels
Current status
This package is published and consumable from npm:
@ktbatterham/external-posture-core- Product site: securl.online
- Live scanner: app.securl.online
It is also used by the External Posture Insight app from the local workspace during development.
Release workflow
- local package check:
npm run pack:core - CI verification:
.github/workflows/core-package-checks.yml - publish workflow:
.github/workflows/publish-core-package.yml - publish requires an
NPM_TOKENrepository secret - publish uses npm provenance (
npm publish --provenance)
Recommended release flow:
- update the version in
packages/core/package.json - run
npm run test:core - run
npm run pack:core - create and push a tag like
core-v0.1.1 - let the publish workflow release the package
See also:
packages/core/CHANGELOG.mdpackages/core/RELEASING.md
Public API
CLI
The package includes a pipe-friendly CLI:
Scan multiple targets in one run:
npx @ktbatterham/external-posture-core scan example.com github.com bbc.co.uk
epi scan example.com github.com bbc.co.ukAvailable output formats:
npx @ktbatterham/external-posture-core scan example.com --format summary
npx @ktbatterham/external-posture-core scan example.com --format json
npx @ktbatterham/external-posture-core scan example.com --format markdown
npx @ktbatterham/external-posture-core scan example.com --format sarif
npx @ktbatterham/external-posture-core scan example.com --format ci-jsonThe CLI writes machine-readable report output to stdout, and lightweight multi-target progress to stderr only when running interactively. This keeps JSON/SARIF output pipe-friendly.
Scan modes:
npx @ktbatterham/external-posture-core scan example.com
npx @ktbatterham/external-posture-core scan example.com --quiet
npx @ktbatterham/external-posture-core scan example.com --deep-passive- default scan: primary response plus bounded passive enrichment, including HTML, DNS/mail, Certificate Transparency, OSV, exposure, CORS, API-surface, and public trust signals.
--quiet: keeps primary response, TLS, headers, cookies, redirects, DNS/mail, Certificate Transparency summary, infrastructure, and public trust checks; skips page-body analysis, related-page crawl, security.txt fetch, identity discovery, exposure probes, CORS probes, API probes, OSV lookups, and CT host sampling. Use this for lower-noise CI smoke checks or frequent regression monitoring.--deep-passive: expands passive CT host sampling, related-page crawl, exposure probes, and API-surface probes while keeping request counts and scan duration bounded. Use this for pre-release or scheduled posture reviews where a broader passive pass is worth the extra time.
CI policy modes:
npx @ktbatterham/external-posture-core scan example.com github.com --fail-on warning
npx @ktbatterham/external-posture-core scan example.com --baseline previous-report.json --fail-on-regression
npx @ktbatterham/external-posture-core scan example.com github.com --fail-if-score-below 75
npx @ktbatterham/external-posture-core compare current-report.json baseline-report.json --fail-on critical --fail-on-regression--fail-onsets exit code1when findings at or above the selected severity are present.--fail-on-regressionsets exit code1when the baseline comparison detects a regression (score drop, new issues, or worse HTTP status class).--fail-if-score-belowsets exit code1when any scanned target score is below the given threshold.
Write results to a file:
npx @ktbatterham/external-posture-core scan example.com --format json --output report.jsonCompare against a previously saved JSON report:
npx @ktbatterham/external-posture-core scan example.com --baseline previous-report.jsonCompare two saved reports directly:
npx @ktbatterham/external-posture-core compare current-report.json baseline-report.json
npx @ktbatterham/external-posture-core compare current-report.json baseline-report.json --format sarifBatch scans return:
- summary: one line per target
- markdown: a compact comparison table
- sarif: one SARIF log containing findings across all scanned targets
- ci-json: compact machine-readable output with policy pass/fail status
- json:
{
"analyses": [{ "...": "scan result" }]
}Direct report comparison returns:
- summary: score, status, and change summary
- markdown: a compact comparison report
- sarif: only findings that are newly introduced in the current report versus the baseline
- ci-json: compact machine-readable output with policy pass/fail status and diff details
- json:
{
"current": { "...": "latest saved report" },
"baseline": { "...": "older saved report" },
"diff": { "...": "structured change summary" }
}Show usage:
npx @ktbatterham/external-posture-core --helpanalyzeUrl(url)
Run a full posture analysis for a public target.
import { analyzeUrl } from "@ktbatterham/external-posture-core";
const result = await analyzeUrl("https://example.com");
console.log(result.score, result.grade);analyzeTarget remains available as a compatibility alias, but analyzeUrl is the primary public entrypoint.
analyzeUrl("https://example.com", { scanMode: "quiet" }) uses the same quiet boundary as CLI --quiet. analyzeUrl("https://example.com", { scanMode: "deep-passive" }) uses the expanded passive recon boundary as CLI --deep-passive.
When a baseline report is supplied to the CLI, summary and Markdown output append a Changes Since Baseline section. JSON output returns:
{
"analysis": { "...": "latest scan result" },
"diff": { "...": "structured change summary" }
}analyzeHtmlDocument(url, html)
Run passive HTML/content analysis against a fetched HTML document.
import { analyzeHtmlDocument } from "@ktbatterham/external-posture-core";
const htmlSecurity = analyzeHtmlDocument("https://example.com", "<html>...</html>");
console.log(htmlSecurity.clientExposureSignals);Notes
- Only use this against targets you are authorized to assess.
- The package is intentionally conservative about active probing.
- Default scans perform bounded passive enrichment; quiet scans skip page-body and probe-heavy enrichment to keep request volume lower.
- Scoring is heuristic and should be treated as a prioritization aid, not an absolute security truth.
- The author is not responsible for misuse, unauthorized scanning, operational impact, or decisions made from the output without appropriate validation.