R-1303: every pin names its security-notice source (upstream.txt, # upstream: above each FROM); gate upstream + decoys. No runtime change.
gates / gates (push) Successful in 55s
gates / gates (push) Successful in 55s
This commit is contained in:
@@ -21,6 +21,8 @@ Gates, in order (all must pass; **non-zero exit on any failure**):
|
||||
… security-scan govulncheck (called vulnerabilities) + gitleaks on the pushed commits, WARN-FIRST: it
|
||||
lists, it never refuses (R-986; shared, felhom.eu/scripts/security_scan_gate.py). Fast
|
||||
although it reads vuln.go.dev: offline it says NOT CHECKED, so it cannot stop a push
|
||||
… upstream every infra.go pin and every Dockerfile FROM names where its security notices are
|
||||
published (R-1303; shared, felhom.eu/scripts/security_watch_inventory.py)
|
||||
… gate-decoys the decoy suite (test_gate_decoys.py): every gate above still convicts its
|
||||
decoys (R-1116). ~22 s and it edits real files in this tree for a moment, so
|
||||
the full run only, never --fast (never the hook, never CI)
|
||||
@@ -65,6 +67,8 @@ SHARED_INSTRUCTIONS = os.path.join(SHARED_DIR, "instructions_gate.py")
|
||||
SHARED_OBSERVATIONS = os.path.join(SHARED_DIR, "observations_gate.py")
|
||||
# R-986 — shared too: the dependency and secret scanner, warn-first.
|
||||
SHARED_SECURITY = os.path.join(SHARED_DIR, "security_scan_gate.py")
|
||||
# R-1303 — shared too: every pin names where its security notices are published (the nightly watch reads it).
|
||||
SHARED_UPSTREAM = os.path.join(SHARED_DIR, "security_watch_inventory.py")
|
||||
|
||||
# R-404 — the golden NOTICE. Lives here, beside the runner, because it is about THIS repo's
|
||||
# releases; it imports the felhom.eu gate rather than copying its comparison.
|
||||
@@ -114,6 +118,9 @@ GATES = [
|
||||
# although it reads vuln.go.dev: it cannot refuse, so a network blink is a NOT CHECKED line. ~8 s here. CI fetches
|
||||
# the pinned gitleaks (FELHOM_SCAN_FETCH=1) and has no Go, so govulncheck says NOT CHECKED there.
|
||||
("security-scan", SHARED_SECURITY, [REPO], True, True),
|
||||
# R-1303 (2026-10-26) — every infra.go pin (upstream.txt beside it) and every Dockerfile FROM / restic ARG (a
|
||||
# `# upstream:` comment directly above) names its notice source. Fast: stdlib file reads.
|
||||
("upstream", SHARED_UPSTREAM, ["--gate=controller", REPO], True, True),
|
||||
# R-404 — ADVISORY. Reports the golden debt where it is created; never refuses.
|
||||
("golden-notice", GOLDEN_NOTICE, [REPO], True, False),
|
||||
# R-1116 (2026-10-17) — the gates' OWN decoy suite: every gate above, red-proved against its decoys. It was
|
||||
|
||||
@@ -55,6 +55,10 @@ COVERS = {
|
||||
"second secret on another line of an accepted file still listed; a called govulncheck "
|
||||
"finding listed, an imported-only one not; no tool is NOT CHECKED out loud), run from here; "
|
||||
"plus the gate on THIS repo: exit 0 and its summary line (warn-first)"),
|
||||
"upstream": ("R-1303: a scratch controller tree - a NEW *Image const with no upstream.txt line, the line "
|
||||
"only in a COMMENT, a Dockerfile `# upstream:` comment one line too high (not directly above "
|
||||
"its FROM), a new FROM with none; controls: a FROM of an earlier STAGE needs no line, and the "
|
||||
"real repo passes"),
|
||||
"offbox-rename": "R-425: NAS branding in a NEW backups*.html, and in a bundle value an offbox Go file "
|
||||
"names; control: the same token in the network-storage feature's copy is accepted",
|
||||
"docker-v": "R-426: an unallowlisted `-v /etc:/x` in a NEW .go file two directories down "
|
||||
@@ -533,6 +537,56 @@ def security_cases():
|
||||
|
||||
security_cases()
|
||||
|
||||
|
||||
def upstream_cases():
|
||||
"""R-1303: the shared upstream rule (felhom.eu scripts/security_watch_inventory.py --gate=controller) on a SCRATCH
|
||||
controller tree, then on this repo."""
|
||||
global ran
|
||||
inv = os.path.join(SHARED, "security_watch_inventory.py")
|
||||
if not os.path.isfile(inv):
|
||||
fails.append("shared %s is MISSING beside this clone - a failure, never a skip" % inv)
|
||||
return
|
||||
GO = 'package infra\nconst (\n\tTraefikImage = "traefik:v3.7.13"\n\tFooImage = "foo/foo:1.0"\n)\n'
|
||||
TABLE = "# header\nTraefikImage github:traefik/traefik\nFooImage github:foo/foo\n"
|
||||
DOCKER = ("# upstream: osv:Go/stdlib\nFROM golang:1.27.3 AS builder\nRUN go build\n"
|
||||
"# upstream: gap:Debian fixes are DSAs the watch does not read\nFROM debian:13.7-slim\n"
|
||||
"COPY --from=builder /x /x\nFROM builder AS again\n")
|
||||
ws = tempfile.mkdtemp(prefix="ctrl-upstream-")
|
||||
try:
|
||||
def run(name, go, table, docker, expect, must):
|
||||
global ran
|
||||
root = os.path.join(ws, "repo")
|
||||
shutil.rmtree(root, ignore_errors=True)
|
||||
os.makedirs(os.path.join(root, "controller", "internal", "infra"))
|
||||
for rel, body in (("controller/internal/infra/infra.go", go), ("controller/internal/infra/upstream.txt", table),
|
||||
("controller/Dockerfile", docker)):
|
||||
io.open(os.path.join(root, rel), "w", encoding="utf-8").write(body)
|
||||
ran += 1
|
||||
rc, out = _run([sys.executable, inv, "--gate=controller", root], REPO)
|
||||
if rc != expect or must not in out:
|
||||
fails.append("upstream: %s: rc=%d (want %d), %r missing\n%s" % (name, rc, expect, must, out[-500:]))
|
||||
else:
|
||||
print(" ok upstream: %s" % name)
|
||||
run("GENUINE: every const and FROM named (a stage FROM needs none)", GO, TABLE, DOCKER, 0, "upstream gate OK")
|
||||
run("FACT: a new *Image const with no table line", GO.replace(")", '\tBarImage = "bar/bar:2.0"\n)'), TABLE, DOCKER,
|
||||
1, "BarImage")
|
||||
run("FACT: the table line only in a COMMENT", GO, TABLE.replace("FooImage ", "# FooImage "), DOCKER, 1, "FooImage")
|
||||
run("FACT: the upstream comment one line too high", GO, TABLE,
|
||||
DOCKER.replace("# upstream: osv:Go/stdlib\nFROM golang", "# upstream: osv:Go/stdlib\n# builder\nFROM golang"),
|
||||
1, "golang:1.27.3")
|
||||
run("FACT: a new FROM with no upstream comment", GO, TABLE, DOCKER + "FROM alpine:3.24.2\n", 1, "alpine:3.24.2")
|
||||
ran += 1
|
||||
rc, out = _run([sys.executable, inv, "--gate=controller", REPO], REPO)
|
||||
if rc != 0 or "upstream gate OK" not in out:
|
||||
fails.append("upstream: GENUINE: this repo: rc=%d\n%s" % (rc, out[-500:]))
|
||||
else:
|
||||
print(" ok upstream: GENUINE: this repo")
|
||||
finally:
|
||||
shutil.rmtree(ws, ignore_errors=True)
|
||||
|
||||
|
||||
upstream_cases()
|
||||
|
||||
print()
|
||||
if fails:
|
||||
for f in fails:
|
||||
|
||||
Reference in New Issue
Block a user