GAM icon indicating copy to clipboard operation
GAM copied to clipboard

Sanitize debug logging of sensitive credentials by default

Open jay0lee opened this issue 3 months ago • 5 comments

Running a command with:

gam config debug_level 1 <actual command>

offers significant details on the API calls GAM is making that can be vital in troubleshooting an issue. However it also outputs sensitive refresh/access tokens by default.

Ideally we'd have something like:

gam config debug_level 1 <actual command>
...
<debug output with sensitive tokens redacted>
gam config debug_level 1 no_debug_redaction 1 <actual command>
...
<debug output with sensitive data like access/refresh tokens>

jay0lee avatar Sep 24 '25 15:09 jay0lee

Here's a rough start that seems to work for httplib2 / http.client debug output. Just add near top of gam/__init__.py:

def redact_sensitive_google_text(text):
    patterns = [
            r'ya29.[0-9A-Za-z-_]+', # Access token
            r'1/[0-9A-Za-z-]{43}|1/[0-9A-Za-z-]{64}', # Refresh token
            r'4/[0-9A-Za-z-_]+', # Auth code
            r'GOCSPX-[0-9a-zA-Z-_]{28}', # Client secret
            r'AIza[0-9A-Za-z-_]{35}', # API key
            ]
    for pattern in patterns:
      text = re.sub(pattern, '****', text)
    return text

def redactable_debug_print(*args):
  redacted_args = []
  for arg in args:
    if arg.startswith('b\''):
      sbytes = arg[2:-1]
      sbytes = bytes(sbytes, 'utf-8')
      arg = sbytes.decode()
      arg = arg.replace('\\r\\n', "\n          ")
    arg = redact_sensitive_google_text(arg)
    redacted_args.append(arg)
  print(*redacted_args)

http.client.print = redactable_debug_print

Needs some cleanup but I'd like to see us redact by default and then add a config option that disables redaction when set.

I believe for things like google.auth and JWT auth some HTTP requests are being sent by the requests library, not httplib2 so we'll need to catch those also and do redaction on them.

jay0lee avatar Oct 15 '25 00:10 jay0lee

First command of the day, client token had to be refreshed

def redact_sensitive_google_text(text):
    patterns = [
            r'ya29.[0-9A-Za-z-_]+', # Access token                                                                                                                                                                                                           
            r'1%2F%2F[0-9A-Za-z-_]{100}|1%2F%2F[0-9A-Za-z-_]{64}|1%2F%2F[0-9A-Za-z-_]{43}', # Refresh token                                                                                                                                                  
            r'4/[0-9A-Za-z-_]+', # Auth code                                                                                                                                                                                                                 
            r'GOCSPX-[0-9a-zA-Z-_]{28}', # Client secret                                                                                                                                                                                                     
            r'AIza[0-9A-Za-z-_]{35}', # API key                                                                                                                                                                                                              
            r'eyJ[a-zA-Z0-9\-_]+\.eyJ[a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]*' # JWT                                                                                                                                                                                 
            ]

Client secret is too narrow

connect: (oauth2.googleapis.com, 443)
send: POST /token HTTP/1.1
          Host: oauth2.googleapis.com
          Content-Length: 268
          content-type: application/x-www-form-urlencoded
          x-goog-api-client: gl-python/3.13.5 auth/2.39.0 cred-type/u
          user-agent: GAM 7.25.02 - https://github.com/GAM-team/GAM / GAM Team <[email protected]> / Python 3.13.5 final / macOS-26.0.1-arm64-arm-64bit-Mach-O arm64 /
          accept-encoding: gzip, deflate


send: grant_type=refresh_token&client_id=785055363286-2plolfdosis7r6id0j4rj9le87cijjoo.apps.googleusercontent.com&client_secret=WPDf2fqtX7z2ZGL-33z4SWi8&refresh_token=****
reply: 'HTTP/1.1 200 OK\r\n'

taers232c avatar Oct 16 '25 15:10 taers232c

Yeah, the challenge here is Google only recently (where recent might be any time in the last 10 years) changed some of these credential values to always match a certain somewhat unique regex patterns. It looks like at some point generated client secrets could be just random alphanumeric characters which makes it really hard to match based on the value.

I've added matchers for both positional (e.g.. if we see client_secret=... we can assume ... is a client secret that should be redacted and the previous patterns (in case that content is being passed around via some other method.

jay0lee avatar Oct 16 '25 19:10 jay0lee

Is there anything more you want to do here ot should I release it?

7.26.00

Added debug_redaction Boolean variable to gam.cfg. When True, the default, sensitive data like access/refresh tokens, client secret and authorization codes are redacted from debug output. This allows you to post debug output without compromising your account information.

Ross

taers232c avatar Oct 17 '25 19:10 taers232c

You can release..we should mention the logs should be sanitized but anything shared publicly should be double-checked for sensitive content.

Jay Lee

On Fri, Oct 17, 2025, 3:31 PM Ross Scroggs @.***> wrote:

taers232c left a comment (GAM-team/GAM#1839) https://github.com/GAM-team/GAM/issues/1839#issuecomment-3416834410

Is there anything more you want to do here ot should I release it?

Ross

— Reply to this email directly, view it on GitHub https://github.com/GAM-team/GAM/issues/1839#issuecomment-3416834410, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABDIZMCG5UXAPU33X3I2BXT3YE7Y5AVCNFSM6AAAAACHMRJWZ2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTIMJWHAZTINBRGA . You are receiving this because you authored the thread.Message ID: @.***>

jay0lee avatar Oct 17 '25 21:10 jay0lee