<aside> 📜 TABLE OF CONTENTS

Security Audit

Our app uses JEST for automated testing

Auditing script

The following python script was used to check if any of our app uses any on the compromised packages by recursively exploring packages in package.json and in package-lock.json to see if they match any of the compromised packages

import argparse
import json
import os
import sys
from typing import Dict, List, Optional, Tuple, Set

def load_json_file(path: str) -> Optional[dict]:
    try:
        with open(path, "r", encoding="utf-8") as f:
            return json.load(f)
    except FileNotFoundError:
        return None
    except json.JSONDecodeError as e:
        print(f"[!] Failed to parse JSON file {path}: {e}", file=sys.stderr)
        return None

def is_compromised(pkg: str, version: Optional[str], compromised_map: Dict[str, List[str]]) -> bool:
    if pkg not in compromised_map:
        return False
    bad_versions = compromised_map[pkg]
    if not bad_versions: 
        return True
    return version in bad_versions

def check_package_json(package_json: dict, compromised_map: Dict[str, List[str]]) -> List[Dict]:
    found = []
    if not package_json:
        return found
    fields = ["dependencies", "devDependencies", "optionalDependencies", "peerDependencies"]
    for field in fields:
        bucket = package_json.get(field, {}) or {}
        for name, version_spec in bucket.items():

            if is_compromised(name, version_spec, compromised_map):
                found.append({
                    "package": name,
                    "version_spec": version_spec,
                    "field": field
                })
            elif name in compromised_map and not compromised_map[name]:

                found.append({
                    "package": name,
                    "version_spec": version_spec,
                    "field": field
                })
    return found

def search_lock_dependencies(lock: dict, compromised_map: Dict[str, List[str]]) -> List[Dict]:
    results = []
    visited = set()

def dfs(dep_name, dep_info, path):
    if isinstance(dep_info, str):
        version = dep_info
        subdeps = {}
    elif isinstance(dep_info, dict):
        version = dep_info.get("version", None)
        subdeps = dep_info.get("dependencies", {})
    else:
        version = None
        subdeps = {}

    if version and dep_name in compromised and version in compromised[dep_name]:
        matches.append({
            "package": dep_name,
            "version": version,
            "path": " -> ".join(path + [f"{dep_name}@{version}"])
        })

    if isinstance(subdeps, dict):
        for sub_name, sub_info in subdeps.items():
            dfs(sub_name, sub_info, path + [f"{dep_name}@{version}" if version else dep_name])

    dfs(lock, [])
    return results

def print_summary(direct_pkgjson, lock_matches):
    any_found = bool(direct_pkgjson or lock_matches)
    print("\\n=== Compromised package detection summary ===")
    if not any_found:
        print("No compromised packages found.")
        return

    if direct_pkgjson:
        print("\\nDirect references in root package.json:")
        for m in direct_pkgjson:
            print(f"  - {m['package']} (version spec: {m['version_spec']}) in {m['field']}")

    if lock_matches:
        print("\\nTransitive references found in package-lock.json (root -> ... -> compromised):")
        for m in lock_matches:
            chain = " -> ".join(f"{p['name']}@{p.get('version') or '?'}" for p in m["path_chain"])
            print(f"  - {m['package']}@{m.get('version')}  (chain: {chain})")

def main(argv=None):
    p = argparse.ArgumentParser(description="Detect compromised npm packages with version checks.")
    p.add_argument("--compromised-json", required=True,
                   help="JSON file mapping {package: [versions]} (empty list = all versions).")
    p.add_argument("--package-json", default="package.json",
                   help="Path to package.json (default: ./package.json)")
    p.add_argument("--package-lock", default="package-lock.json",
                   help="Path to package-lock.json (default: ./package-lock.json)")
    p.add_argument("--output", default="report.json",
                   help="Write JSON report to this file (default: report.json).")
    args = p.parse_args(argv)

    compromised_map = load_json_file(args.compromised_json)
    if not compromised_map:
        print("[!] Compromised JSON file missing or invalid.", file=sys.stderr)
        return 2

    root_pj = load_json_file(args.package_json)
    direct_matches = check_package_json(root_pj, compromised_map) if root_pj else []

    lock = load_json_file(args.package_lock)
    lock_matches = []
    if lock and "dependencies" in lock:
        lock_root = {"dependencies": lock.get("dependencies", {})}
        lock_matches = search_lock_dependencies(lock_root, compromised_map)
    elif lock and "packages" in lock:
        synthetic_root = {"dependencies": {}}
        for path_key, info in lock.get("packages", {}).items():
            if path_key == "":
                continue
            name = info.get("name") or os.path.basename(path_key)
            synthetic_root["dependencies"].setdefault(name, info)
        lock_matches = search_lock_dependencies(synthetic_root, compromised_map)

    report = {
        "compromised_input": compromised_map,
        "direct_package_json_matches": direct_matches,
        "package_lock_matches": lock_matches,
    }

    with open(args.output, "w", encoding="utf-8") as outf:
        json.dump(report, outf, indent=2)
        print(f"[+] Report written to {args.output}")

    print_summary(direct_matches, lock_matches)
    return 1 if direct_matches or lock_matches else 0

if __name__ == "__main__":
    sys.exit(main())

Audit script usage

Tinycolor npm Package Compromise

npm debug and chalk audit

Protecting against supply chain attacks

Protecting against being infected by other malware through the same process