Skip to content

Commit 021bb03

Browse files
author
Nathan Gillett
committed
address Bugbot: fix OSV args and dedupe allowlist checks
Parse optional lockfiles without a brittle shift, share allowlist expiry validation in one script, and fix codeql allowlist empty-entry handling. Signed-off-by: Nathan Gillett <nathan@intentproof.io>
1 parent 3b5b58e commit 021bb03

4 files changed

Lines changed: 113 additions & 178 deletions

File tree

scripts/check-allowlist-expiry.sh

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#!/usr/bin/env bash
2+
# Validate allowlist YAML expiry dates (minimal parser, no PyYAML).
3+
# Usage: check-allowlist-expiry.sh [file] [id-field...]
4+
set -euo pipefail
5+
6+
ALLOWLIST_FILE="${1:-.github/codeql-allowlist.yml}"
7+
shift || true
8+
ID_FIELDS=("$@")
9+
if ((${#ID_FIELDS[@]} == 0)); then
10+
ID_FIELDS=(rule_id)
11+
fi
12+
13+
if [[ ! -f "$ALLOWLIST_FILE" ]]; then
14+
echo "No allowlist file at $ALLOWLIST_FILE; skipping expiry check."
15+
exit 0
16+
fi
17+
18+
if ! command -v python3 >/dev/null 2>&1; then
19+
echo "python3 is required to validate $ALLOWLIST_FILE" >&2
20+
exit 1
21+
fi
22+
23+
python3 - "$ALLOWLIST_FILE" "${ID_FIELDS[*]}" <<'PY'
24+
import datetime
25+
import re
26+
import sys
27+
28+
path = sys.argv[1]
29+
id_fields = sys.argv[2].split()
30+
patterns = {
31+
"rule_id": re.compile(r"rule_id:\s*(\S+)"),
32+
"cve_id": re.compile(r"cve_id:\s*(\S+)"),
33+
"id": re.compile(r"(?:^|\s)id:\s*(\S+)"),
34+
}
35+
36+
37+
def extract_id(text, anchored=False):
38+
for field in id_fields:
39+
pattern = patterns.get(field)
40+
if pattern is None:
41+
continue
42+
match = pattern.match(text) if anchored else pattern.search(text)
43+
if match:
44+
return match.group(1)
45+
return None
46+
47+
48+
text = open(path, encoding="utf-8").read()
49+
entries = []
50+
current = None
51+
for line in text.splitlines():
52+
stripped = line.strip()
53+
if stripped.startswith("- "):
54+
if current is not None:
55+
entries.append(current)
56+
current = {}
57+
item = stripped[2:].strip()
58+
entry_id = extract_id(item, anchored=False)
59+
if entry_id:
60+
current["id"] = entry_id
61+
match = re.search(r"expires:\s*(\S+)", item)
62+
if match:
63+
current["expires"] = match.group(1)
64+
continue
65+
if current is None:
66+
continue
67+
match = re.match(r"expires:\s*(\S+)", stripped)
68+
if match:
69+
current["expires"] = match.group(1)
70+
entry_id = extract_id(stripped, anchored=True)
71+
if entry_id:
72+
current["id"] = entry_id
73+
if current is not None:
74+
entries.append(current)
75+
76+
today = datetime.date.today()
77+
expired = []
78+
for idx, entry in enumerate(entries):
79+
expires_raw = entry.get("expires")
80+
if not expires_raw:
81+
print(
82+
f"{path}: allowlist[{idx}] missing expires date "
83+
"(required for security on-call approval model)",
84+
file=sys.stderr,
85+
)
86+
sys.exit(1)
87+
try:
88+
expires = datetime.date.fromisoformat(str(expires_raw))
89+
except ValueError:
90+
print(
91+
f"{path}: allowlist[{idx}] has invalid expires date: {expires_raw!r}",
92+
file=sys.stderr,
93+
)
94+
sys.exit(1)
95+
if expires < today:
96+
entry_id = entry.get("id", "<unknown>")
97+
expired.append(f"{entry_id} (expired {expires.isoformat()})")
98+
99+
if expired:
100+
print("Allowlist expired; contact security on-call to extend or remove:", file=sys.stderr)
101+
for item in expired:
102+
print(f" - {item}", file=sys.stderr)
103+
sys.exit(1)
104+
105+
print(f"PASS: {len(entries)} allowlist entries are current.")
106+
PY

scripts/check-codeql-allowlist.sh

Lines changed: 1 addition & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,3 @@
11
#!/usr/bin/env bash
22
# Validate .github/codeql-allowlist.yml expiry dates.
3-
# Expired entries fail with a clear message for security on-call follow-up.
4-
set -euo pipefail
5-
6-
ALLOWLIST_FILE="${1:-.github/codeql-allowlist.yml}"
7-
8-
if [[ ! -f "$ALLOWLIST_FILE" ]]; then
9-
echo "No allowlist file at $ALLOWLIST_FILE; skipping expiry check."
10-
exit 0
11-
fi
12-
13-
if ! command -v python3 >/dev/null 2>&1; then
14-
echo "python3 is required to validate $ALLOWLIST_FILE" >&2
15-
exit 1
16-
fi
17-
18-
python3 - "$ALLOWLIST_FILE" <<'PY'
19-
import datetime
20-
import re
21-
import sys
22-
23-
path = sys.argv[1]
24-
text = open(path, encoding="utf-8").read()
25-
26-
# Minimal parser for our allowlist schema (no PyYAML dependency).
27-
entries = []
28-
current = None
29-
for line in text.splitlines():
30-
stripped = line.strip()
31-
if stripped.startswith("- "):
32-
if current:
33-
entries.append(current)
34-
current = {}
35-
item = stripped[2:].strip()
36-
m = re.search(r"rule_id:\s*(\S+)", item)
37-
if m:
38-
current["rule_id"] = m.group(1)
39-
m = re.search(r"expires:\s*(\S+)", item)
40-
if m:
41-
current["expires"] = m.group(1)
42-
continue
43-
if current is None:
44-
continue
45-
m = re.match(r"expires:\s*(\S+)", stripped)
46-
if m:
47-
current["expires"] = m.group(1)
48-
m = re.match(r"rule_id:\s*(\S+)", stripped)
49-
if m:
50-
current["rule_id"] = m.group(1)
51-
if current:
52-
entries.append(current)
53-
54-
today = datetime.date.today()
55-
expired = []
56-
for idx, entry in enumerate(entries):
57-
expires_raw = entry.get("expires")
58-
if not expires_raw:
59-
print(
60-
f"{path}: allowlist[{idx}] missing expires date "
61-
"(required for security on-call approval model)",
62-
file=sys.stderr,
63-
)
64-
sys.exit(1)
65-
try:
66-
expires = datetime.date.fromisoformat(str(expires_raw))
67-
except ValueError:
68-
print(
69-
f"{path}: allowlist[{idx}] has invalid expires date: {expires_raw!r}",
70-
file=sys.stderr,
71-
)
72-
sys.exit(1)
73-
if expires < today:
74-
rule_id = entry.get("rule_id", "<unknown>")
75-
expired.append(f"{rule_id} (expired {expires.isoformat()})")
76-
77-
if expired:
78-
print("Allowlist expired; contact security on-call to extend or remove:", file=sys.stderr)
79-
for item in expired:
80-
print(f" - {item}", file=sys.stderr)
81-
sys.exit(1)
82-
83-
print(f"PASS: {len(entries)} allowlist entries are current.")
84-
PY
3+
exec "$(dirname "$0")/check-allowlist-expiry.sh" "${1:-.github/codeql-allowlist.yml}" rule_id

scripts/check-deps-allowlist.sh

Lines changed: 1 addition & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,3 @@
11
#!/usr/bin/env bash
22
# Validate .github/deps-allowlist.yml expiry dates.
3-
# Expired entries fail with a clear message for security on-call follow-up.
4-
set -euo pipefail
5-
6-
ALLOWLIST_FILE="${1:-.github/deps-allowlist.yml}"
7-
8-
if [[ ! -f "$ALLOWLIST_FILE" ]]; then
9-
echo "No allowlist file at $ALLOWLIST_FILE; skipping expiry check."
10-
exit 0
11-
fi
12-
13-
if ! command -v python3 >/dev/null 2>&1; then
14-
echo "python3 is required to validate $ALLOWLIST_FILE" >&2
15-
exit 1
16-
fi
17-
18-
python3 - "$ALLOWLIST_FILE" <<'PY'
19-
import datetime
20-
import re
21-
import sys
22-
23-
path = sys.argv[1]
24-
text = open(path, encoding="utf-8").read()
25-
26-
# Minimal parser for our allowlist schema (no PyYAML dependency).
27-
entries = []
28-
current = None
29-
for line in text.splitlines():
30-
stripped = line.strip()
31-
if stripped.startswith("- "):
32-
if current is not None:
33-
entries.append(current)
34-
current = {}
35-
item = stripped[2:].strip()
36-
m = re.search(r"(?:^|\s)id:\s*(\S+)", item)
37-
if m:
38-
current["id"] = m.group(1)
39-
m = re.search(r"rule_id:\s*(\S+)", item)
40-
if m:
41-
current["id"] = m.group(1)
42-
m = re.search(r"cve_id:\s*(\S+)", item)
43-
if m:
44-
current["id"] = m.group(1)
45-
m = re.search(r"expires:\s*(\S+)", item)
46-
if m:
47-
current["expires"] = m.group(1)
48-
continue
49-
if current is None:
50-
continue
51-
m = re.match(r"expires:\s*(\S+)", stripped)
52-
if m:
53-
current["expires"] = m.group(1)
54-
m = re.match(r"(?:^|\s)id:\s*(\S+)", stripped)
55-
if m:
56-
current["id"] = m.group(1)
57-
m = re.match(r"rule_id:\s*(\S+)", stripped)
58-
if m:
59-
current["id"] = m.group(1)
60-
m = re.match(r"cve_id:\s*(\S+)", stripped)
61-
if m:
62-
current["id"] = m.group(1)
63-
if current is not None:
64-
entries.append(current)
65-
66-
today = datetime.date.today()
67-
expired = []
68-
for idx, entry in enumerate(entries):
69-
expires_raw = entry.get("expires")
70-
if not expires_raw:
71-
print(
72-
f"{path}: allowlist[{idx}] missing expires date "
73-
"(required for security on-call approval model)",
74-
file=sys.stderr,
75-
)
76-
sys.exit(1)
77-
try:
78-
expires = datetime.date.fromisoformat(str(expires_raw))
79-
except ValueError:
80-
print(
81-
f"{path}: allowlist[{idx}] has invalid expires date: {expires_raw!r}",
82-
file=sys.stderr,
83-
)
84-
sys.exit(1)
85-
if expires < today:
86-
entry_id = entry.get("id", "<unknown>")
87-
expired.append(f"{entry_id} (expired {expires.isoformat()})")
88-
89-
if expired:
90-
print("Allowlist expired; contact security on-call to extend or remove:", file=sys.stderr)
91-
for item in expired:
92-
print(f" - {item}", file=sys.stderr)
93-
sys.exit(1)
94-
95-
print(f"PASS: {len(entries)} allowlist entries are current.")
96-
PY
3+
exec "$(dirname "$0")/check-allowlist-expiry.sh" "${1:-.github/deps-allowlist.yml}" rule_id cve_id id

scripts/run-osv-scanner-gate.sh

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ set -euo pipefail
55

66
ROOT="${1:-.}"
77
CONFIG="${2:-.osv-scanner.toml}"
8-
shift 2 2>/dev/null || true
9-
EXTRA_LOCKFILES=("$@")
8+
if (( $# > 2 )); then
9+
EXTRA_LOCKFILES=("${@:3}")
10+
else
11+
EXTRA_LOCKFILES=()
12+
fi
1013
OSV_VERSION="${OSV_SCANNER_VERSION:-v2.2.2}"
1114

1215
if ! command -v osv-scanner >/dev/null 2>&1; then

0 commit comments

Comments
 (0)