Fix the diff scanner that misses AWS keys

Review the AI's codeMedium20 min

Your task

An assistant generated a Go client that uploads backups to S3, with an AWS access key and secret pasted into the source. A reviewer skimming the diff missed them, so the team now runs a scanner on every diff before merge.

An assistant wrote scan_diff_for_secrets(diff_lines). It is in the editor. It has a bug. Find it and fix it.

Input and output:

  • diff_lines: the lines of a unified diff, in order. Added lines start with +, removed lines with -, unchanged lines with a space. The file header starts with +++.
  • Return a list of findings, each "<line number>:<rule>". Line numbers start at 1 and count every line of the input.

Rules the tests check:

  • Scan only added lines: lines that start with + but not with +++. Skip every other line. A removed key is already in git history, and the gate that matters is the one that stops new keys.
  • Check each scanned line against four rules, in this order. Report each rule at most once per line.
    1. aws_access_key_id: AKIA followed directly by 16 characters, each an uppercase letter A to Z or a digit. It counts anywhere in the line, even inside a longer word.
    2. aws_secret_access_key: a quoted string of exactly 40 characters, each an ASCII letter, a digit, /, + or =. Pair the line's double quotes left to right: the 1st with the 2nd, the 3rd with the 4th, and so on. Every " counts, even one after a backslash. A last quote with no partner is ignored.
    3. hardcoded_password: the first password= in the line (case matters) is followed by at least one character, and that character is not the space character. A tab, for example, still counts as a finding.
    4. discarded_error: the line contains , _ := or , _ =, the Go pattern that throws an error away.
  • List findings by line number, and within a line in the rule order above.

Examples:

  • For ["+++ b/uploader.go", "+ creds := credentials.NewStaticCredentialsProvider(", "+ \"AKIAIOSFODNN7EXAMPLE\",", "+ \"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\",", "+ cfg, _ := config.LoadDefaultConfig(context.TODO(),"], it returns ["3:aws_access_key_id", "4:aws_secret_access_key", "5:discarded_error"].
  • For ["- \"AKIAIOSFODNN7EXAMPLE\",", " some context", "+ // nothing to see here"], it returns []: the key is on a removed line.
  • For ["+ db, _ := sql.Open(dsn + \"password=hunter2\")"], it returns ["1:hardcoded_password", "1:discarded_error"].

Then, in a sentence or two: how would you catch this kind of bug in review?

Examples

scan_diff_for_secrets(diff_lines: list[str]) -> list[str]
Example 1
Inputscan_diff_for_secrets(["+++ b/uploader.go", "+ creds := credentials.NewStaticCredentialsProvider(", "+ \"AKIAIOSFODNN7EXAMPLE\",", "+ \"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\",", "+ cfg, _ := config.LoadDefaultConfig(context.TODO(),"])
Output["3:aws_access_key_id", "4:aws_secret_access_key", "5:discarded_error"]
Example 2
Inputscan_diff_for_secrets(["- \"AKIAIOSFODNN7EXAMPLE\",", " some context", "+ // nothing to see here"])
Output[]
Example 3
Inputscan_diff_for_secrets(["+ db, _ := sql.Open(dsn + \"password=hunter2\")"])
Output["1:hardcoded_password", "1:discarded_error"]