Skip to content

fix(sarif): report a subdirectory's lockfile relative to the source root - #1403

Merged
sonukapoor merged 4 commits into
mainfrom
bugfix/issue-1380-sarif-subdirectory-paths
Oct 25, 2026
Merged

sonukapoor merged 4 commits into
mainfrom
bugfix/issue-1380-sarif-subdirectory-paths

Conversation

@sonukapoor

Copy link
Copy Markdown
Collaborator

SARIF locations are emitted relative to %SRCROOT%, but the URI was the lockfile's bare filename. So a scan of a subdirectory reported every finding against a lockfile at the repository root, and Code Scanning put the alerts on a file without those dependencies, or on one that does not exist.

The lockfile is now measured from the launch directory, which is the checkout root on every path that uploads to Code Scanning: our Action runs each scan from the workspace and passes the target as an argument. A scan run at the project root still emits the bare filename, so single-project setups see no change. A lockfile above the launch directory, or on another Windows drive, falls back to the bare filename rather than emitting an invalid location.

This deliberately differs from the HTML report, which measures from the scanned project because it is read wherever it is pasted (#1271). Each artefact measures from wherever it is consumed.

Scanning examples/direct-fixable from the repository root: before, all 26 results were located at package-lock.json; now all 26 are at examples/direct-fixable/package-lock.json. The same scan run from inside the project is unchanged, and the findings are identical in both.

Worth a line in the release notes: some adopters work around this by prefixing the folder onto SARIF paths themselves before uploading. Once they upgrade, that step would double the prefix, so it should be removed.

Closes #1380

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Directory names containing reserved URI characters remain unescaped and can cause SARIF locations to resolve to incorrect files.

1 open issue
What changed in this PR

This PR corrects SARIF lockfile locations for subdirectory scans by measuring paths from the launch directory, aligning them with the checkout root used by the Action’s Code Scanning uploads.

Changes:

  • Emit relative lockfile paths while preserving bare filenames for root scans and unsupported relative paths.
  • Add tests for root, subdirectory, relative, and missing paths.
  • Add Windows-specific coverage for separator normalization and cross-drive fallback.
File Description
tests/​sarif.test.ts Tests launch-directory-relative paths and fallback behavior.
tests/​sarif-lockfile-uri-win32.test.ts Tests Windows separators and cross-drive fallback.
src/​output/​sarif.ts Derives SARIF lockfile paths relative to the launch directory.

Review effort: Balanced

Comment thread src/output/sarif.ts Outdated
Every SARIF location is emitted with uriBaseId %SRCROOT%, but the URI was the
lockfile's basename. A scan of a subdirectory therefore reported its findings
against a lockfile at the repository root, so Code Scanning put the alerts on
a file that does not contain the vulnerable packages, or on one that does not
exist.

Measure the lockfile from the launch directory instead. That is the checkout
root on every path that uploads to Code Scanning, since our own Action runs
each scan step from the workspace and passes the target as an argument, so a
scan of the root still emits the bare filename. A lockfile above the launch
directory cannot be source-root-relative and falls back to the basename.

This deliberately differs from the HTML report, which measures from the
scanned project because it is read wherever it is pasted (#1271).
…Windows drive

On Windows a lockfile on a different drive from the launch directory makes
path.relative return an absolute path, which the parent-directory check did
not catch, so the location came out as D:/proj/package-lock.json. That is not
source-root-relative and is worse than the basename that shipped.
…e root

The function had no direct tests, only mocks of it, which is how a
basename-only location shipped. Covers the launch directory, a subdirectory,
a relative path, a lockfile above the launch directory, the no-path default,
and under Windows path rules the slash conversion and the cross-drive case.
A SARIF location is a URI. Before this branch it only ever held a lockfile's
fixed basename, which never needed encoding; now it carries directory names,
which can. Unencoded, a folder named ui#legacy is cut short at the #, which
starts a fragment, and a literal %41 decodes to a different name. Encode each
segment and keep / as the separator.
@sonukapoor
sonukapoor force-pushed the bugfix/issue-1380-sarif-subdirectory-paths branch from a90d39c to b8fe51c Compare October 25, 2026 13:30
@sonukapoor
sonukapoor requested a balanced review from Copilot October 25, 2026 15:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The focused implementation matches the intended location contract, preserves fallback behavior, and includes regression coverage with no unresolved findings.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@sonukapoor
sonukapoor merged commit a653b6f into main Oct 25, 2026
7 checks passed
@sonukapoor
sonukapoor deleted the bugfix/issue-1380-sarif-subdirectory-paths branch October 25, 2026 15:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(sarif): a subdirectory scan reports its findings against the root lockfile, so Code Scanning alerts land on the wrong file

2 participants