/** * PackageGateScanner — Phase 2: Version Conflict Detection * * Supports: * - package-lock.json (npm) * - pnpm-lock.yaml (pnpm) * - bun.lockb (bun; binary but contains ASCII-readable sections) */ import { Scanner, ScanResult, Finding, Severity } from '../types'; export interface ParsedDependency { name: string; version: string; resolved?: string; integrity?: string; } export interface ParsedLockResult { lockType: 'npm' | 'pnpm' | 'bun'; dependencies: ParsedDependency[]; /** package name → all versions found across the lock file */ rawVersionMap: Record; } export interface ConflictFinding { packageName: string; versions: string[]; conflictType: 'multi-version' | 'suspicious-version' | 'pinned-mismatch'; severity: Severity; details?: string; } /** * Detect version conflicts and anomalies from a parsed lock file result. * * Returns ConflictFinding[] covering three conflict types: * - multi-version: same package resolved to ≥2 different versions * - suspicious-version: version has pre-release suffix or .0.0 ending * - pinned-mismatch: version doesn't match strict semver (x.y.z) */ export declare function detectVersionConflicts(result: ParsedLockResult): ConflictFinding[]; export declare class PackageGateLockParser { /** * Parse npm `package-lock.json` (lockfileVersion 1, 2, or 3). * * v1: top-level `dependencies` map * v2/v3: top-level `packages` map (preferred) plus optional `dependencies` */ parseNpmLock(content: string): ParsedLockResult; /** * Parse pnpm `pnpm-lock.yaml`. * * We use a hand-rolled YAML parser focused on the lock file structure * rather than pulling in a full YAML library: * * lockfileVersion: 5.x / '6.0' * * v5 format: * packages: * /foo/1.2.3: * resolution: {integrity: sha512-...} * * v6 format: * packages: * foo@1.2.3: * resolution: {integrity: sha512-..., tarball: ...} * * v9 format (lockfileVersion: '9.0'): * snapshots: * foo@1.2.3: * ... * packages: * foo@1.2.3: * resolution: ... */ parsePnpmLock(content: string): ParsedLockResult; /** * Parse bun `bun.lockb`. * * bun.lockb is a binary file, but it contains readable ASCII sections * with package name@version strings. We extract those heuristically. * * Pattern seen in bun.lockb ASCII sections: * "package-name@version" strings surrounded by null bytes / binary data. * * We scan the buffer for printable ASCII runs and extract npm-style * `name@semver` tokens from them. */ parseBunLock(content: string): ParsedLockResult; } /** * Detect suspicious install hooks in a `package.json` file. * * Checks `scripts.preinstall`, `scripts.install`, and `scripts.postinstall` for: * - PKGATE-010 (high): dangerous shell commands (curl, wget, bash, sh, eval, exec) * - PKGATE-011 (critical): base64 decode patterns * - PKGATE-012 (high): external URL references (http/https) * - PKGATE-013 (info): blank / whitespace-only hook * * @param packageJsonContent UTF-8 content of the `package.json` file * @param filePath Absolute path of the file (used for Finding.file) * @returns Finding[] — may be empty if no suspicious hooks found */ export declare function detectSuspiciousHooks(packageJsonContent: string, filePath: string): Finding[]; export declare class PackageGateScanner implements Scanner { name: string; description: string; private parser; scan(targetDir: string): Promise; } //# sourceMappingURL=package-gate-scanner.d.ts.map