88 "io"
99 "os"
1010 "os/exec"
11+ "path/filepath"
1112 "regexp"
1213 "strings"
1314 "time"
@@ -136,7 +137,18 @@ func (g *Generator) getInstalledPackages() ([]DpkgPackage, error) {
136137}
137138
138139func (g * Generator ) getPackageLicense (packageName string ) (string , string ) {
139- copyrightPath := fmt .Sprintf ("/usr/share/doc/%s/copyright" , packageName )
140+ // Sanitize package name to prevent path traversal
141+ cleanName := filepath .Clean (packageName )
142+ if strings .Contains (cleanName , ".." ) || strings .HasPrefix (cleanName , "/" ) || strings .Contains (cleanName , string (filepath .Separator )) {
143+ return "NOASSERTION" , "NOASSERTION"
144+ }
145+
146+ copyrightPath := filepath .Join ("/usr/share/doc" , cleanName , "copyright" )
147+
148+ // Verify the resolved path is within the expected directory
149+ if ! strings .HasPrefix (copyrightPath , "/usr/share/doc/" ) {
150+ return "NOASSERTION" , "NOASSERTION"
151+ }
140152
141153 content , err := os .ReadFile (copyrightPath )
142154 if err != nil {
@@ -211,7 +223,13 @@ func (g *Generator) packageToSPDX(pkg DpkgPackage, id int) spdx.Package {
211223}
212224
213225func (g * Generator ) calculatePackageChecksum (packageName string ) string {
214- cmd := exec .Command ("dpkg" , "-L" , packageName )
226+ // Sanitize package name to prevent command injection
227+ cleanName := filepath .Clean (packageName )
228+ if strings .Contains (cleanName , ".." ) || strings .HasPrefix (cleanName , "/" ) || strings .Contains (cleanName , string (filepath .Separator )) {
229+ return ""
230+ }
231+
232+ cmd := exec .Command ("dpkg" , "-L" , cleanName )
215233 output , err := cmd .Output ()
216234 if err != nil {
217235 return ""
@@ -235,7 +253,21 @@ func (g *Generator) calculatePackageChecksum(packageName string) string {
235253}
236254
237255func hashFile (path string ) string {
238- file , err := os .Open (path )
256+ // Sanitize path to prevent path traversal
257+ cleanPath := filepath .Clean (path )
258+
259+ // Reject paths with traversal attempts or that aren't absolute
260+ if strings .Contains (cleanPath , ".." ) || ! filepath .IsAbs (cleanPath ) {
261+ return ""
262+ }
263+
264+ // Verify it's a regular file (not a symlink to outside, directory, etc.)
265+ info , err := os .Lstat (cleanPath )
266+ if err != nil || ! info .Mode ().IsRegular () {
267+ return ""
268+ }
269+
270+ file , err := os .Open (cleanPath )
239271 if err != nil {
240272 return ""
241273 }
0 commit comments