/** * Dependency-manifest helpers for the deserialization-safety-gate pass. * * cognium-dev #258 — dependency-version-aware sink gating. The engine * never reads the filesystem (Pillar I / browser-safety); the caller * (cognium-dev CLI or `analyzeProject`) reads the manifest and passes * it as raw text via `AnalyzerOptions.dependencyContext`. Helpers here * turn that raw text into the boolean predicates the gate needs. * * All parsers here are string-scoped: regex over the raw manifest * rather than a full XML/JSON tree. That is deliberate — the gate only * needs a handful of narrow signals (Fastjson version, presence of a * safe classifier), and every existing runtime dep in circle-ir is * either `web-tree-sitter` or `yaml`. Pulling in an XML parser purely * for one Fastjson property would violate the minimal-dependencies * guardrail. */ /** * Result of extracting the effective Fastjson coordinate from a * `pom.xml` string. `version` is the raw value as declared (including * any classifier suffix); `noneAutotype` is true when the version * literally matches Alibaba's `_noneautotype` hardened build family * (any patch level, e.g. `1.2.83_noneautotype`, `1.2.85_noneautotype`). */ export interface FastjsonPomResolution { version: string; noneAutotype: boolean; } /** * Extract the effective Fastjson version from a `pom.xml`. Two sources * are consulted: * * 1. A `` entry named exactly `` — the * idiomatic way Maven projects centralise a dep version they * reference in a `` block. This is where * alibaba/Sentinel pins `1.2.83_noneautotype`. * 2. A `` block whose `` is `com.alibaba` and * `` is `fastjson` — read as a fallback when the * version is declared inline rather than as a property. * * Returns `null` when no Fastjson coordinate can be resolved from the * pom (no properties entry AND no matching dependency block, or the * dependency uses a `${...}` reference the properties block doesn't * define). */ export declare function resolveFastjsonFromPom(pomXml: string): FastjsonPomResolution | null; /** * Extract the effective Fastjson version from a Gradle build script * (`build.gradle` Groovy DSL or `build.gradle.kts` Kotlin DSL). * * cognium-dev #261 (Gradle-first slice extending #258's pom.xml gate). * * Recognises three declaration shapes: * * 1. Direct literal — the classic Groovy / Kotlin single-string form: * implementation 'com.alibaba:fastjson:1.2.83_noneautotype' * implementation "com.alibaba:fastjson:1.2.83_noneautotype" * implementation("com.alibaba:fastjson:1.2.83_noneautotype") * Also `api`, `compile`, `runtimeOnly`, `testImplementation`, … — the * configuration keyword is not part of the regex; only the * `group:artifact:version` triple is matched, so any dependency- * configuration prefix works. * * 2. Groovy interpolation — `implementation "com.alibaba:fastjson:${fastjsonVersion}"` * with the property defined via `ext { fastjsonVersion = '1.2.83_noneautotype' }`, * `def fastjsonVersion = '1.2.83_noneautotype'`, or top-level `fastjsonVersion = '…'`. * * 3. Kotlin interpolation — `implementation("com.alibaba:fastjson:$fastjsonVersion")` * with the property defined via `val fastjsonVersion = "1.2.83_noneautotype"` * or `const val fastjsonVersion = "…"`. * * Returns `null` on miss (no direct declaration AND no resolvable * property reference). The `DeserializationSafetyGatePass` then falls * through to its default "do not drop" behaviour on the sink. * * NOT recognised in this MVP (deferred, follow-ups on #261): * - `platform(...)` / `enforcedPlatform(...)` BOM version imports * - Version-catalog `libs.versions.toml` references (`libs.fastjson`) * - `constraints { }` block versions * - `subprojects { }` / `allprojects { }` conditional declarations */ export declare function resolveFastjsonFromGradle(buildGradle: string): FastjsonPomResolution | null; /** * Extract the effective Fastjson version from a Gradle version-catalog * (`gradle/libs.versions.toml`) combined with the `build.gradle` script * that references it via a `libs.` accessor. * * cognium-dev #261 (Gradle catalog slice, extending the direct-Gradle * shape landed in the first Gradle slice). * * Recognises the two common `[libraries]` entry shapes: * * fastjson = { module = "com.alibaba:fastjson", version.ref = "fastjson" } * fastjson = { group = "com.alibaba", name = "fastjson", version.ref = "fastjson" } * * The version can be either a `version.ref` pointer into the * `[versions]` section, or an inline `version = "…"` on the library * entry itself. Both forms are handled. * * The build.gradle must reference the resolved alias via a * `libs.` accessor (or `libs.` — Gradle normalises * dashes to dots for accessor names, but at the toml level the key * uses the original form; we match the toml alias here). If the alias * isn't referenced anywhere in the build.gradle, returns null — an * unreferenced catalog entry is not an active dependency. * * Returns null when no fastjson library entry exists, when the version * cannot be resolved, or when the alias is defined but unreferenced. * The `DeserializationSafetyGatePass` then falls through to its * default "do not drop" behaviour. */ export declare function resolveFastjsonFromGradleCatalog(buildGradle: string, libsVersionsToml: string): FastjsonPomResolution | null; /** * Result of extracting the effective PyYAML version. `safeByDefault` is * true when the parsed version is ≥ 6.0; at that point pyyaml.load() * without an explicit `Loader=` keyword argument raises TypeError * instead of silently invoking the unsafe default Loader. * * See https://github.com/yaml/pyyaml/blob/master/CHANGES for the full * 6.0 breakage story. The gate consumer must ALSO check the call site * for an explicit `Loader=` keyword (fileHasUnsafePyYamlLoader below) * — a caller under pyyaml ≥ 6.0 that explicitly passes * `Loader=yaml.Loader` or `Loader=yaml.UnsafeLoader` is still * dangerous regardless of the version pin. */ export interface PyYamlResolution { version: string; safeByDefault: boolean; } /** * Extract the effective PyYAML version from a `requirements.txt` file. * Recognises the standard PEP 508 shapes (`==`, `>=`, `~=`, `>`, * exact pins with trailing modifiers). Package name matched * case-insensitively (both `PyYAML` and `pyyaml` are common in the * wild). * * Returns null when no pyyaml line is found or the version string * cannot be parsed as `M.m[.p]`. Non-strict on trailing environment * markers (` ; python_version >= '3.6'`), which are common on * requirements.txt lines. */ export declare function resolvePyYamlFromRequirements(requirementsTxt: string): PyYamlResolution | null; /** * Extract the effective PyYAML version from a `pyproject.toml`. * Recognises the common Poetry and PEP 621 shapes: * * Poetry — under `[tool.poetry.dependencies]`: * PyYAML = "6.0" * pyyaml = "^6.0.1" * pyyaml = { version = "6.0", extras = ["..."] } * * PEP 621 — under `[project]` `dependencies` array: * dependencies = [ "PyYAML>=6.0", ... ] * * As with the requirements.txt resolver, non-strict on markers / * modifiers; regex-based rather than a full TOML parser to keep the * runtime-dep list minimal (Pillar I minimal-dependencies principle). */ export declare function resolvePyYamlFromPyproject(pyprojectToml: string): PyYamlResolution | null; /** * True when `version` (as `M.m[.p]`) is ≥ 6.0. Handles bare `6`, * `6.0`, `6.0.1`, `7`, `10.0`, etc. Returns false on malformed input * (defensive — the gate defaults to *do not drop* on missing signal). */ export declare function isPyYamlVersionSafeByDefault(version: string): boolean; /** * Return true when the file contains an explicit unsafe `Loader=` * keyword argument on a `yaml.load(...)` call at or shortly after * `sinkLine`. Recognises the well-known unsafe loaders and their * qualified forms: * * Loader=Loader Loader=yaml.Loader * Loader=UnsafeLoader Loader=yaml.UnsafeLoader * Loader=FullLoader Loader=yaml.FullLoader (technically safer * than Loader; still * permits arbitrary * Python object types) * * SafeLoader / CSafeLoader / BaseLoader / CBaseLoader are all safe and * are NOT matched here. * * Scans `sinkLine` through the next 9 lines to catch multi-line call * shapes; if the closing `)` appears before the window ends the scan * stops there. Regex-based (no AST inspection) to stay consistent with * the sink-filter-pass conventions and avoid pulling parse state into * the gate. */ export declare function fileHasUnsafePyYamlLoader(sourceLines: string[], sinkLine: number): boolean; /** * Extracted npm dep info. `version` is the raw range/spec as declared * in the manifest (may be `"^1.2.3"`, `"~1.0"`, `">=2 <3"`, exact * `"1.2.3"`, dist-tag `"latest"`, etc.). Semver-range parsing is left * to callers that need it — this helper does not pull in a semver * library. */ export interface PackageJsonDepResolution { version: string; /** * Which top-level manifest section the dep was resolved from. * `'dependencies' | 'devDependencies' | 'peerDependencies' | * 'optionalDependencies'`. Callers can use this to weight runtime * deps over dev-only deps in gate decisions. */ section: 'dependencies' | 'devDependencies' | 'peerDependencies' | 'optionalDependencies'; } /** * Extract the declared version + manifest section for a named npm * dependency from a `package.json`. Searches `dependencies` first, * then `devDependencies`, then `peerDependencies`, then * `optionalDependencies`. Returns the FIRST match — matching npm's * own precedence when a name appears in multiple sections (rare, but * npm resolves against `dependencies` for the installed tree). * * Returns null when: * - The manifest text isn't parseable JSON (defensive; the gate * defaults to fire on missing signal). * - The named dep isn't declared in any section. * - The value is a non-string (unusual — npm accepts strings) or * starts with a well-known non-registry source prefix (`git+`, * `github:`, `file:`, `link:`, `workspace:`, `npm:` alias-style * without a version). No version to compare against for those. * * cognium-dev #261 (npm slice, plumbing-only). */ export declare function resolveDepFromPackageJson(packageJson: string, depName: string): PackageJsonDepResolution | null; /** * Generic result: the declared version string + the parsed feature list * (for `[dependencies] pkg = { version = "…", features = ["safe"] }` * shapes). Returns null when the dep is absent, or when the version is * a `{ git = "…" }` / `{ path = "…" }` non-registry source (no version * string to compare against). Feature-set matching is left to the * caller; this helper only parses. */ export interface CargoDepResolution { version: string; features: string[]; } /** * Extract the declared version + feature list for a named crate from a * `Cargo.toml`. Recognises the standard `[dependencies]` (and * `[dev-dependencies]` / `[build-dependencies]`) shapes: * * pkg = "1.2.3" — bare string * pkg = { version = "1.2.3" } — table with version * pkg = { version = "1.2.3", features = ["a", "b"] } * pkg = { git = "…" } — git source (no version) * pkg = { path = "…" } — path source (no version) * * Cross-table dependency declarations (`[dependencies.pkg]`) are not * yet recognised; those are less common and can be added when needed. * Regex-based rather than a full TOML parser to keep the runtime-dep * list minimal (Pillar I). */ export declare function resolveDepFromCargoToml(cargoToml: string, crateName: string): CargoDepResolution | null; /** * Return true when the given source text contains an in-file call that * re-enables Fastjson autotype. Even a `_noneautotype` build does not * protect against code that programmatically re-enables the feature * (which the hardened build documents as impossible, but the classifier * is a build-time strip, not a runtime lock). Defense-in-depth for the * `resolveFastjsonFromPom` gate. */ export declare function fileReenablesFastjsonAutotype(source: string): boolean; /** * Return true when the given Java source contains a call that enables * Jackson polymorphic type handling — either the legacy * `enableDefaultTyping(...)` (deprecated in Jackson 2.10+ but still * shipped) or the current `activateDefaultTyping(...)`. * * When neither is present in the file (and no `@JsonTypeInfo` is used * on the target type — best-effort scan below), Jackson's default * behaviour since 2.10 is safe: `ObjectMapper.readValue(json, * targetType)` cannot instantiate arbitrary classes. The gate uses * this to distinguish a genuine `readValue` sink from a safely- * configured one. * * `@JsonTypeInfo` scan is intentionally file-local. A `@JsonTypeInfo` * annotation on a target type in a different file would still allow * polymorphic construction, but the engine treats that as unknown * risk and preserves the sink (the gate only fires when the *file * itself* provides positive evidence of a safe configuration). */ export declare function fileEnablesJacksonPolymorphism(source: string): boolean; /** * Return true when the given Java source contains a * `new Yaml(new SafeConstructor(...))` or an equivalent hardened * SnakeYAML constructor. When any `Yaml` instance in the file is * built with the safe constructor family, we assume the file's * `Yaml.load(...)` calls are safely configured; the gate then drops * the deserialization sink for those calls. * * Recognised safe constructor classes (SnakeYAML 1.x + 2.x): * - SafeConstructor — canonical safe loader * - SafeSchema (rare, YAML 1.2) — safe schema-based loader * * Recognised safe factory calls (SnakeYAML 2.x LoaderOptions API): * - Yaml.load() with a Constructor that extends SafeConstructor * (heuristic: any `SafeConstructor`-typed variable is safe) * * NOTE: A file that mixes `new Yaml(new SafeConstructor())` with * `new Yaml(new Constructor(SomeClass.class))` on separate call sites * would over-suppress the unsafe site. In practice this is rare (SAST * teams write one wrapper per file), and the current sink-filter * stage 9b handles the analogous compiled-template case with the same * file-scoped heuristic. If it becomes a problem, tighten to * receiver-scoped: check the specific `Yaml` receiver that carries * the load() call. */ export declare function fileConfiguresSnakeYamlSafely(source: string): boolean; //# sourceMappingURL=dependency-versions.d.ts.map