@cipheraheadio/sdk
v1.1.0
Published
Official Node.js SDK for CipherAhead — post-quantum cryptography audit API
Maintainers
Readme
@cipherahead/sdk
Official Node.js SDK for the CipherAhead post-quantum cryptography (PQC) audit API.
Scan repositories, directories, files, live websites, and code snippets for weak or quantum-vulnerable cryptography using the same multi-engine pipeline that powers the CipherAhead platform.
Requirements
| | |
|---|---|
| Node.js | ≥ 18 |
| CipherAhead server | running locally (npm run server) or deployed |
Installation
# From npm (once published)
npm install @cipherahead/sdk
# Directly from the monorepo
import { CipherAhead } from "./sdk/index.js";Quick start
import { CipherAhead } from "@cipherahead/sdk";
const ca = new CipherAhead({ baseUrl: "http://127.0.0.1:8787" });
// Scan a local directory
const result = await ca.scanDirectory("./src");
console.log(result.riskScore); // 0-100 (higher = riskier)
console.log(result.ciStatus); // "Pass" | "Fail"
console.log(result.critical); // number of critical findings
// Assert safety thresholds (throws AssertionError if exceeded)
result.assertSafe({ maxRiskScore: 70, failOnCritical: true });Constructor
new CipherAhead(options?)| Option | Type | Default | Description |
|---|---|---|---|
| baseUrl | string | "http://127.0.0.1:8787" | CipherAhead server URL |
| apiKey | string | — | API key (future auth) |
| timeout | number | 120000 | Request timeout in ms |
| maxFiles | number | 500 | Max files per directory scan |
Instance methods
health()
Check whether the server is reachable.
const { ok, latencyMs } = await ca.health();scanDirectory(dirPath, opts?)
Recursively collect and scan all source files in a directory.
Skips node_modules, .git, dist, build, and similar non-source directories.
const result = await ca.scanDirectory("./src", { maxFiles: 300 });Supported extensions: .js .ts .jsx .tsx .py .go .java .rs .cs .cpp .rb .php .yaml .toml .tf .env and more.
scanFiles(filePaths)
Scan specific files by path.
const result = await ca.scanFiles(["src/auth.ts", "config/tls.yaml"]);scanGitHub(repoUrl, opts?)
Download and audit a public or private GitHub repository.
const result = await ca.scanGitHub("https://github.com/org/repo", {
branch: "main",
token: process.env.GITHUB_TOKEN, // for private repos
});scanUrl(url)
Crawl a live website and audit its JavaScript, CSS, TLS configuration, and source maps.
const result = await ca.scanUrl("https://myapp.com");
console.log(result.webMeta?.sourceMapsRecovered); // recovered source filesWhat the crawler collects:
- Linked JavaScript and CSS files
- Inline
<script>blocks - Webpack / Vite source maps → original TypeScript/JSX before minification
- TLS certificate info and cipher suites
- Up to 4 pages via
<a href>crawling
scanCode(code, opts?)
Scan a raw string of source code.
const result = await ca.scanCode(
`const cipher = crypto.createCipher("aes-128-cbc", key);`,
{ filename: "auth.js" }
);Progress events
CipherAhead extends EventEmitter and emits "progress" events throughout the scan lifecycle:
ca.on("progress", ({ phase, message }) => {
console.log(`[${phase}] ${message}`);
});Static helpers
CipherAhead.scan(type, target, sdkOpts?, scanOpts?)
One-shot scan without instantiating the class:
const result = await CipherAhead.scan("url", "https://example.com");type must be one of: "directory" · "files" · "github" · "url" · "code"
CipherAhead.gate(type, target, opts?)
Scan + assert in a single call. Designed for CI pipelines:
await CipherAhead.gate("directory", ".", {
maxRiskScore: 60,
failOnCritical: true,
failOnHigh: false,
});Throws AssertionError if thresholds are exceeded.
ScanResult API
Every scan method returns a ScanResult instance.
Core properties
| Property | Type | Description |
|---|---|---|
| source | string | Label (path / URL / repo) |
| riskScore | number | 0–100, higher = riskier |
| riskLevel | Severity | "Critico" | "Alto" | "Medio" | "Bajo" | "Info" |
| agilityScore | number | 0–100 PQC readiness (higher = better) |
| ciStatus | "Pass"\|"Fail" | CI gate result |
| passed / failed | boolean | Derived from ciStatus |
| findings | number | Total finding count |
| critical / high | number | By severity |
| aiVerified | number | AI-confirmed findings |
| scannedFiles | number | |
| isPartialScan | boolean | true when backend was unavailable |
| webMeta | object\|undefined | Web crawl metadata (URL scans only) |
Filtering
result.filter("Alto") // findings at severity Alto or above
result.criticalFindings // array of critical findings
result.highFindings // array of high + critical findings
result.aiFindings // AI-validated findings only
result.byFile // Map<path, Finding[]>
result.byAlgorithm // Map<algorithm, Finding[]>Assertions
result.assertSafe({
maxRiskScore: 70, // default
failOnCritical: true, // default
failOnHigh: false, // default
});Returns this when safe — throws AssertionError otherwise.
Reports
result.toMarkdown() // human-readable Markdown string
result.toJSON() // raw API JSONError types
| Class | Code | When |
|---|---|---|
| ServerUnavailableError | SERVER_UNAVAILABLE | Server not reachable |
| ScanFailedError | SCAN_FAILED | Non-2xx from API |
| AssertionError | ASSERTION_FAILED | assertSafe() / gate() threshold exceeded |
| TimeoutError | TIMEOUT | Scan exceeded timeout ms |
| ValidationError | VALIDATION_ERROR | Bad input (invalid URL, empty code, etc.) |
All extend CipherAheadError, which extends Error.
import { AssertionError, ServerUnavailableError } from "@cipherahead/sdk";
try {
await ca.scanDirectory("./src");
} catch (e) {
if (e instanceof ServerUnavailableError) {
console.error("Start the server: npm run server");
} else if (e instanceof AssertionError) {
console.error(`Audit failed — score ${e.result.riskScore}`);
process.exit(1);
}
throw e;
}CI integration
GitHub Actions
- name: Start CipherAhead server
run: npm run server &
- name: PQC audit
run: node sdk/examples/04-ci-gate.mjs . --max-risk-score=70npm script
{
"scripts": {
"audit:pqc": "node sdk/examples/04-ci-gate.mjs src"
}
}Programmatic gate
// scripts/pqc-gate.mjs
import { CipherAhead, AssertionError } from "@cipherahead/sdk";
try {
await CipherAhead.gate("directory", "./src", {
maxRiskScore: 60,
failOnCritical: true,
});
console.log("PQC audit passed ✓");
} catch (e) {
if (e instanceof AssertionError) {
console.error(e.message);
process.exit(1);
}
throw e;
}Examples
| File | Description |
|---|---|
| examples/01-scan-directory.mjs | Scan ./src, print summary |
| examples/02-scan-github.mjs | Scan a GitHub repo, print Markdown report |
| examples/03-scan-url.mjs | Crawl and scan a live website |
| examples/04-ci-gate.mjs | CI gate with exit codes |
| examples/05-events-and-report.mjs | Progress events + write .md report |
Run any example:
# Make sure the server is running first
npm run server
# Then in another terminal
node sdk/examples/01-scan-directory.mjs
node sdk/examples/03-scan-url.mjs https://example.com
node sdk/examples/04-ci-gate.mjs . --max-risk-score=60 --fail-on-highDetection pipeline
Every scan runs the same 5-engine pipeline:
| Engine | What it does |
|---|---|
| local-context | Pattern rules with comment/doc filtering |
| structural | API-call and config-block analysis |
| tree-sitter | AST-level analysis per language (if installed) |
| semgrep | SAST rules (if semgrep CLI installed) |
| ai-claude | AI reasoning via Claude (if ANTHROPIC_API_KEY set) |
Findings from all engines are merged, deduplicated, and scored into a single ScanResult.
TypeScript
Full type definitions are included in types.d.ts — no @types package needed.
import type { ScanResult, Finding, Severity } from "@cipherahead/sdk";