Skip to content

klyrek-js

Status: live on PyPI — pip install klyrek-js

Scans client-side JavaScript source for hardcoded secrets (AWS keys, Google API keys, Stripe keys, Slack tokens, GitHub PATs, private key blocks, and a generic api_key=/secret_key=-shaped assignment pattern) and extracts API-shaped endpoint references (both relative paths and absolute URLs).

from klyrek_js.secrets import scan_for_secrets
from klyrek_js.endpoints import extract_endpoints

findings = scan_for_secrets(js_source, source_url="https://admin.sandbox.klyrek.com/assets/app.js")
endpoints = extract_endpoints(js_source, base_url="https://admin.sandbox.klyrek.com/assets/app.js")

Real finding from the sandbox (matched values are masked to the first/last 4 characters, since a Finding may end up in a report handed to a third party):

{
  "title": "Hardcoded Stripe Live Secret Key found in JavaScript",
  "severity": "critical",
  "evidence": ["sk_l...DEMO", "https://admin.sandbox.klyrek.com/assets/app.js"],
  "module": "klyrek-js"
}

extract_endpoints pulls out both fetch("/api/v1/products")-style relative paths (anchored to a small set of API-shaped prefixes: /api, /v1, /v2, /graphql, /rest, so it doesn't match every static asset path like /favicon.ico) and full absolute URLs like https://api.sandbox.klyrek.com/api/v1/admin/stats — both show up as real js-endpoint-sourced Endpoint records once run through the full pipeline.

API reference

klyrek_js.secrets

Detect hardcoded secrets and API keys embedded in JavaScript source.

scan_for_secrets

scan_for_secrets(js_source: str, source_url: str | None = None) -> list[Finding]

Scan JavaScript source text for hardcoded secrets and API keys.

Matched values are masked in the evidence (kept to first/last 4 chars) rather than stored in full, since a Finding may end up in a report handed to a third party.

Source code in klyrek_js\secrets.py
def scan_for_secrets(js_source: str, source_url: str | None = None) -> list[Finding]:
    """Scan JavaScript source text for hardcoded secrets and API keys.

    Matched values are masked in the evidence (kept to first/last 4 chars) rather than
    stored in full, since a Finding may end up in a report handed to a third party.
    """
    findings: list[Finding] = []
    for name, pattern, severity in _COMPILED:
        for match in pattern.finditer(js_source):
            evidence = [_mask(match.group(0))]
            if source_url:
                evidence.append(source_url)
            findings.append(
                Finding(
                    title=f"Hardcoded {name} found in JavaScript",
                    severity=severity,
                    description=f"A pattern matching a {name} was found embedded in "
                    "client-side JavaScript, which is downloadable by anyone visiting the page.",
                    evidence=evidence,
                    module="klyrek-js",
                )
            )
    return findings

klyrek_js.endpoints

Extract API-like endpoint strings referenced inside JavaScript source.

extract_endpoints

extract_endpoints(js_source: str, base_url: str) -> list[Endpoint]

Pull API-shaped path and URL string literals out of a JavaScript source file.

Source code in klyrek_js\endpoints.py
def extract_endpoints(js_source: str, base_url: str) -> list[Endpoint]:
    """Pull API-shaped path and URL string literals out of a JavaScript source file."""
    seen: set[str] = set()
    endpoints: list[Endpoint] = []

    for match in _PATH_LITERAL.finditer(js_source):
        url = urljoin(base_url, match.group(1))
        if url not in seen:
            seen.add(url)
            endpoints.append(
                Endpoint(url=url, method="GET", source="js-endpoint", discovered_by="klyrek-js")
            )

    for match in _URL_LITERAL.finditer(js_source):
        url = match.group(1)
        if url not in seen and _looks_like_api_url(url):
            seen.add(url)
            endpoints.append(
                Endpoint(url=url, method="GET", source="js-endpoint", discovered_by="klyrek-js")
            )

    return endpoints