@@ -543,6 +543,7 @@ func (a *APK) InitKeyring(ctx context.Context, keyFiles, extraKeyFiles []string)
543543 for _ , element := range keyFiles {
544544 eg .Go (func () error {
545545 log .Debugf ("installing key %v" , element )
546+ keyName := filepath .Base (element )
546547
547548 var asURL * url.URL
548549 var err error
@@ -586,6 +587,9 @@ func (a *APK) InitKeyring(ctx context.Context, keyFiles, extraKeyFiles []string)
586587 if resp .StatusCode < 200 || resp .StatusCode > 299 {
587588 return fmt .Errorf ("failed to fetch apk key from %s: http response indicated error code: %d" , req .Host , resp .StatusCode )
588589 }
590+ if contentDispositionFileName := keyFilenameFromContentDisposition (resp .Header .Get ("Content-Disposition" )); contentDispositionFileName != "" {
591+ keyName = contentDispositionFileName
592+ }
589593
590594 data , err = io .ReadAll (resp .Body )
591595 if err != nil {
@@ -596,7 +600,7 @@ func (a *APK) InitKeyring(ctx context.Context, keyFiles, extraKeyFiles []string)
596600 }
597601
598602 // #nosec G306 -- apk keyring must be publicly readable
599- if err := a .fs .WriteFile (filepath .Join ("etc" , "apk" , "keys" , filepath . Base ( element ) ), data ,
603+ if err := a .fs .WriteFile (filepath .Join ("etc" , "apk" , "keys" , keyName ), data ,
600604 0o644 ); err != nil {
601605 return fmt .Errorf ("failed to write apk key: %w" , err )
602606 }
@@ -608,6 +612,43 @@ func (a *APK) InitKeyring(ctx context.Context, keyFiles, extraKeyFiles []string)
608612 return eg .Wait ()
609613}
610614
615+ func keyFilenameFromContentDisposition (contentDisposition string ) string {
616+ if contentDisposition == "" {
617+ return ""
618+ }
619+
620+ for _ , field := range strings .Split (contentDisposition , ";" ) {
621+ field = strings .TrimSpace (field )
622+ lower := strings .ToLower (field )
623+
624+ if strings .HasPrefix (lower , "filename*=" ) {
625+ filename := strings .TrimSpace (field [len ("filename*=" ):])
626+ filename = strings .Trim (filename , `"` )
627+ if i := strings .Index (filename , "''" ); i >= 0 {
628+ filename = filename [i + 2 :]
629+ }
630+ if decodedFilename , err := url .PathUnescape (filename ); err == nil {
631+ filename = decodedFilename
632+ }
633+ filename = filepath .Base (filename )
634+ if filename != "" && filename != "." {
635+ return filename
636+ }
637+ }
638+
639+ if strings .HasPrefix (lower , "filename=" ) {
640+ filename := strings .TrimSpace (field [len ("filename=" ):])
641+ filename = strings .Trim (filename , `"` )
642+ filename = filepath .Base (filename )
643+ if filename != "" && filename != "." {
644+ return filename
645+ }
646+ }
647+ }
648+
649+ return ""
650+ }
651+
611652// ResolveWorld determine the target state for the requested dependencies in /etc/apk/world. Does not install anything.
612653func (a * APK ) ResolveWorld (ctx context.Context ) (toInstall []* RepositoryPackage , conflicts []string , err error ) {
613654 log := clog .FromContext (ctx )
0 commit comments