From 4763eeb4205ca5626879c5d229d1bb92122a2d08 Mon Sep 17 00:00:00 2001 From: Martin Najemi Date: Mon, 23 Feb 2026 11:16:07 +0100 Subject: [PATCH] fix: Add intra-file taint propagation after seeding phase Risk: low JIRA: STL-2317 --- .../pull-request-status-check-changelog.yml | 6 +- CHANGELOG.md | 6 ++ VERSION | 2 +- internal/analyzer/analyzer.go | 60 +++++++++++++++++++ 4 files changed, 70 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pull-request-status-check-changelog.yml b/.github/workflows/pull-request-status-check-changelog.yml index 2619e8e..8afb1c4 100644 --- a/.github/workflows/pull-request-status-check-changelog.yml +++ b/.github/workflows/pull-request-status-check-changelog.yml @@ -27,18 +27,18 @@ jobs: - name: Install changelog validator run: | # Install Node.js tool for Keep a Changelog validation - npm install -g keep-a-changelog + npm install -g keep-a-changelog@2.8.0 - name: Validate changelog format run: | echo "Validating CHANGELOG.md format according to Keep a Changelog..." # Use keep-a-changelog to validate the changelog format - if ! npx keep-a-changelog CHANGELOG.md > /dev/null 2>&1; then + if ! npx keep-a-changelog@2.8.0 CHANGELOG.md > /dev/null 2>&1; then echo "❌ CHANGELOG.md is not valid according to Keep a Changelog format" echo "Please ensure your changelog follows the format at https://keepachangelog.com" echo "Validation output:" - npx keep-a-changelog CHANGELOG.md + npx keep-a-changelog@2.8.0 CHANGELOG.md exit 1 fi diff --git a/CHANGELOG.md b/CHANGELOG.md index cfef018..6feb676 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.15.3] - 2026-02-23 + +### Fixed +- Add intra-file taint propagation after seeding phase in both `AnalyzeLibraryPackage` and `FindAffectedFiles`, so that symbols referencing other tainted symbols in the same file are also marked as tainted before BFS starts + ## [0.15.2] - 2026-02-20 ### Fixed @@ -192,6 +197,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Multi-stage Docker build - Automated vendor upgrade workflow +[0.15.3]: https://github.com/gooddata/gooddata-goodchanges/compare/v0.15.2...v0.15.3 [0.15.2]: https://github.com/gooddata/gooddata-goodchanges/compare/v0.15.1...v0.15.2 [0.15.1]: https://github.com/gooddata/gooddata-goodchanges/compare/v0.15.0...v0.15.1 [0.15.0]: https://github.com/gooddata/gooddata-goodchanges/compare/v0.14.2...v0.15.0 diff --git a/VERSION b/VERSION index a12760e..0cf69a5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.15.2 \ No newline at end of file +0.15.3 \ No newline at end of file diff --git a/internal/analyzer/analyzer.go b/internal/analyzer/analyzer.go index 822a83f..7d027d2 100644 --- a/internal/analyzer/analyzer.go +++ b/internal/analyzer/analyzer.go @@ -714,6 +714,38 @@ func AnalyzeLibraryPackage(projectFolder string, entrypoints []Entrypoint, merge return nil, nil } + // Intra-file propagation for seeded taint. + // When upstream taint or AST diff marks symbol A as tainted, other symbols + // in the same file that reference A should also be tainted. + // Example: if KdaDialogController taints KeyDriverAnalysisComponent, then + // KeyDriverAnalysis = connect(...)(KeyDriverAnalysisComponent) should also be tainted. + for stem, names := range tainted { + analysis := fileAnalyses[stem] + if analysis == nil || analysis.SourceFile == nil { + continue + } + sourceText := analysis.SourceFile.Text() + lineMap := analysis.SourceFile.ECMALineMap() + changed := true + for changed { + changed = false + for _, sym := range analysis.Symbols { + if names[sym.Name] { + continue + } + bodyText := tsparse.ExtractTextForLines(sourceText, lineMap, sym.StartLine, sym.EndLine) + for tName := range names { + if strings.Contains(bodyText, tName) { + names[sym.Name] = true + changed = true + debugf(" %s: %s tainted via intra-file dep on %s (seed propagation)", stem, sym.Name, tName) + break + } + } + } + } + } + // Build reverse import graph reverseImports := make(map[string][]string) for stem, edges := range importGraph { @@ -1500,6 +1532,34 @@ func FindAffectedFiles(globPattern string, filterPattern string, upstreamTaint m return nil } + // Intra-file propagation for seeded taint (same as in AnalyzeLibraryPackage). + for stem, names := range tainted { + analysis := fileAnalyses[stem] + if analysis == nil || analysis.SourceFile == nil { + continue + } + sourceText := analysis.SourceFile.Text() + lineMap := analysis.SourceFile.ECMALineMap() + changed := true + for changed { + changed = false + for _, sym := range analysis.Symbols { + if names[sym.Name] { + continue + } + bodyText := tsparse.ExtractTextForLines(sourceText, lineMap, sym.StartLine, sym.EndLine) + for tName := range names { + if strings.Contains(bodyText, tName) { + names[sym.Name] = true + changed = true + debugf(" %s: %s tainted via intra-file dep on %s (seed propagation)", stem, sym.Name, tName) + break + } + } + } + } + } + // Symbol-level BFS propagation (same engine as AnalyzeLibraryPackage) debugf("=== Starting BFS taint propagation (FindAffectedFiles) ===") queue := make([]string, 0, len(tainted))