Skip to content

Follow/resolve directory symlinks during license file search #401

@spiffcs

Description

@spiffcs

Summary

When scanning a directory for license files(not syft sbom generation), grant skips symlinks that point to directories. This means license files inside symlinked directories are not discovered by the local license file search:

grant/grant/case.go

Lines 400 to 440 in 8358948

err := filepath.WalkDir(root, func(path string, d os.DirEntry, err error) error {
if err != nil {
return nil // Continue walking even if there's an error with a specific directory
}
if d.IsDir() {
dirName := d.Name()
if skipDirectories[dirName] {
return filepath.SkipDir
}
return nil
}
// skip if we've already processed this file
if visited[path] {
return nil
}
// look for file in license patterns
filename := filepath.Base(path)
for _, pattern := range patterns {
matched, err := filepath.Match(pattern, filename)
if err != nil {
continue
}
if matched {
visited[path] = true
licenses, err := ch.handleLicenseFile(path)
if err != nil {
continue
}
if len(licenses) > 0 {
foundLicenses = append(foundLicenses, licenses...)
}
break // Found a match, no need to check other patterns for this file
}
}
return nil

This was discovered as a bug in #70. filepath.WalkDir uses lstat semantics and never descends into symlinked directories. They appear as non-directory entries. Without skipping them, they get passed to the license classifier, which causes errors.

Current behavior

  • Symlinks to regular files: followed (license is detected)
  • Symlinks to directories: skipped (licenses inside are missed)
  • Broken symlinks: skipped

Desired behavior

Directory symlinks should be resolved and followed during the license file search, with cycle detection to prevent infinite loops (e.g., a -> b -> a).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions