kirograph 0.17.0 → 0.19.0
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/LICENSE +1 -1
- package/README.md +103 -1822
- package/dist/architecture/layers/dart.js +112 -0
- package/dist/architecture/layers/dart.js.map +7 -0
- package/dist/architecture/layers/index.js +3 -1
- package/dist/architecture/layers/index.js.map +2 -2
- package/dist/bin/banner.js +74 -6
- package/dist/bin/banner.js.map +2 -2
- package/dist/bin/commands/attack-surface.js +157 -0
- package/dist/bin/commands/attack-surface.js.map +7 -0
- package/dist/bin/commands/benchmark.js +206 -0
- package/dist/bin/commands/benchmark.js.map +7 -0
- package/dist/bin/commands/budget.js +70 -0
- package/dist/bin/commands/budget.js.map +7 -0
- package/dist/bin/commands/communities.js +77 -0
- package/dist/bin/commands/communities.js.map +7 -0
- package/dist/bin/commands/dep-confusion.js +119 -0
- package/dist/bin/commands/dep-confusion.js.map +7 -0
- package/dist/bin/commands/export.js +304 -10
- package/dist/bin/commands/export.js.map +2 -2
- package/dist/bin/commands/flows.js +97 -0
- package/dist/bin/commands/flows.js.map +7 -0
- package/dist/bin/commands/help.js +382 -101
- package/dist/bin/commands/help.js.map +2 -2
- package/dist/bin/commands/install.js +90 -8
- package/dist/bin/commands/install.js.map +2 -2
- package/dist/bin/commands/licenses.js +201 -0
- package/dist/bin/commands/licenses.js.map +7 -0
- package/dist/bin/commands/reachability.js +160 -0
- package/dist/bin/commands/reachability.js.map +7 -0
- package/dist/bin/commands/read.js +100 -0
- package/dist/bin/commands/read.js.map +7 -0
- package/dist/bin/commands/refactor.js +116 -0
- package/dist/bin/commands/refactor.js.map +7 -0
- package/dist/bin/commands/remediation.js +133 -0
- package/dist/bin/commands/remediation.js.map +7 -0
- package/dist/bin/commands/sbom.js +76 -0
- package/dist/bin/commands/sbom.js.map +7 -0
- package/dist/bin/commands/security-ci-report.js +267 -0
- package/dist/bin/commands/security-ci-report.js.map +7 -0
- package/dist/bin/commands/security-export.js +1349 -0
- package/dist/bin/commands/security-export.js.map +7 -0
- package/dist/bin/commands/security-flows.js +126 -0
- package/dist/bin/commands/security-flows.js.map +7 -0
- package/dist/bin/commands/security-secrets.js +170 -0
- package/dist/bin/commands/security-secrets.js.map +7 -0
- package/dist/bin/commands/security.js +193 -0
- package/dist/bin/commands/security.js.map +7 -0
- package/dist/bin/commands/staleness.js +144 -0
- package/dist/bin/commands/staleness.js.map +7 -0
- package/dist/bin/commands/status.js +102 -2
- package/dist/bin/commands/status.js.map +2 -2
- package/dist/bin/commands/supply-chain.js +138 -0
- package/dist/bin/commands/supply-chain.js.map +7 -0
- package/dist/bin/commands/uninit.js +109 -60
- package/dist/bin/commands/uninit.js.map +2 -2
- package/dist/bin/commands/vex.js +76 -0
- package/dist/bin/commands/vex.js.map +7 -0
- package/dist/bin/commands/vuln-suppress.js +95 -0
- package/dist/bin/commands/vuln-suppress.js.map +7 -0
- package/dist/bin/commands/vulns.js +382 -0
- package/dist/bin/commands/vulns.js.map +7 -0
- package/dist/bin/installer/auto-detect.js +125 -0
- package/dist/bin/installer/auto-detect.js.map +7 -0
- package/dist/bin/installer/cli-agent.js +28 -5
- package/dist/bin/installer/cli-agent.js.map +2 -2
- package/dist/bin/installer/common.js +47 -0
- package/dist/bin/installer/common.js.map +2 -2
- package/dist/bin/installer/config-prompt.js +12 -1
- package/dist/bin/installer/config-prompt.js.map +2 -2
- package/dist/bin/installer/detect.js +309 -0
- package/dist/bin/installer/detect.js.map +7 -0
- package/dist/bin/installer/index.js +9 -1
- package/dist/bin/installer/index.js.map +2 -2
- package/dist/bin/installer/instructions.js +195 -3
- package/dist/bin/installer/instructions.js.map +2 -2
- package/dist/bin/installer/steering.js +407 -0
- package/dist/bin/installer/steering.js.map +2 -2
- package/dist/bin/installer/targets/aider.js +3 -3
- package/dist/bin/installer/targets/aider.js.map +2 -2
- package/dist/bin/installer/targets/amp.js +3 -3
- package/dist/bin/installer/targets/amp.js.map +2 -2
- package/dist/bin/installer/targets/antigravity.js +35 -6
- package/dist/bin/installer/targets/antigravity.js.map +2 -2
- package/dist/bin/installer/targets/augment.js +3 -3
- package/dist/bin/installer/targets/augment.js.map +2 -2
- package/dist/bin/installer/targets/claude.js +49 -5
- package/dist/bin/installer/targets/claude.js.map +2 -2
- package/dist/bin/installer/targets/cline.js +32 -6
- package/dist/bin/installer/targets/cline.js.map +2 -2
- package/dist/bin/installer/targets/codex.js +64 -12
- package/dist/bin/installer/targets/codex.js.map +2 -2
- package/dist/bin/installer/targets/continue.js +2 -2
- package/dist/bin/installer/targets/continue.js.map +2 -2
- package/dist/bin/installer/targets/copilot-cli.js +101 -0
- package/dist/bin/installer/targets/copilot-cli.js.map +7 -0
- package/dist/bin/installer/targets/copilot.js +31 -5
- package/dist/bin/installer/targets/copilot.js.map +2 -2
- package/dist/bin/installer/targets/cursor.js +4 -4
- package/dist/bin/installer/targets/cursor.js.map +2 -2
- package/dist/bin/installer/targets/devin.js +2 -2
- package/dist/bin/installer/targets/devin.js.map +2 -2
- package/dist/bin/installer/targets/gemini-cli.js +2 -2
- package/dist/bin/installer/targets/gemini-cli.js.map +2 -2
- package/dist/bin/installer/targets/generic.js +2 -14
- package/dist/bin/installer/targets/generic.js.map +2 -2
- package/dist/bin/installer/targets/goose.js +3 -3
- package/dist/bin/installer/targets/goose.js.map +2 -2
- package/dist/bin/installer/targets/index.js +250 -0
- package/dist/bin/installer/targets/index.js.map +2 -2
- package/dist/bin/installer/targets/junie.js +2 -2
- package/dist/bin/installer/targets/junie.js.map +2 -2
- package/dist/bin/installer/targets/kilo.js +2 -2
- package/dist/bin/installer/targets/kilo.js.map +2 -2
- package/dist/bin/installer/targets/kiro.js +3 -3
- package/dist/bin/installer/targets/kiro.js.map +2 -2
- package/dist/bin/installer/targets/opencode.js +2 -2
- package/dist/bin/installer/targets/opencode.js.map +2 -2
- package/dist/bin/installer/targets/openhands.js +3 -3
- package/dist/bin/installer/targets/openhands.js.map +2 -2
- package/dist/bin/installer/targets/qoder.js +91 -0
- package/dist/bin/installer/targets/qoder.js.map +7 -0
- package/dist/bin/installer/targets/qwen.js +96 -0
- package/dist/bin/installer/targets/qwen.js.map +7 -0
- package/dist/bin/installer/targets/replit.js +3 -3
- package/dist/bin/installer/targets/replit.js.map +2 -2
- package/dist/bin/installer/targets/roo.js +2 -2
- package/dist/bin/installer/targets/roo.js.map +2 -2
- package/dist/bin/installer/targets/tabnine.js +3 -3
- package/dist/bin/installer/targets/tabnine.js.map +2 -2
- package/dist/bin/installer/targets/trae.js +5 -5
- package/dist/bin/installer/targets/trae.js.map +2 -2
- package/dist/bin/installer/targets/warp.js +2 -2
- package/dist/bin/installer/targets/warp.js.map +2 -2
- package/dist/bin/installer/targets/windsurf.js +35 -6
- package/dist/bin/installer/targets/windsurf.js.map +2 -2
- package/dist/bin/kirograph.js +72 -6
- package/dist/bin/kirograph.js.map +3 -3
- package/dist/compression/tracker.js +80 -0
- package/dist/compression/tracker.js.map +2 -2
- package/dist/config.js +90 -3
- package/dist/config.js.map +2 -2
- package/dist/core/pipeline.js +36 -2
- package/dist/core/pipeline.js.map +2 -2
- package/dist/db/database.js +56 -5
- package/dist/db/database.js.map +2 -2
- package/dist/db/memory-schema.sql +5 -1
- package/dist/db/schema.sql +3 -1
- package/dist/db/security-schema.sql +72 -0
- package/dist/extraction/extractor.js +81 -0
- package/dist/extraction/extractor.js.map +2 -2
- package/dist/extraction/grammars.js +32 -8
- package/dist/extraction/grammars.js.map +2 -2
- package/dist/extraction/languages.js +43 -1
- package/dist/extraction/languages.js.map +2 -2
- package/dist/extraction/notebook.js +300 -0
- package/dist/extraction/notebook.js.map +7 -0
- package/dist/extraction/wasm/tree-sitter-astro.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-gdscript.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-julia.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-nix.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-perl.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-powershell.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-r.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-sql.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-verilog.wasm +0 -0
- package/dist/frameworks/flutter.js +130 -0
- package/dist/frameworks/flutter.js.map +7 -0
- package/dist/frameworks/index.js +7 -1
- package/dist/frameworks/index.js.map +3 -3
- package/dist/graph/communities.js +317 -0
- package/dist/graph/communities.js.map +7 -0
- package/dist/graph/flows.js +138 -0
- package/dist/graph/flows.js.map +7 -0
- package/dist/graph/refactor.js +155 -0
- package/dist/graph/refactor.js.map +7 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +2 -2
- package/dist/mcp/cache.js +172 -0
- package/dist/mcp/cache.js.map +7 -0
- package/dist/mcp/read-modes.js +295 -0
- package/dist/mcp/read-modes.js.map +7 -0
- package/dist/mcp/server.js +2 -1
- package/dist/mcp/server.js.map +2 -2
- package/dist/mcp/tool-names.js +21 -1
- package/dist/mcp/tool-names.js.map +2 -2
- package/dist/mcp/tools.js +1160 -1
- package/dist/mcp/tools.js.map +3 -3
- package/dist/memory/database.js +32 -2
- package/dist/memory/database.js.map +2 -2
- package/dist/memory/types.js.map +1 -1
- package/dist/resolution/bridges/android-rn.js +298 -0
- package/dist/resolution/bridges/android-rn.js.map +7 -0
- package/dist/resolution/bridges/expo-modules.js +155 -0
- package/dist/resolution/bridges/expo-modules.js.map +7 -0
- package/dist/resolution/bridges/flutter-channel.js +385 -0
- package/dist/resolution/bridges/flutter-channel.js.map +7 -0
- package/dist/resolution/bridges/index.js +80 -0
- package/dist/resolution/bridges/index.js.map +7 -0
- package/dist/resolution/bridges/native-events.js +188 -0
- package/dist/resolution/bridges/native-events.js.map +7 -0
- package/dist/resolution/bridges/native-views.js +244 -0
- package/dist/resolution/bridges/native-views.js.map +7 -0
- package/dist/resolution/bridges/react-native.js +161 -0
- package/dist/resolution/bridges/react-native.js.map +7 -0
- package/dist/resolution/bridges/swift-objc.js +227 -0
- package/dist/resolution/bridges/swift-objc.js.map +7 -0
- package/dist/resolution/bridges/turbomodules.js +216 -0
- package/dist/resolution/bridges/turbomodules.js.map +7 -0
- package/dist/resolution/index.js +61 -2
- package/dist/resolution/index.js.map +2 -2
- package/dist/security/attack-surface.js +164 -0
- package/dist/security/attack-surface.js.map +7 -0
- package/dist/security/context-warnings.js +123 -0
- package/dist/security/context-warnings.js.map +7 -0
- package/dist/security/context-warnings.test.js +300 -0
- package/dist/security/context-warnings.test.js.map +7 -0
- package/dist/security/data-flows.js +228 -0
- package/dist/security/data-flows.js.map +7 -0
- package/dist/security/dep-confusion.js +255 -0
- package/dist/security/dep-confusion.js.map +7 -0
- package/dist/security/errors.js +51 -0
- package/dist/security/errors.js.map +7 -0
- package/dist/security/export/fix-suggestions.js +58 -0
- package/dist/security/export/fix-suggestions.js.map +7 -0
- package/dist/security/export/fix-suggestions.test.js +74 -0
- package/dist/security/export/fix-suggestions.test.js.map +7 -0
- package/dist/security/export/sbom.js +230 -0
- package/dist/security/export/sbom.js.map +7 -0
- package/dist/security/export/sbom.test.js +288 -0
- package/dist/security/export/sbom.test.js.map +7 -0
- package/dist/security/export/serialization.js +142 -0
- package/dist/security/export/serialization.js.map +7 -0
- package/dist/security/export/serialization.test.js +310 -0
- package/dist/security/export/serialization.test.js.map +7 -0
- package/dist/security/export/vex.js +220 -0
- package/dist/security/export/vex.js.map +7 -0
- package/dist/security/export/vex.test.js +278 -0
- package/dist/security/export/vex.test.js.map +7 -0
- package/dist/security/index.js +67 -0
- package/dist/security/index.js.map +7 -0
- package/dist/security/integrator-transitives.test.js +359 -0
- package/dist/security/integrator-transitives.test.js.map +7 -0
- package/dist/security/integrator.js +491 -0
- package/dist/security/integrator.js.map +7 -0
- package/dist/security/integrator.test.js +237 -0
- package/dist/security/integrator.test.js.map +7 -0
- package/dist/security/license.js +70 -0
- package/dist/security/license.js.map +7 -0
- package/dist/security/manifest/adapter.js +243 -0
- package/dist/security/manifest/adapter.js.map +7 -0
- package/dist/security/manifest/adapter.test.js +272 -0
- package/dist/security/manifest/adapter.test.js.map +7 -0
- package/dist/security/manifest/parser.js +376 -0
- package/dist/security/manifest/parser.js.map +7 -0
- package/dist/security/manifest/parser.test.js +110 -0
- package/dist/security/manifest/parser.test.js.map +7 -0
- package/dist/security/manifest/plugins/cargo.js +233 -0
- package/dist/security/manifest/plugins/cargo.js.map +7 -0
- package/dist/security/manifest/plugins/cargo.test.js +304 -0
- package/dist/security/manifest/plugins/cargo.test.js.map +7 -0
- package/dist/security/manifest/plugins/composer.js +152 -0
- package/dist/security/manifest/plugins/composer.js.map +7 -0
- package/dist/security/manifest/plugins/go.js +146 -0
- package/dist/security/manifest/plugins/go.js.map +7 -0
- package/dist/security/manifest/plugins/go.test.js +341 -0
- package/dist/security/manifest/plugins/go.test.js.map +7 -0
- package/dist/security/manifest/plugins/gradle.js +159 -0
- package/dist/security/manifest/plugins/gradle.js.map +7 -0
- package/dist/security/manifest/plugins/hex.js +159 -0
- package/dist/security/manifest/plugins/hex.js.map +7 -0
- package/dist/security/manifest/plugins/maven.js +128 -0
- package/dist/security/manifest/plugins/maven.js.map +7 -0
- package/dist/security/manifest/plugins/maven.test.js +389 -0
- package/dist/security/manifest/plugins/maven.test.js.map +7 -0
- package/dist/security/manifest/plugins/npm.js +284 -0
- package/dist/security/manifest/plugins/npm.js.map +7 -0
- package/dist/security/manifest/plugins/npm.test.js +298 -0
- package/dist/security/manifest/plugins/npm.test.js.map +7 -0
- package/dist/security/manifest/plugins/nuget.js +186 -0
- package/dist/security/manifest/plugins/nuget.js.map +7 -0
- package/dist/security/manifest/plugins/pip.js +123 -0
- package/dist/security/manifest/plugins/pip.js.map +7 -0
- package/dist/security/manifest/plugins/pip.test.js +208 -0
- package/dist/security/manifest/plugins/pip.test.js.map +7 -0
- package/dist/security/manifest/plugins/pubspec.js +212 -0
- package/dist/security/manifest/plugins/pubspec.js.map +7 -0
- package/dist/security/manifest/plugins/pyproject.js +261 -0
- package/dist/security/manifest/plugins/pyproject.js.map +7 -0
- package/dist/security/manifest/plugins/rubygems.js +185 -0
- package/dist/security/manifest/plugins/rubygems.js.map +7 -0
- package/dist/security/manifest/plugins/swift.js +200 -0
- package/dist/security/manifest/plugins/swift.js.map +7 -0
- package/dist/security/owasp.js +104 -0
- package/dist/security/owasp.js.map +7 -0
- package/dist/security/pipeline.js +125 -0
- package/dist/security/pipeline.js.map +7 -0
- package/dist/security/reachability.js +276 -0
- package/dist/security/reachability.js.map +7 -0
- package/dist/security/reachability.test.js +394 -0
- package/dist/security/reachability.test.js.map +7 -0
- package/dist/security/remediation.js +126 -0
- package/dist/security/remediation.js.map +7 -0
- package/dist/security/secrets.js +176 -0
- package/dist/security/secrets.js.map +7 -0
- package/dist/security/staleness.js +231 -0
- package/dist/security/staleness.js.map +7 -0
- package/dist/security/supply-chain.js +301 -0
- package/dist/security/supply-chain.js.map +7 -0
- package/dist/security/suppressions.js +106 -0
- package/dist/security/suppressions.js.map +7 -0
- package/dist/security/types.js +17 -0
- package/dist/security/types.js.map +7 -0
- package/dist/security/vuln/client.js +355 -0
- package/dist/security/vuln/client.js.map +7 -0
- package/dist/security/vuln/client.test.js +288 -0
- package/dist/security/vuln/client.test.js.map +7 -0
- package/dist/security/vuln/epss-client.js +95 -0
- package/dist/security/vuln/epss-client.js.map +7 -0
- package/dist/security/vuln/index.js +29 -0
- package/dist/security/vuln/index.js.map +7 -0
- package/dist/security/vuln/osv-adapter.js +321 -0
- package/dist/security/vuln/osv-adapter.js.map +7 -0
- package/dist/security/vuln/osv-adapter.test.js +391 -0
- package/dist/security/vuln/osv-adapter.test.js.map +7 -0
- package/dist/security/vuln/types.js +17 -0
- package/dist/security/vuln/types.js.map +7 -0
- package/dist/types.js.map +2 -2
- package/package.json +2 -1
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var composer_exports = {};
|
|
30
|
+
__export(composer_exports, {
|
|
31
|
+
parseComposerManifest: () => parseComposerManifest
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(composer_exports);
|
|
34
|
+
var fs = __toESM(require("fs"));
|
|
35
|
+
var path = __toESM(require("path"));
|
|
36
|
+
var import_errors = require("../../../errors");
|
|
37
|
+
async function parseComposerManifest(manifestPath, projectRoot) {
|
|
38
|
+
const manifestDir = path.dirname(manifestPath);
|
|
39
|
+
const relativeManifest = path.relative(projectRoot, manifestPath).replace(/\\/g, "/");
|
|
40
|
+
let content;
|
|
41
|
+
try {
|
|
42
|
+
content = fs.readFileSync(manifestPath, "utf8");
|
|
43
|
+
} catch (err) {
|
|
44
|
+
(0, import_errors.logWarn)(`[sec:composer] Failed to read ${relativeManifest}: ${err instanceof Error ? err.message : String(err)}`);
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
let manifest;
|
|
48
|
+
try {
|
|
49
|
+
manifest = JSON.parse(content);
|
|
50
|
+
} catch (err) {
|
|
51
|
+
(0, import_errors.logWarn)(`[sec:composer] Failed to parse JSON in ${relativeManifest}: ${err instanceof Error ? err.message : String(err)}`);
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
const resolvedVersions = loadResolvedVersions(manifestDir);
|
|
55
|
+
const license = extractComposerLicense(manifest);
|
|
56
|
+
const dependencies = [];
|
|
57
|
+
const sections = [
|
|
58
|
+
{ key: "require", scope: "production" },
|
|
59
|
+
{ key: "require-dev", scope: "development" }
|
|
60
|
+
];
|
|
61
|
+
for (const { key, scope } of sections) {
|
|
62
|
+
const section = manifest[key];
|
|
63
|
+
if (!section || typeof section !== "object" || Array.isArray(section)) continue;
|
|
64
|
+
for (const [pkgName, versionConstraint] of Object.entries(section)) {
|
|
65
|
+
if (shouldSkipEntry(pkgName)) continue;
|
|
66
|
+
if (typeof versionConstraint !== "string") {
|
|
67
|
+
(0, import_errors.logWarn)(`[sec:composer] Non-string version for "${pkgName}" in ${relativeManifest} \u2014 skipping`);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (!isValidPackageName(pkgName)) {
|
|
71
|
+
(0, import_errors.logWarn)(`[sec:composer] Invalid package name "${pkgName}" in ${relativeManifest} \u2014 skipping`);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const resolvedVersion = resolvedVersions.get(pkgName.toLowerCase());
|
|
75
|
+
dependencies.push({
|
|
76
|
+
name: pkgName,
|
|
77
|
+
declaredConstraint: versionConstraint,
|
|
78
|
+
resolvedVersion,
|
|
79
|
+
scope,
|
|
80
|
+
ecosystem: "composer",
|
|
81
|
+
sourceManifest: relativeManifest,
|
|
82
|
+
...license !== void 0 ? { license } : {}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return dependencies;
|
|
87
|
+
}
|
|
88
|
+
function shouldSkipEntry(name) {
|
|
89
|
+
if (name === "php") return true;
|
|
90
|
+
if (name.startsWith("ext-")) return true;
|
|
91
|
+
if (name === "platform") return true;
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
function isValidPackageName(name) {
|
|
95
|
+
if (!name || typeof name !== "string") return false;
|
|
96
|
+
if (name.length > 255) return false;
|
|
97
|
+
return /^[a-z0-9]([a-z0-9_.-]*\/[a-z0-9][a-z0-9_.-]*)$/.test(name);
|
|
98
|
+
}
|
|
99
|
+
function loadResolvedVersions(manifestDir) {
|
|
100
|
+
const map = /* @__PURE__ */ new Map();
|
|
101
|
+
const lockPath = path.join(manifestDir, "composer.lock");
|
|
102
|
+
if (!fs.existsSync(lockPath)) {
|
|
103
|
+
return map;
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
const lockContent = fs.readFileSync(lockPath, "utf8");
|
|
107
|
+
extractFromComposerLock(lockContent, map);
|
|
108
|
+
} catch (err) {
|
|
109
|
+
(0, import_errors.logWarn)(`[sec:composer] Failed to parse composer.lock: ${err instanceof Error ? err.message : String(err)}`);
|
|
110
|
+
}
|
|
111
|
+
return map;
|
|
112
|
+
}
|
|
113
|
+
function extractFromComposerLock(content, map) {
|
|
114
|
+
let lockData;
|
|
115
|
+
try {
|
|
116
|
+
lockData = JSON.parse(content);
|
|
117
|
+
} catch {
|
|
118
|
+
(0, import_errors.logWarn)("[sec:composer] composer.lock is not valid JSON \u2014 resolved versions unavailable");
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const arrays = [lockData["packages"], lockData["packages-dev"]];
|
|
122
|
+
for (const arr of arrays) {
|
|
123
|
+
if (!Array.isArray(arr)) continue;
|
|
124
|
+
for (const entry of arr) {
|
|
125
|
+
if (!entry || typeof entry !== "object") continue;
|
|
126
|
+
const pkg = entry;
|
|
127
|
+
const name = typeof pkg["name"] === "string" ? pkg["name"].toLowerCase() : null;
|
|
128
|
+
const version = typeof pkg["version"] === "string" ? pkg["version"] : null;
|
|
129
|
+
if (name && version) {
|
|
130
|
+
const normalised = version.startsWith("v") ? version.slice(1) : version;
|
|
131
|
+
if (!map.has(name)) {
|
|
132
|
+
map.set(name, normalised);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function extractComposerLicense(manifest) {
|
|
139
|
+
const raw = manifest["license"];
|
|
140
|
+
if (typeof raw === "string" && raw.trim() !== "") {
|
|
141
|
+
return raw.trim();
|
|
142
|
+
}
|
|
143
|
+
if (Array.isArray(raw) && raw.length > 0 && typeof raw[0] === "string") {
|
|
144
|
+
return raw.join(" OR ");
|
|
145
|
+
}
|
|
146
|
+
return void 0;
|
|
147
|
+
}
|
|
148
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
149
|
+
0 && (module.exports = {
|
|
150
|
+
parseComposerManifest
|
|
151
|
+
});
|
|
152
|
+
//# sourceMappingURL=composer.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/security/manifest/plugins/composer.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Composer Version Extraction Plugin for KiroGraph-Sec\n *\n * Parses composer.json manifests to extract PHP package declarations with\n * version constraints, scopes, and resolved versions from composer.lock.\n *\n * Handles:\n * - `require` section \u2192 'production' scope\n * - `require-dev` section \u2192 'development' scope\n * - Skips `php`, `ext-*`, and `platform` entries (not installable packages)\n */\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { ParsedDependency } from '../../types';\nimport { logWarn } from '../../../errors';\n\n/**\n * Resolved version map: package name \u2192 resolved version string.\n * Built from composer.lock.\n */\ntype ResolvedVersionMap = Map<string, string>;\n\n/**\n * Parse a composer.json manifest and extract package declarations with\n * version constraints, scopes, and resolved versions from composer.lock.\n *\n * @param manifestPath - Absolute path to the composer.json file\n * @param projectRoot - Absolute path to the project root directory\n * @returns Array of parsed dependencies with version and scope information\n */\nexport async function parseComposerManifest(\n manifestPath: string,\n projectRoot: string,\n): Promise<ParsedDependency[]> {\n const manifestDir = path.dirname(manifestPath);\n const relativeManifest = path.relative(projectRoot, manifestPath).replace(/\\\\/g, '/');\n\n // Read the composer.json content\n let content: string;\n try {\n content = fs.readFileSync(manifestPath, 'utf8');\n } catch (err) {\n logWarn(`[sec:composer] Failed to read ${relativeManifest}: ${err instanceof Error ? err.message : String(err)}`);\n return [];\n }\n\n // Parse JSON\n let manifest: Record<string, unknown>;\n try {\n manifest = JSON.parse(content) as Record<string, unknown>;\n } catch (err) {\n logWarn(`[sec:composer] Failed to parse JSON in ${relativeManifest}: ${err instanceof Error ? err.message : String(err)}`);\n return [];\n }\n\n // Attempt to load resolved versions from composer.lock\n const resolvedVersions = loadResolvedVersions(manifestDir);\n\n // Extract the project-level license\n const license = extractComposerLicense(manifest);\n\n const dependencies: ParsedDependency[] = [];\n\n // Process `require` (production) and `require-dev` (development) sections\n const sections: Array<{ key: string; scope: ParsedDependency['scope'] }> = [\n { key: 'require', scope: 'production' },\n { key: 'require-dev', scope: 'development' },\n ];\n\n for (const { key, scope } of sections) {\n const section = manifest[key];\n if (!section || typeof section !== 'object' || Array.isArray(section)) continue;\n\n for (const [pkgName, versionConstraint] of Object.entries(section as Record<string, unknown>)) {\n // Skip PHP runtime and extensions\n if (shouldSkipEntry(pkgName)) continue;\n\n if (typeof versionConstraint !== 'string') {\n logWarn(`[sec:composer] Non-string version for \"${pkgName}\" in ${relativeManifest} \u2014 skipping`);\n continue;\n }\n\n if (!isValidPackageName(pkgName)) {\n logWarn(`[sec:composer] Invalid package name \"${pkgName}\" in ${relativeManifest} \u2014 skipping`);\n continue;\n }\n\n const resolvedVersion = resolvedVersions.get(pkgName.toLowerCase());\n dependencies.push({\n name: pkgName,\n declaredConstraint: versionConstraint,\n resolvedVersion,\n scope,\n ecosystem: 'composer',\n sourceManifest: relativeManifest,\n ...(license !== undefined ? { license } : {}),\n });\n }\n }\n\n return dependencies;\n}\n\n/**\n * Determine whether a composer.json key should be skipped.\n * Skips `php`, `ext-*`, and `platform` entries.\n */\nfunction shouldSkipEntry(name: string): boolean {\n if (name === 'php') return true;\n if (name.startsWith('ext-')) return true;\n if (name === 'platform') return true;\n return false;\n}\n\n/**\n * Validate that a Composer package name follows the `vendor/package` convention.\n * Also accepts bare names for legacy packages, but rejects obviously invalid entries.\n */\nfunction isValidPackageName(name: string): boolean {\n if (!name || typeof name !== 'string') return false;\n if (name.length > 255) return false;\n // Composer names must be vendor/package (lowercase, hyphens, digits allowed)\n return /^[a-z0-9]([a-z0-9_.-]*\\/[a-z0-9][a-z0-9_.-]*)$/.test(name);\n}\n\n/**\n * Attempt to load resolved versions from composer.lock in the given directory.\n * Returns an empty map if composer.lock is not available.\n *\n * composer.lock format (JSON):\n * ```json\n * {\n * \"packages\": [{ \"name\": \"vendor/package\", \"version\": \"1.2.3\" }],\n * \"packages-dev\": [{ \"name\": \"vendor/dev-package\", \"version\": \"v2.0.0\" }]\n * }\n * ```\n * Version strings may be prefixed with `v` \u2014 these are stripped.\n */\nfunction loadResolvedVersions(manifestDir: string): ResolvedVersionMap {\n const map: ResolvedVersionMap = new Map();\n\n const lockPath = path.join(manifestDir, 'composer.lock');\n if (!fs.existsSync(lockPath)) {\n return map;\n }\n\n try {\n const lockContent = fs.readFileSync(lockPath, 'utf8');\n extractFromComposerLock(lockContent, map);\n } catch (err) {\n logWarn(`[sec:composer] Failed to parse composer.lock: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n return map;\n}\n\n/**\n * Extract resolved versions from composer.lock content.\n *\n * Reads both `packages` (production) and `packages-dev` arrays.\n * Normalises version strings by stripping a leading `v`.\n */\nfunction extractFromComposerLock(content: string, map: ResolvedVersionMap): void {\n let lockData: Record<string, unknown>;\n try {\n lockData = JSON.parse(content) as Record<string, unknown>;\n } catch {\n logWarn('[sec:composer] composer.lock is not valid JSON \u2014 resolved versions unavailable');\n return;\n }\n\n const arrays = [lockData['packages'], lockData['packages-dev']];\n for (const arr of arrays) {\n if (!Array.isArray(arr)) continue;\n for (const entry of arr) {\n if (!entry || typeof entry !== 'object') continue;\n const pkg = entry as Record<string, unknown>;\n const name = typeof pkg['name'] === 'string' ? pkg['name'].toLowerCase() : null;\n const version = typeof pkg['version'] === 'string' ? pkg['version'] : null;\n if (name && version) {\n // Strip leading `v` from version strings (e.g. \"v1.2.3\" \u2192 \"1.2.3\")\n const normalised = version.startsWith('v') ? version.slice(1) : version;\n if (!map.has(name)) {\n map.set(name, normalised);\n }\n }\n }\n }\n}\n\n/**\n * Extract the license field from a parsed composer.json manifest.\n * The \"license\" field can be a string or an array of strings (SPDX).\n */\nfunction extractComposerLicense(manifest: Record<string, unknown>): string | undefined {\n const raw = manifest['license'];\n if (typeof raw === 'string' && raw.trim() !== '') {\n return raw.trim();\n }\n if (Array.isArray(raw) && raw.length > 0 && typeof raw[0] === 'string') {\n return (raw as string[]).join(' OR ');\n }\n return undefined;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var go_exports = {};
|
|
30
|
+
__export(go_exports, {
|
|
31
|
+
parseGoManifest: () => parseGoManifest
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(go_exports);
|
|
34
|
+
var fs = __toESM(require("fs"));
|
|
35
|
+
var path = __toESM(require("path"));
|
|
36
|
+
var import_errors = require("../../../errors");
|
|
37
|
+
async function parseGoManifest(manifestPath, projectRoot) {
|
|
38
|
+
const manifestDir = path.dirname(manifestPath);
|
|
39
|
+
const relativeManifest = path.relative(projectRoot, manifestPath).replace(/\\/g, "/");
|
|
40
|
+
let content;
|
|
41
|
+
try {
|
|
42
|
+
content = fs.readFileSync(manifestPath, "utf8");
|
|
43
|
+
} catch (err) {
|
|
44
|
+
(0, import_errors.logWarn)(`[sec:go] Failed to read ${relativeManifest}: ${err instanceof Error ? err.message : String(err)}`);
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
const goSumHashes = loadGoSumHashes(manifestDir);
|
|
48
|
+
const dependencies = [];
|
|
49
|
+
const requireBlockRegex = /require\s*\(([^)]*)\)/gs;
|
|
50
|
+
let blockMatch;
|
|
51
|
+
while ((blockMatch = requireBlockRegex.exec(content)) !== null) {
|
|
52
|
+
const blockContent = blockMatch[1];
|
|
53
|
+
parseRequireLines(blockContent, relativeManifest, goSumHashes, dependencies);
|
|
54
|
+
}
|
|
55
|
+
const lines = content.split("\n");
|
|
56
|
+
for (const line of lines) {
|
|
57
|
+
const trimmed = line.trim();
|
|
58
|
+
const singleRequireMatch = trimmed.match(/^require\s+(\S+)\s+(\S+)/);
|
|
59
|
+
if (singleRequireMatch) {
|
|
60
|
+
const modulePath = singleRequireMatch[1];
|
|
61
|
+
const version = singleRequireMatch[2];
|
|
62
|
+
addDependency(modulePath, version, relativeManifest, goSumHashes, dependencies);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return dependencies;
|
|
66
|
+
}
|
|
67
|
+
function parseRequireLines(blockContent, relativeManifest, goSumHashes, dependencies) {
|
|
68
|
+
const lines = blockContent.split("\n");
|
|
69
|
+
for (const line of lines) {
|
|
70
|
+
const trimmed = line.trim();
|
|
71
|
+
if (!trimmed || trimmed.startsWith("//")) continue;
|
|
72
|
+
const match = trimmed.match(/^(\S+)\s+(\S+)/);
|
|
73
|
+
if (match) {
|
|
74
|
+
const modulePath = match[1];
|
|
75
|
+
const version = match[2];
|
|
76
|
+
if (modulePath.startsWith("//")) continue;
|
|
77
|
+
addDependency(modulePath, version, relativeManifest, goSumHashes, dependencies);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function addDependency(modulePath, version, relativeManifest, goSumHashes, dependencies) {
|
|
82
|
+
if (!isValidGoModulePath(modulePath)) {
|
|
83
|
+
(0, import_errors.logWarn)(`[sec:go] Invalid module path "${modulePath}" in ${relativeManifest} \u2014 skipping`);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (!isValidGoVersion(version)) {
|
|
87
|
+
(0, import_errors.logWarn)(`[sec:go] Invalid version "${version}" for module "${modulePath}" in ${relativeManifest} \u2014 skipping`);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const hasIntegrity = goSumHashes.has(`${modulePath}@${version}`);
|
|
91
|
+
dependencies.push({
|
|
92
|
+
name: modulePath,
|
|
93
|
+
declaredConstraint: version,
|
|
94
|
+
resolvedVersion: version,
|
|
95
|
+
scope: "production",
|
|
96
|
+
// Go doesn't have dev dependencies in go.mod
|
|
97
|
+
ecosystem: "go",
|
|
98
|
+
sourceManifest: relativeManifest
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
function loadGoSumHashes(manifestDir) {
|
|
102
|
+
const map = /* @__PURE__ */ new Map();
|
|
103
|
+
const goSumPath = path.join(manifestDir, "go.sum");
|
|
104
|
+
if (!fs.existsSync(goSumPath)) {
|
|
105
|
+
return map;
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
const content = fs.readFileSync(goSumPath, "utf8");
|
|
109
|
+
const lines = content.split("\n");
|
|
110
|
+
for (const line of lines) {
|
|
111
|
+
const trimmed = line.trim();
|
|
112
|
+
if (!trimmed) continue;
|
|
113
|
+
const parts = trimmed.split(/\s+/);
|
|
114
|
+
if (parts.length >= 3) {
|
|
115
|
+
const modulePath = parts[0];
|
|
116
|
+
let version = parts[1];
|
|
117
|
+
version = version.replace(/\/go\.mod$/, "");
|
|
118
|
+
map.set(`${modulePath}@${version}`, true);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
} catch (err) {
|
|
122
|
+
(0, import_errors.logWarn)(`[sec:go] Failed to read go.sum: ${err instanceof Error ? err.message : String(err)}`);
|
|
123
|
+
}
|
|
124
|
+
return map;
|
|
125
|
+
}
|
|
126
|
+
function isValidGoModulePath(modulePath) {
|
|
127
|
+
if (!modulePath || typeof modulePath !== "string") return false;
|
|
128
|
+
if (modulePath.includes(" ") || modulePath.includes(" ")) return false;
|
|
129
|
+
const firstSlash = modulePath.indexOf("/");
|
|
130
|
+
const firstElement = firstSlash === -1 ? modulePath : modulePath.slice(0, firstSlash);
|
|
131
|
+
if (!firstElement.includes(".")) return false;
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
function isValidGoVersion(version) {
|
|
135
|
+
if (!version || typeof version !== "string") return false;
|
|
136
|
+
if (!version.startsWith("v")) return false;
|
|
137
|
+
const versionBody = version.slice(1);
|
|
138
|
+
if (!versionBody) return false;
|
|
139
|
+
const semverPattern = /^\d+\.\d+\.\d+/;
|
|
140
|
+
return semverPattern.test(versionBody);
|
|
141
|
+
}
|
|
142
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
143
|
+
0 && (module.exports = {
|
|
144
|
+
parseGoManifest
|
|
145
|
+
});
|
|
146
|
+
//# sourceMappingURL=go.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/security/manifest/plugins/go.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Go Version Extraction Plugin for KiroGraph-Sec\n *\n * Extends the existing architecture go parser to extract version constraints\n * and resolved versions from go.mod and go.sum for security analysis.\n *\n * Reuses `goParser` from `src/architecture/manifest/go.ts` for discovery and\n * basic parsing, then layers on version extraction.\n *\n * In Go modules, the version in go.mod IS the resolved version (go.mod is\n * effectively a lock file). go.sum provides integrity hashes but the version\n * source of truth is go.mod itself. All Go dependencies are scope \"production\"\n * since Go doesn't have dev dependencies in go.mod.\n */\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { ParsedDependency } from '../../types';\nimport { logWarn } from '../../../errors';\n\n/**\n * Parse a go.mod manifest and extract dependency declarations with version\n * information. In Go modules, the version declared in go.mod is the resolved\n * version (pinned), so declaredConstraint and resolvedVersion are the same.\n *\n * @param manifestPath - Absolute path to the go.mod file\n * @param projectRoot - Absolute path to the project root directory\n * @returns Array of parsed dependencies with version information\n */\nexport async function parseGoManifest(\n manifestPath: string,\n projectRoot: string,\n): Promise<ParsedDependency[]> {\n const manifestDir = path.dirname(manifestPath);\n const relativeManifest = path.relative(projectRoot, manifestPath).replace(/\\\\/g, '/');\n\n // Read go.mod content\n let content: string;\n try {\n content = fs.readFileSync(manifestPath, 'utf8');\n } catch (err) {\n logWarn(`[sec:go] Failed to read ${relativeManifest}: ${err instanceof Error ? err.message : String(err)}`);\n return [];\n }\n\n // Load go.sum for integrity verification (optional)\n const goSumHashes = loadGoSumHashes(manifestDir);\n\n // Extract dependencies from require directives\n const dependencies: ParsedDependency[] = [];\n\n // Parse require block: require ( ... )\n const requireBlockRegex = /require\\s*\\(([^)]*)\\)/gs;\n let blockMatch: RegExpExecArray | null;\n while ((blockMatch = requireBlockRegex.exec(content)) !== null) {\n const blockContent = blockMatch[1];\n parseRequireLines(blockContent, relativeManifest, goSumHashes, dependencies);\n }\n\n // Parse single-line require directives: require module/path v1.2.3\n const lines = content.split('\\n');\n for (const line of lines) {\n const trimmed = line.trim();\n // Skip lines inside require blocks (already handled above)\n // Match: require <module> <version>\n const singleRequireMatch = trimmed.match(/^require\\s+(\\S+)\\s+(\\S+)/);\n if (singleRequireMatch) {\n const modulePath = singleRequireMatch[1];\n const version = singleRequireMatch[2];\n addDependency(modulePath, version, relativeManifest, goSumHashes, dependencies);\n }\n }\n\n return dependencies;\n}\n\n/**\n * Parse lines within a require block and extract module paths and versions.\n */\nfunction parseRequireLines(\n blockContent: string,\n relativeManifest: string,\n goSumHashes: GoSumMap,\n dependencies: ParsedDependency[],\n): void {\n const lines = blockContent.split('\\n');\n for (const line of lines) {\n const trimmed = line.trim();\n\n // Skip empty lines and comments\n if (!trimmed || trimmed.startsWith('//')) continue;\n\n // Match: module/path v1.2.3 [// indirect]\n const match = trimmed.match(/^(\\S+)\\s+(\\S+)/);\n if (match) {\n const modulePath = match[1];\n const version = match[2];\n\n // Skip if the \"module path\" is actually a comment\n if (modulePath.startsWith('//')) continue;\n\n addDependency(modulePath, version, relativeManifest, goSumHashes, dependencies);\n }\n }\n}\n\n/**\n * Add a single dependency entry after validation.\n */\nfunction addDependency(\n modulePath: string,\n version: string,\n relativeManifest: string,\n goSumHashes: GoSumMap,\n dependencies: ParsedDependency[],\n): void {\n // Validate module path\n if (!isValidGoModulePath(modulePath)) {\n logWarn(`[sec:go] Invalid module path \"${modulePath}\" in ${relativeManifest} \u2014 skipping`);\n return;\n }\n\n // Validate version format (should start with 'v' for Go modules)\n if (!isValidGoVersion(version)) {\n logWarn(`[sec:go] Invalid version \"${version}\" for module \"${modulePath}\" in ${relativeManifest} \u2014 skipping`);\n return;\n }\n\n // Check if this module+version has integrity info in go.sum\n const hasIntegrity = goSumHashes.has(`${modulePath}@${version}`);\n\n // In Go, the version in go.mod is the resolved version\n // declaredConstraint and resolvedVersion are the same\n dependencies.push({\n name: modulePath,\n declaredConstraint: version,\n resolvedVersion: version,\n scope: 'production', // Go doesn't have dev dependencies in go.mod\n ecosystem: 'go',\n sourceManifest: relativeManifest,\n });\n}\n\n/**\n * Map of module@version \u2192 true, indicating presence in go.sum.\n * Used for integrity verification awareness.\n */\ntype GoSumMap = Map<string, boolean>;\n\n/**\n * Load go.sum hashes from the same directory as go.mod.\n * go.sum contains lines like:\n * module/path v1.2.3 h1:hash...\n * module/path v1.2.3/go.mod h1:hash...\n */\nfunction loadGoSumHashes(manifestDir: string): GoSumMap {\n const map: GoSumMap = new Map();\n const goSumPath = path.join(manifestDir, 'go.sum');\n\n if (!fs.existsSync(goSumPath)) {\n return map;\n }\n\n try {\n const content = fs.readFileSync(goSumPath, 'utf8');\n const lines = content.split('\\n');\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n // Format: module/path version hash\n // e.g.: github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqFPSKw=\n const parts = trimmed.split(/\\s+/);\n if (parts.length >= 3) {\n const modulePath = parts[0];\n let version = parts[1];\n // Strip /go.mod suffix from version if present\n version = version.replace(/\\/go\\.mod$/, '');\n map.set(`${modulePath}@${version}`, true);\n }\n }\n } catch (err) {\n logWarn(`[sec:go] Failed to read go.sum: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n return map;\n}\n\n/**\n * Validate a Go module path.\n * A valid module path must contain at least one dot in the first path element\n * (domain requirement) and consist of valid characters.\n */\nfunction isValidGoModulePath(modulePath: string): boolean {\n if (!modulePath || typeof modulePath !== 'string') return false;\n\n // Must not be empty or contain spaces\n if (modulePath.includes(' ') || modulePath.includes('\\t')) return false;\n\n // First path element must contain a dot (domain name requirement)\n const firstSlash = modulePath.indexOf('/');\n const firstElement = firstSlash === -1 ? modulePath : modulePath.slice(0, firstSlash);\n if (!firstElement.includes('.')) return false;\n\n return true;\n}\n\n/**\n * Validate a Go module version string.\n * Valid formats: v1.2.3, v0.0.0-timestamp-hash, v1.2.3-pre, v1.2.3+incompatible\n */\nfunction isValidGoVersion(version: string): boolean {\n if (!version || typeof version !== 'string') return false;\n\n // Must start with 'v'\n if (!version.startsWith('v')) return false;\n\n // Basic semver-like check after 'v': at minimum \"vX.Y.Z\" or pseudo-version\n const versionBody = version.slice(1);\n if (!versionBody) return false;\n\n // Allow semver, pseudo-versions, and +incompatible suffix\n // Pseudo-version format: v0.0.0-20230101120000-abcdef123456\n const semverPattern = /^\\d+\\.\\d+\\.\\d+/;\n return semverPattern.test(versionBody);\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAcA,SAAoB;AACpB,WAAsB;AAEtB,oBAAwB;AAWxB,eAAsB,gBACpB,cACA,aAC6B;AAC7B,QAAM,cAAc,KAAK,QAAQ,YAAY;AAC7C,QAAM,mBAAmB,KAAK,SAAS,aAAa,YAAY,EAAE,QAAQ,OAAO,GAAG;AAGpF,MAAI;AACJ,MAAI;AACF,cAAU,GAAG,aAAa,cAAc,MAAM;AAAA,EAChD,SAAS,KAAK;AACZ,+BAAQ,2BAA2B,gBAAgB,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAC1G,WAAO,CAAC;AAAA,EACV;AAGA,QAAM,cAAc,gBAAgB,WAAW;AAG/C,QAAM,eAAmC,CAAC;AAG1C,QAAM,oBAAoB;AAC1B,MAAI;AACJ,UAAQ,aAAa,kBAAkB,KAAK,OAAO,OAAO,MAAM;AAC9D,UAAM,eAAe,WAAW,CAAC;AACjC,sBAAkB,cAAc,kBAAkB,aAAa,YAAY;AAAA,EAC7E;AAGA,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAU,KAAK,KAAK;AAG1B,UAAM,qBAAqB,QAAQ,MAAM,0BAA0B;AACnE,QAAI,oBAAoB;AACtB,YAAM,aAAa,mBAAmB,CAAC;AACvC,YAAM,UAAU,mBAAmB,CAAC;AACpC,oBAAc,YAAY,SAAS,kBAAkB,aAAa,YAAY;AAAA,IAChF;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,kBACP,cACA,kBACA,aACA,cACM;AACN,QAAM,QAAQ,aAAa,MAAM,IAAI;AACrC,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAU,KAAK,KAAK;AAG1B,QAAI,CAAC,WAAW,QAAQ,WAAW,IAAI,EAAG;AAG1C,UAAM,QAAQ,QAAQ,MAAM,gBAAgB;AAC5C,QAAI,OAAO;AACT,YAAM,aAAa,MAAM,CAAC;AAC1B,YAAM,UAAU,MAAM,CAAC;AAGvB,UAAI,WAAW,WAAW,IAAI,EAAG;AAEjC,oBAAc,YAAY,SAAS,kBAAkB,aAAa,YAAY;AAAA,IAChF;AAAA,EACF;AACF;AAKA,SAAS,cACP,YACA,SACA,kBACA,aACA,cACM;AAEN,MAAI,CAAC,oBAAoB,UAAU,GAAG;AACpC,+BAAQ,iCAAiC,UAAU,QAAQ,gBAAgB,kBAAa;AACxF;AAAA,EACF;AAGA,MAAI,CAAC,iBAAiB,OAAO,GAAG;AAC9B,+BAAQ,6BAA6B,OAAO,iBAAiB,UAAU,QAAQ,gBAAgB,kBAAa;AAC5G;AAAA,EACF;AAGA,QAAM,eAAe,YAAY,IAAI,GAAG,UAAU,IAAI,OAAO,EAAE;AAI/D,eAAa,KAAK;AAAA,IAChB,MAAM;AAAA,IACN,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,OAAO;AAAA;AAAA,IACP,WAAW;AAAA,IACX,gBAAgB;AAAA,EAClB,CAAC;AACH;AAcA,SAAS,gBAAgB,aAA+B;AACtD,QAAM,MAAgB,oBAAI,IAAI;AAC9B,QAAM,YAAY,KAAK,KAAK,aAAa,QAAQ;AAEjD,MAAI,CAAC,GAAG,WAAW,SAAS,GAAG;AAC7B,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,UAAU,GAAG,aAAa,WAAW,MAAM;AACjD,UAAM,QAAQ,QAAQ,MAAM,IAAI;AAEhC,eAAW,QAAQ,OAAO;AACxB,YAAM,UAAU,KAAK,KAAK;AAC1B,UAAI,CAAC,QAAS;AAId,YAAM,QAAQ,QAAQ,MAAM,KAAK;AACjC,UAAI,MAAM,UAAU,GAAG;AACrB,cAAM,aAAa,MAAM,CAAC;AAC1B,YAAI,UAAU,MAAM,CAAC;AAErB,kBAAU,QAAQ,QAAQ,cAAc,EAAE;AAC1C,YAAI,IAAI,GAAG,UAAU,IAAI,OAAO,IAAI,IAAI;AAAA,MAC1C;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,+BAAQ,mCAAmC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,EAC/F;AAEA,SAAO;AACT;AAOA,SAAS,oBAAoB,YAA6B;AACxD,MAAI,CAAC,cAAc,OAAO,eAAe,SAAU,QAAO;AAG1D,MAAI,WAAW,SAAS,GAAG,KAAK,WAAW,SAAS,GAAI,EAAG,QAAO;AAGlE,QAAM,aAAa,WAAW,QAAQ,GAAG;AACzC,QAAM,eAAe,eAAe,KAAK,aAAa,WAAW,MAAM,GAAG,UAAU;AACpF,MAAI,CAAC,aAAa,SAAS,GAAG,EAAG,QAAO;AAExC,SAAO;AACT;AAMA,SAAS,iBAAiB,SAA0B;AAClD,MAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AAGpD,MAAI,CAAC,QAAQ,WAAW,GAAG,EAAG,QAAO;AAGrC,QAAM,cAAc,QAAQ,MAAM,CAAC;AACnC,MAAI,CAAC,YAAa,QAAO;AAIzB,QAAM,gBAAgB;AACtB,SAAO,cAAc,KAAK,WAAW;AACvC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|