verimu 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -10
- package/dist/index.cjs +675 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +340 -2
- package/dist/index.d.ts +340 -2
- package/dist/index.mjs +667 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Core types for the Verimu scanning pipeline.
|
|
3
5
|
*
|
|
@@ -6,7 +8,7 @@
|
|
|
6
8
|
* → CveSource → Vulnerability[]
|
|
7
9
|
*/
|
|
8
10
|
/** Supported package ecosystems */
|
|
9
|
-
type Ecosystem = 'npm' | 'nuget' | 'cargo' | 'maven' | 'pip' | 'go';
|
|
11
|
+
type Ecosystem = 'npm' | 'nuget' | 'cargo' | 'maven' | 'pip' | 'go' | 'ruby';
|
|
10
12
|
/** Supported CI/CD providers */
|
|
11
13
|
type CiProvider = 'github' | 'gitlab' | 'bitbucket';
|
|
12
14
|
/** A single resolved dependency from a lockfile */
|
|
@@ -307,6 +309,342 @@ declare class NpmScanner implements DependencyScanner {
|
|
|
307
309
|
private parseDependenciesV1;
|
|
308
310
|
}
|
|
309
311
|
|
|
312
|
+
/**
|
|
313
|
+
* C# / NuGet dependency scanner.
|
|
314
|
+
*
|
|
315
|
+
* Parses `packages.lock.json` (NuGet lock file, generated by
|
|
316
|
+
* `dotnet restore --use-lock-file`) to extract the full resolved
|
|
317
|
+
* dependency tree. The lock file itself tracks Direct vs Transitive.
|
|
318
|
+
*
|
|
319
|
+
* Lock file format (NuGet v1):
|
|
320
|
+
* ```json
|
|
321
|
+
* {
|
|
322
|
+
* "version": 1,
|
|
323
|
+
* "dependencies": {
|
|
324
|
+
* "net8.0": {
|
|
325
|
+
* "PackageName": {
|
|
326
|
+
* "type": "Direct" | "Transitive",
|
|
327
|
+
* "resolved": "13.0.3",
|
|
328
|
+
* "contentHash": "..."
|
|
329
|
+
* }
|
|
330
|
+
* }
|
|
331
|
+
* }
|
|
332
|
+
* }
|
|
333
|
+
* ```
|
|
334
|
+
*/
|
|
335
|
+
declare class NugetScanner implements DependencyScanner {
|
|
336
|
+
readonly ecosystem: Ecosystem;
|
|
337
|
+
readonly lockfileNames: string[];
|
|
338
|
+
detect(projectPath: string): Promise<string | null>;
|
|
339
|
+
scan(projectPath: string, lockfilePath: string): Promise<ScanResult>;
|
|
340
|
+
/**
|
|
341
|
+
* Parses packages.lock.json and extracts dependencies across all
|
|
342
|
+
* target frameworks. Deduplicates by package name (keeps highest version
|
|
343
|
+
* if the same package appears under multiple frameworks).
|
|
344
|
+
*/
|
|
345
|
+
private parseLockfile;
|
|
346
|
+
/**
|
|
347
|
+
* Builds a purl for a NuGet package.
|
|
348
|
+
* NuGet purls are straightforward: pkg:nuget/Name@Version
|
|
349
|
+
*/
|
|
350
|
+
private buildPurl;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Python / pip dependency scanner.
|
|
355
|
+
*
|
|
356
|
+
* Supports multiple Python dependency file formats (in priority order):
|
|
357
|
+
* 1. `requirements.txt` — flat list of pinned dependencies
|
|
358
|
+
* 2. `Pipfile.lock` — Pipenv lock file with exact versions
|
|
359
|
+
*
|
|
360
|
+
* For `requirements.txt`, all listed packages are treated as direct
|
|
361
|
+
* dependencies (the file doesn't distinguish direct vs transitive).
|
|
362
|
+
* For `Pipfile.lock`, `default` packages are direct and `develop`
|
|
363
|
+
* packages are dev dependencies.
|
|
364
|
+
*
|
|
365
|
+
* Limitation: `requirements.txt` doesn't capture transitive deps unless
|
|
366
|
+
* generated with `pip freeze`. If using `pip freeze` output, all deps
|
|
367
|
+
* are listed but we can't distinguish direct vs transitive.
|
|
368
|
+
*/
|
|
369
|
+
declare class PipScanner implements DependencyScanner {
|
|
370
|
+
readonly ecosystem: Ecosystem;
|
|
371
|
+
readonly lockfileNames: string[];
|
|
372
|
+
detect(projectPath: string): Promise<string | null>;
|
|
373
|
+
scan(projectPath: string, lockfilePath: string): Promise<ScanResult>;
|
|
374
|
+
/**
|
|
375
|
+
* Parses `requirements.txt` format.
|
|
376
|
+
*
|
|
377
|
+
* Supports:
|
|
378
|
+
* - `package==1.2.3` (pinned)
|
|
379
|
+
* - `package>=1.2.0` (minimum — uses the specified version)
|
|
380
|
+
* - `package~=1.2.0` (compatible release)
|
|
381
|
+
* - Comments (`#`) and blank lines are skipped
|
|
382
|
+
* - `-r other-file.txt` (include directive) — skipped for now
|
|
383
|
+
* - `--index-url` and other pip flags — skipped
|
|
384
|
+
*/
|
|
385
|
+
private parseRequirementsTxt;
|
|
386
|
+
/**
|
|
387
|
+
* Parses `Pipfile.lock` (JSON format from Pipenv).
|
|
388
|
+
*
|
|
389
|
+
* Structure:
|
|
390
|
+
* ```json
|
|
391
|
+
* {
|
|
392
|
+
* "_meta": { ... },
|
|
393
|
+
* "default": {
|
|
394
|
+
* "requests": { "version": "==2.31.0", ... }
|
|
395
|
+
* },
|
|
396
|
+
* "develop": {
|
|
397
|
+
* "pytest": { "version": "==7.4.0", ... }
|
|
398
|
+
* }
|
|
399
|
+
* }
|
|
400
|
+
* ```
|
|
401
|
+
*/
|
|
402
|
+
private parsePipfileLock;
|
|
403
|
+
/**
|
|
404
|
+
* Extracts the version number from a pip version specifier.
|
|
405
|
+
* "1.2.3" → "1.2.3"
|
|
406
|
+
* "1.2.3,<2.0" → "1.2.3"
|
|
407
|
+
*/
|
|
408
|
+
private extractVersion;
|
|
409
|
+
/**
|
|
410
|
+
* Normalizes a pip package name per PEP 503.
|
|
411
|
+
* Converts to lowercase and replaces any run of [-_.] with a single hyphen.
|
|
412
|
+
*/
|
|
413
|
+
private normalizePipName;
|
|
414
|
+
/**
|
|
415
|
+
* Builds a purl for a PyPI package.
|
|
416
|
+
* Per purl spec, the type is "pypi" (not "pip").
|
|
417
|
+
*/
|
|
418
|
+
private buildPurl;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Rust / Cargo dependency scanner.
|
|
423
|
+
*
|
|
424
|
+
* Parses `Cargo.lock` (TOML format) to extract the full resolved
|
|
425
|
+
* dependency tree. Reads `Cargo.toml` to determine which packages
|
|
426
|
+
* are direct dependencies vs transitive.
|
|
427
|
+
*
|
|
428
|
+
* Cargo.lock format (v3):
|
|
429
|
+
* ```toml
|
|
430
|
+
* [[package]]
|
|
431
|
+
* name = "serde"
|
|
432
|
+
* version = "1.0.195"
|
|
433
|
+
* source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
434
|
+
* checksum = "abc123..."
|
|
435
|
+
* dependencies = [
|
|
436
|
+
* "serde_derive",
|
|
437
|
+
* ]
|
|
438
|
+
* ```
|
|
439
|
+
*
|
|
440
|
+
* Note: We use a simple TOML parser since Cargo.lock has a very
|
|
441
|
+
* regular structure (just [[package]] entries). No need for a full
|
|
442
|
+
* TOML library.
|
|
443
|
+
*/
|
|
444
|
+
declare class CargoScanner implements DependencyScanner {
|
|
445
|
+
readonly ecosystem: Ecosystem;
|
|
446
|
+
readonly lockfileNames: string[];
|
|
447
|
+
detect(projectPath: string): Promise<string | null>;
|
|
448
|
+
scan(projectPath: string, lockfilePath: string): Promise<ScanResult>;
|
|
449
|
+
/**
|
|
450
|
+
* Parses Cargo.lock by splitting on [[package]] blocks.
|
|
451
|
+
* This is a lightweight parser that handles the regular structure
|
|
452
|
+
* of Cargo.lock without needing a full TOML parser.
|
|
453
|
+
*/
|
|
454
|
+
private parseLockfile;
|
|
455
|
+
/**
|
|
456
|
+
* Extracts a string field value from a TOML block.
|
|
457
|
+
* Handles: `name = "value"` format.
|
|
458
|
+
*/
|
|
459
|
+
private extractField;
|
|
460
|
+
/**
|
|
461
|
+
* Parses Cargo.toml to extract direct dependency names.
|
|
462
|
+
* Looks for [dependencies] and [dev-dependencies] sections.
|
|
463
|
+
*/
|
|
464
|
+
private parseCargoToml;
|
|
465
|
+
/**
|
|
466
|
+
* Builds a purl for a Cargo (crates.io) package.
|
|
467
|
+
*/
|
|
468
|
+
private buildPurl;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Java / Maven dependency scanner.
|
|
473
|
+
*
|
|
474
|
+
* Maven doesn't have a lockfile. This scanner uses two strategies:
|
|
475
|
+
*
|
|
476
|
+
* 1. **Primary (auto)**: If `mvn` is on `$PATH`, runs
|
|
477
|
+
* `mvn dependency:list -DoutputType=text` to get the resolved
|
|
478
|
+
* dependency tree including transitive dependencies.
|
|
479
|
+
*
|
|
480
|
+
* 2. **Fallback (pre-generated)**: Looks for a `dependency-tree.txt`
|
|
481
|
+
* file in the project root. Users can generate this with:
|
|
482
|
+
* ```
|
|
483
|
+
* mvn dependency:list -DoutputFile=dependency-tree.txt -DoutputType=text
|
|
484
|
+
* ```
|
|
485
|
+
*
|
|
486
|
+
* The scanner detects a Maven project by the presence of `pom.xml`.
|
|
487
|
+
*
|
|
488
|
+
* Maven dependency:list output format (one per line):
|
|
489
|
+
* ```
|
|
490
|
+
* com.google.guava:guava:jar:32.1.3-jre:compile
|
|
491
|
+
* org.slf4j:slf4j-api:jar:2.0.9:compile
|
|
492
|
+
* junit:junit:jar:4.13.2:test
|
|
493
|
+
* ```
|
|
494
|
+
* Fields: groupId:artifactId:type:version:scope
|
|
495
|
+
*/
|
|
496
|
+
declare class MavenScanner implements DependencyScanner {
|
|
497
|
+
readonly ecosystem: Ecosystem;
|
|
498
|
+
readonly lockfileNames: string[];
|
|
499
|
+
/** Allow injection for testing */
|
|
500
|
+
private execSyncFn;
|
|
501
|
+
constructor(execSyncImpl?: typeof execSync);
|
|
502
|
+
detect(projectPath: string): Promise<string | null>;
|
|
503
|
+
scan(projectPath: string, _lockfilePath: string): Promise<ScanResult>;
|
|
504
|
+
/**
|
|
505
|
+
* Parses Maven `dependency:list` output.
|
|
506
|
+
*
|
|
507
|
+
* Each dependency line has the format:
|
|
508
|
+
* groupId:artifactId:type:version:scope
|
|
509
|
+
* groupId:artifactId:type:classifier:version:scope
|
|
510
|
+
*
|
|
511
|
+
* Lines are typically indented with leading whitespace.
|
|
512
|
+
*/
|
|
513
|
+
private parseDependencyList;
|
|
514
|
+
/** Checks if `mvn` is available on PATH */
|
|
515
|
+
private isMavenAvailable;
|
|
516
|
+
/**
|
|
517
|
+
* Runs `mvn dependency:list` and returns the output.
|
|
518
|
+
*/
|
|
519
|
+
private runMavenDependencyList;
|
|
520
|
+
/**
|
|
521
|
+
* Builds a purl for a Maven package.
|
|
522
|
+
* Format: pkg:maven/groupId/artifactId@version
|
|
523
|
+
*/
|
|
524
|
+
private buildPurl;
|
|
525
|
+
private buildResult;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Go module dependency scanner.
|
|
530
|
+
*
|
|
531
|
+
* Parses `go.sum` to extract the full resolved dependency list, and
|
|
532
|
+
* cross-references `go.mod` to distinguish direct vs indirect (transitive)
|
|
533
|
+
* dependencies.
|
|
534
|
+
*
|
|
535
|
+
* go.sum format (one or two lines per module):
|
|
536
|
+
* ```
|
|
537
|
+
* github.com/gin-gonic/gin v1.9.1 h1:abc123...=
|
|
538
|
+
* github.com/gin-gonic/gin v1.9.1/go.mod h1:def456...=
|
|
539
|
+
* ```
|
|
540
|
+
*
|
|
541
|
+
* Lines ending in `/go.mod` are checksums of the module's go.mod file —
|
|
542
|
+
* we skip those and only keep the `h1:` lines (source archive checksums).
|
|
543
|
+
*
|
|
544
|
+
* go.mod `require` block format:
|
|
545
|
+
* ```
|
|
546
|
+
* require (
|
|
547
|
+
* github.com/gin-gonic/gin v1.9.1
|
|
548
|
+
* golang.org/x/text v0.14.0 // indirect
|
|
549
|
+
* )
|
|
550
|
+
* ```
|
|
551
|
+
*
|
|
552
|
+
* Dependencies marked `// indirect` are transitive.
|
|
553
|
+
*/
|
|
554
|
+
declare class GoScanner implements DependencyScanner {
|
|
555
|
+
readonly ecosystem: Ecosystem;
|
|
556
|
+
readonly lockfileNames: string[];
|
|
557
|
+
detect(projectPath: string): Promise<string | null>;
|
|
558
|
+
scan(projectPath: string, lockfilePath: string): Promise<ScanResult>;
|
|
559
|
+
/**
|
|
560
|
+
* Parses go.sum and extracts unique module dependencies.
|
|
561
|
+
*
|
|
562
|
+
* Each module may appear twice in go.sum (once for the source archive,
|
|
563
|
+
* once for go.mod). We deduplicate by module path + version, keeping
|
|
564
|
+
* only the `h1:` entry (not the `/go.mod` entry).
|
|
565
|
+
*/
|
|
566
|
+
private parseGoSum;
|
|
567
|
+
/**
|
|
568
|
+
* Parses go.mod to extract direct and indirect dependency names.
|
|
569
|
+
*
|
|
570
|
+
* Handles both single-line and block `require` directives:
|
|
571
|
+
* ```
|
|
572
|
+
* require github.com/pkg/errors v0.9.1
|
|
573
|
+
*
|
|
574
|
+
* require (
|
|
575
|
+
* github.com/gin-gonic/gin v1.9.1
|
|
576
|
+
* golang.org/x/text v0.14.0 // indirect
|
|
577
|
+
* )
|
|
578
|
+
* ```
|
|
579
|
+
*/
|
|
580
|
+
private parseGoMod;
|
|
581
|
+
/**
|
|
582
|
+
* Builds a purl for a Go module.
|
|
583
|
+
*
|
|
584
|
+
* Per purl spec, the type is "golang" and the module path
|
|
585
|
+
* uses `/` separators (no encoding needed for path segments).
|
|
586
|
+
*
|
|
587
|
+
* Example: `pkg:golang/github.com/gin-gonic/gin@v1.9.1`
|
|
588
|
+
*/
|
|
589
|
+
private buildPurl;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Ruby dependency scanner (Bundler).
|
|
594
|
+
*
|
|
595
|
+
* Parses `Gemfile.lock` to extract the full resolved dependency list,
|
|
596
|
+
* and cross-references the `DEPENDENCIES` section to distinguish
|
|
597
|
+
* direct vs transitive gems.
|
|
598
|
+
*
|
|
599
|
+
* Gemfile.lock format:
|
|
600
|
+
* ```
|
|
601
|
+
* GEM
|
|
602
|
+
* remote: https://rubygems.org/
|
|
603
|
+
* specs:
|
|
604
|
+
* actioncable (7.1.2)
|
|
605
|
+
* actionpack (= 7.1.2)
|
|
606
|
+
* activesupport (= 7.1.2)
|
|
607
|
+
* rack (3.0.8)
|
|
608
|
+
*
|
|
609
|
+
* PLATFORMS
|
|
610
|
+
* ruby
|
|
611
|
+
*
|
|
612
|
+
* DEPENDENCIES
|
|
613
|
+
* puma (>= 5.0)
|
|
614
|
+
* rails (~> 7.1.2)
|
|
615
|
+
*
|
|
616
|
+
* BUNDLED WITH
|
|
617
|
+
* 2.5.3
|
|
618
|
+
* ```
|
|
619
|
+
*
|
|
620
|
+
* The `GEM > specs:` section lists all resolved gems with exact versions.
|
|
621
|
+
* The `DEPENDENCIES` section lists direct gems (from the Gemfile).
|
|
622
|
+
*/
|
|
623
|
+
declare class RubyScanner implements DependencyScanner {
|
|
624
|
+
readonly ecosystem: Ecosystem;
|
|
625
|
+
readonly lockfileNames: string[];
|
|
626
|
+
detect(projectPath: string): Promise<string | null>;
|
|
627
|
+
scan(projectPath: string, lockfilePath: string): Promise<ScanResult>;
|
|
628
|
+
/**
|
|
629
|
+
* Parses the GEM > specs section to extract all resolved gems.
|
|
630
|
+
*
|
|
631
|
+
* Gems at the top level of the specs section (indented 4 spaces) are
|
|
632
|
+
* resolved packages. Their sub-dependencies (indented 6+ spaces) are
|
|
633
|
+
* constraints, not separate entries — those sub-deps appear as their
|
|
634
|
+
* own top-level spec entries elsewhere.
|
|
635
|
+
*
|
|
636
|
+
* Format: ` gem-name (1.2.3)`
|
|
637
|
+
*/
|
|
638
|
+
private parseSpecs;
|
|
639
|
+
/**
|
|
640
|
+
* Parses the DEPENDENCIES section to get direct dependency names.
|
|
641
|
+
*
|
|
642
|
+
* Format: ` gem-name (>= 1.0)` or ` gem-name`
|
|
643
|
+
* The version constraint is optional and we only need the name.
|
|
644
|
+
*/
|
|
645
|
+
private parseDependencies;
|
|
646
|
+
}
|
|
647
|
+
|
|
310
648
|
/**
|
|
311
649
|
* Registry of all available dependency scanners.
|
|
312
650
|
* Auto-detects the correct scanner for a given project.
|
|
@@ -472,4 +810,4 @@ declare class ConsoleReporter implements Reporter {
|
|
|
472
810
|
report(result: VerimuReport): string;
|
|
473
811
|
}
|
|
474
812
|
|
|
475
|
-
export { ApiKeyRequiredError, type CiProvider, ConsoleReporter, CveAggregator, type CveCheckResult, CveSourceError, CycloneDxGenerator, type Dependency, type Ecosystem, type GenerateSbomInput, type GenerateSbomResult, LockfileParseError, NoLockfileError, NpmScanner, OsvSource, type Sbom, type SbomDependency, type SbomFormat, type ScanResult, ScannerRegistry, type Severity, type VerimuConfig, VerimuError, type VerimuReport, type Vulnerability, type VulnerabilitySource, generateSbom, printReport, scan, shouldFailCi };
|
|
813
|
+
export { ApiKeyRequiredError, CargoScanner, type CiProvider, ConsoleReporter, CveAggregator, type CveCheckResult, CveSourceError, CycloneDxGenerator, type Dependency, type Ecosystem, type GenerateSbomInput, type GenerateSbomResult, GoScanner, LockfileParseError, MavenScanner, NoLockfileError, NpmScanner, NugetScanner, OsvSource, PipScanner, RubyScanner, type Sbom, type SbomDependency, type SbomFormat, type ScanResult, ScannerRegistry, type Severity, type VerimuConfig, VerimuError, type VerimuReport, type Vulnerability, type VulnerabilitySource, generateSbom, printReport, scan, shouldFailCi };
|